6 * Copyright (C) 1987 by the Massachusetts Institute of Technology
7 * For copying and distribution information, please see the file
13 static char *rcsid_qsupport_qc = "$Header$";
16 #include <mit-copyright.h>
18 #include "sms_server.h"
22 extern char *whoami, *strsave();
23 extern int ingres_errno, sms_errcode;
26 /* Specialized Access Routines */
28 /* access_user - verify that client name equals specified login name
30 * - since field validation routines are called first, a users_id is
31 * now in argv[0] instead of the login name.
34 access_user(q, argv, cl)
39 if (cl->users_id != *(int *)argv[0])
47 /* access_login - verify that client name equals specified login name
49 * argv[0...n] contain search info. q->
52 access_login(q, argv, cl)
60 build_qual(q->qual, q->argc, argv, qual);
61 ## range of u is users
62 ## retrieve (id = u.users_id) where qual
63 ## inquire_equel(rowcount = "rowcount")
64 if (rowcount != 1 || id != cl->users_id)
72 /* access_list - check access for most list operations
74 * Inputs: argv[0] - list_id
76 * argv[2] - member ID (only for queries "amtl" and "dmfl")
77 * argv[7] - group IID (only for query "ulis")
80 * - check that client is a member of the access control list
81 * - OR, if the query is add_member_to_list or delete_member_from_list
82 * and the list is public, allow access if client = member
85 access_list(q, argv, cl)
90 ## int list_id, acl_id, flags, rowcount, gid;
93 int client_id, status;
95 list_id = *(int *)argv[0];
96 ## repeat retrieve (acl_id = list.#acl_id, acl_type = list.#acl_type,
97 ## gid = list.#gid, flags = list.#public)
98 ## where list.#list_id = @list_id
99 ## inquire_equel(rowcount = "rowcount")
101 return(SMS_INTERNAL);
103 /* parse client structure */
104 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
107 /* if amtl or dmfl and list is public allow client to add or delete self */
108 if (((!strcmp("amtl", q->shortname) && flags) ||
109 (!strcmp("dmfl", q->shortname))) &&
110 (!strcmp("USER", argv[1]))) {
111 if (*(int *)argv[2] == client_id) return(SMS_SUCCESS);
112 /* if update_list, don't allow them to change the GID */
113 } else if (!strcmp("ulis", q->shortname)) {
114 if ((!strcmp(argv[7], UNIQUE_GID) && (gid != -1)) ||
115 (strcmp(argv[7], UNIQUE_GID) && (gid != atoi(argv[7]))))
119 /* check for client in access control list */
120 status = find_member(acl_type, acl_id, client_type, client_id, 0);
121 if (!status) return(SMS_PERM);
127 /* access_visible_list - allow access to list only if it is not hidden,
128 * or if the client is on the ACL
130 * Inputs: argv[0] - list_id
131 * cl - client identifier
134 access_visible_list(q, argv, cl)
139 ## int list_id, acl_id, flags, rowcount;
142 int client_id, status;
144 list_id = *(int *)argv[0];
145 ## repeat retrieve (flags = list.hidden, acl_id = list.#acl_id,
146 ## acl_type = list.#acl_type) where list.#list_id = @list_id
147 ## inquire_equel(rowcount = "rowcount")
149 return(SMS_INTERNAL);
154 /* parse client structure */
155 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
158 /* check for client in access control list */
159 status = find_member(acl_type, acl_id, client_type, client_id, 0);
167 /* access_vis_list_by_name - allow access to list only if it is not hidden,
168 * or if the client is on the ACL
170 * Inputs: argv[0] - list name
171 * cl - client identifier
174 access_vis_list_by_name(q, argv, cl)
179 ## int acl_id, flags, rowcount;
180 ## char acl_type[9], *listname;
182 int client_id, status;
185 ## repeat retrieve (flags = list.hidden, acl_id = list.#acl_id,
186 ## acl_type = list.#acl_type) where list.#name = @listname
187 ## inquire_equel(rowcount = "rowcount");
189 return(SMS_WILDCARD);
191 return(SMS_NO_MATCH);
195 /* parse client structure */
196 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
199 /* check for client in access control list */
200 status = find_member(acl_type, acl_id, client_type, client_id, 0);
208 /* access_member - allow user to access member of type "USER" and name matches
209 * username, or to access member of type "LIST" and list is one that user is
210 * on the acl of, or the list is visible.
213 access_member(q, argv, cl)
218 if (!strcmp(argv[0], "LIST") || !strcmp(argv[0], "RLIST"))
219 return(access_visible_list(q, &argv[1], cl));
221 if (!strcmp(argv[0], "USER") || !strcmp(argv[0], "RUSER")) {
222 if (cl->users_id == *(int *)argv[1])
230 /* access_qgli - special access routine for Qualified_get_lists. Allows
231 * access iff argv[0] == "TRUE" and argv[2] == "FALSE".
234 access_qgli(q, argv, cl)
239 if (!strcmp(argv[0], "TRUE") && !strcmp(argv[2], "FALSE"))
245 /* access_service - allow access if user is on ACL of service. Don't
246 * allow access if a wildcard is used.
249 access_service(q, argv, cl)
254 ## int acl_id, rowcount;
255 ## char *name, acl_type[9];
256 int client_id, status;
260 ## repeat retrieve (acl_id = servers.#acl_id, acl_type = servers.#acl_type)
261 ## where servers.#name = uppercase(@name)
262 ## inquire_equel(rowcount = "rowcount")
266 /* parse client structure */
267 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
270 /* check for client in access control list */
271 status = find_member(acl_type, acl_id, client_type, client_id, 0);
272 if (!status) return(SMS_PERM);
279 /* access_filesys - verify that client is owner or on owners list of filesystem
283 access_filesys(q, argv, cl)
288 ## int rowcount, users_id, list_id;
290 int status, client_id;
294 ## repeat retrieve (users_id = filesys.owner, list_id = filesys.owners)
295 ## where filesys.label = @name
296 ## inquire_equel(rowcount = "rowcount")
300 if (users_id == cl->users_id)
302 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
304 status = find_member("LIST", list_id, client_type, client_id, 0);
315 /* Setup routine for add_user
317 * Inputs: argv[0] - login
322 * - if argv[1] == UNIQUE_UID then set argv[1] = next(uid)
323 * - if argv[0] == UNIQUE_LOGIN then set argv[0] = "#<uid>"
326 setup_ausr(q, argv, cl)
328 register char *argv[];
331 ## int nuid, rowcount;
333 if (!strcmp(argv[1], UNIQUE_UID) || atoi(argv[1]) == -1) {
334 if (set_next_object_id("uid", "users"))
335 return(SMS_INGRES_ERR);
336 ## repeat retrieve (nuid = values.value) where values.name = "uid"
337 ## inquire_equel(rowcount = "rowcount")
339 return(SMS_INTERNAL);
340 sprintf(argv[1], "%d", nuid);
343 if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[1]) == -1) {
344 sprintf(argv[0], "#%s", argv[1]);
351 /* setup_dusr - verify that the user is no longer being referenced
352 * and may safely be deleted.
355 int setup_dusr(q, argv)
361 id = *(int *)argv[0];
363 /* For now, only allow users to be deleted if their status is 0 */
364 ## repeat retrieve (flag = u.status) where u.users_id = @id
365 if (flag != 0 && flag != 4)
368 ## repeat delete nfsquota where nfsquota.users_id = @id
369 ## repeat delete krbmap where krbmap.users_id = @id
370 ## repeat retrieve (flag = any(imembers.member_id where imembers.member_id=@id
371 ## and imembers.member_type = "USER"))
374 ## repeat retrieve (flag = any(filesys.label where filesys.owner=@id))
377 ## repeat retrieve (flag = any(list.name where list.acl_id=@id and
378 ## list.acl_type = "USER"))
381 ## repeat retrieve (flag = any(servers.name where servers.acl_id=@id and
382 ## servers.acl_type = "USER"))
385 ## repeat retrieve (flag=any(hostaccess.acl_id where hostaccess.acl_id=@id and
386 ## hostaccess.acl_type = "USER"))
395 /* setup_spop: verify that there is already a valid POP machine_id in the
396 * pop_id field. Also take care of keeping track of the post office usage.
398 int setup_spop(q, argv)
402 ## int id, mid, flag;
405 id = *(int *)argv[0];
406 ## repeat retrieve (type = u.potype, mid = u.pop_id,
407 ## flag = any(machine.name where machine.mach_id = u.pop_id
408 ## and u.pop_id != 0 and u.users_id = @id))
409 ## where u.users_id = @id
412 if (strcmp(strtrim(type), "POP"))
413 set_pop_usage(mid, 1);
418 /* setup_dpob: Take care of keeping track of the post office usage.
420 int setup_dpob(q, argv)
427 user = *(int *)argv[0];
428 ## repeat retrieve (type = u.potype, id = u.pop_id)
429 ## where u.users_id = @user
430 if (ingres_errno) return(sms_errcode);
432 if (!strcmp(strtrim(type), "POP"))
433 set_pop_usage(id, -1);
438 /* setup_dmac - verify that the machine is no longer being referenced
439 * and may safely be deleted.
442 int setup_dmac(q, argv)
448 id = *(int *)argv[0];
449 ## repeat retrieve (flag = any(users.login where users.potype = "POP"
450 ## and users.pop_id=@id))
453 ## repeat retrieve (flag = any(serverhosts.mach_id
454 ## where serverhosts.mach_id=@id))
457 ## repeat retrieve (flag = any(nfsphys.mach_id where nfsphys.mach_id=@id))
460 ## repeat retrieve (flag = any(hostaccess.mach_id where hostaccess.mach_id=@id))
463 ## repeat retrieve (flag = any(printcap.mach_id where printcap.mach_id=@id))
466 ## repeat retrieve (flag = any(palladium.mach_id where palladium.mach_id=@id))
470 ## repeat delete mcmap where mcmap.mach_id = @id
471 if (ingres_errno) return(sms_errcode);
476 /* setup_dclu - verify that the cluster is no longer being referenced
477 * and may safely be deleted.
480 int setup_dclu(q, argv)
486 id = *(int *)argv[0];
487 ## repeat retrieve (flag = any(mcmap.mach_id where mcmap.clu_id=@id))
490 ## repeat retrieve (flag = any(svc.clu_id where svc.clu_id=@id))
499 /* setup_alis - if argv[5] is non-zero and argv[6] is UNIQUE_ID, then allocate
500 * a new gid and put it in argv[6]. Otherwise if argv[6] is UNIQUE_ID but
501 * argv[5] is not, then remember that UNIQUE_ID is being stored by putting
502 * a -1 there. Remember that this is also used for ulis, with the indexes
506 int setup_alis(q, argv)
514 if (!strcmp(q->shortname, "alis"))
516 else if (!strcmp(q->shortname, "ulis"))
519 if (!strcmp(argv[idx], UNIQUE_GID) || atoi(argv[idx]) == -1) {
520 if (atoi(argv[idx - 1])) {
521 if (set_next_object_id("gid", "list"))
522 return(SMS_INGRES_ERR);
523 ## repeat retrieve (ngid = values.value) where values.name = "gid"
524 if (ingres_errno) return(sms_errcode);
525 sprintf(argv[idx], "%d", ngid);
527 strcpy(argv[idx], "-1");
535 /* setup_dlist - verify that the list is no longer being referenced
536 * and may safely be deleted.
539 int setup_dlis(q, argv)
545 id = *(int *)argv[0];
546 ## repeat retrieve (flag = any(imembers.member_id where imembers.member_id=@id
547 ## and imembers.member_type = "LIST"))
550 ## repeat retrieve (flag = any(imembers.member_id where imembers.list_id=@id))
553 ## repeat retrieve (flag = any(filesys.label where filesys.owners=@id))
556 ## repeat retrieve (flag = any(capacls.tag where capacls.list_id=@id))
559 ## repeat retrieve (flag = any(list.name where list.acl_id=@id and
560 ## list.acl_type = "LIST" and list.list_id != @id))
563 ## repeat retrieve (flag = any(servers.name where servers.acl_id=@id and
564 ## servers.acl_type = "LIST"))
567 ## repeat retrieve (flag=any(hostaccess.acl_id where hostaccess.acl_id=@id and
568 ## hostaccess.acl_type = "LIST"))
571 ## repeat retrieve (flag = any(zephyr.class
572 ## where zephyr.xmt_type = "LIST" and zephyr.xmt_id = @id or
573 ## zephyr.sub_type = "LIST" and zephyr.sub_id = @id or
574 ## zephyr.iws_type = "LIST" and zephyr.iws_id = @id or
575 ## zephyr.iui_type = "LIST" and zephyr.iui_id = @id))
584 /* setup_dsin - verify that the service is no longer being referenced
585 * and may safely be deleted.
588 int setup_dsin(q, argv)
596 ## repeat retrieve (flag = any(serverhosts.service
597 ## where serverhosts.service=uppercase(@name)))
600 ## repeat retrieve (flag = servers.inprogress) where servers.#name = @name
609 /* setup_dshi - verify that the service-host is no longer being referenced
610 * and may safely be deleted.
613 int setup_dshi(q, argv)
621 id = *(int *)argv[1];
622 ## repeat retrieve (flag=serverhosts.inprogress)
623 ## where serverhosts.service=uppercase(@name) and serverhosts.mach_id=@id
633 ** setup_add_filesys - verify existance of referenced file systems
645 ** * extract directory prefix from name
646 ** * verify mach_id/dir in nfsphys
647 ** * verify access in {r, w, R, W}
649 ** Side effect: sets variable var_phys_id to the ID of the physical
650 ** filesystem (nfsphys_id for NFS, 0 for RVD)
653 ** SMS_NFS - specified directory not exported
654 ** SMS_FILESYS_ACCESS - invalid filesys access
658 ##static int var_phys_id;
670 mach_id = *(int *)argv[2];
675 if (!strcmp(type, "NFS"))
676 return (check_nfs(mach_id, name, access));
682 /* Verify the arguments, depending on the FStype. Also, if this is an
683 * NFS filesystem, then update any quotas for that filesystem to reflect
692 char *type, *name, *access;
696 mach_id = *(int *)argv[3];
701 if (!strcmp(type, "NFS")) {
702 status = check_nfs(mach_id, name, access);
703 fid = *(int *)argv[0];
704 ## replace nfsquota (phys_id = var_phys_id) where nfsquota.filsys_id = fid
705 if (ingres_errno) return(sms_errcode);
712 /* Find the NFS physical partition that the named directory is on.
713 * This is done by comparing the dir against the mount point of the
714 * partition. To make sure we get the correct match when there is
715 * more than one, we sort the query in reverse order by dir name.
718 ##check_nfs(mach_id, name, access)
729 caccess = (isupper(*access)) ? tolower(*access) : *access;
730 if (caccess != 'r' && caccess != 'w') return(SMS_FILESYS_ACCESS);
733 ## range of np is nfsphys
734 ## repeat retrieve (var_phys_id = np.#nfsphys_id, dir = trim(np.#dir))
735 ## where np.#mach_id = @mach_id sort by #dir:d {
739 if (*cp1++ != *cp2) break;
743 status = SMS_SUCCESS;
753 /* setup_dfil: free any quota records and fsgroup info associated with
754 * a filesystem when it is deleted. Also adjust the allocation numbers.
757 setup_dfil(q, argv, cl)
764 id = *(int *)argv[0];
765 ## range of q is nfsquota
766 ## range of fs is filesys
767 ## range of n is nfsphys
768 ## repeat replace n (allocated=n.allocated-sum(q.quota where q.filsys_id=@id))
769 ## where n.nfsphys_id = fs.phys_id and fs.filsys_id = @id
771 ## repeat delete q where q.filsys_id = @id
772 ## repeat delete fsgroup where fsgroup.filsys_id = @id
773 ## repeat delete fsgroup where fsgroup.group_id = @id
774 if (ingres_errno) return(sms_errcode);
779 /* setup_dnfp: check to see that the nfs physical partition does not have
780 * any filesystems assigned to it before allowing it to be deleted.
783 setup_dnfp(q, argv, cl)
790 id = *(int *)argv[0];
791 ## repeat retrieve (exists = any(filesys.label where filesys.phys_id = @id))
800 /* setup_dnfq: Remove allocation from nfsphys before deleting quota.
801 * argv[0] = filsys_id
805 setup_dnfq(q, argv, cl)
810 ## int quota, fs, user;
812 fs = *(int *)argv[0];
813 user = *(int *)argv[1];
815 ## range of q is nfsquota
816 ## repeat retrieve (quota = q.#quota) where q.users_id = @user and
818 ## repeat replace nfsphys (allocated = nfsphys.allocated - @quota)
819 ## where nfsphys.nfsphys_id = filesys.#phys_id and filesys.filsys_id = @fs
820 if (ingres_errno) return(sms_errcode);
825 /* setup_sshi: don't exclusive lock the machine table during
826 * set_server_host_internal.
829 setup_sshi(q, argv, cl)
834 ## set lockmode session where readlock = system
838 /* setup add_kerberos_user_mapping: add the string to the string
839 * table if necessary.
842 setup_akum(q, argv, cl)
851 ## range of s is strings
852 ## repeat retrieve (id = s.string_id) where s.string = @name
853 ## inquire_equel (rowcount = "rowcount")
855 if (q->type != APPEND) return(SMS_STRING);
856 ## range of v is values
857 ## retrieve (id = v.value) where v.#name = "strings_id"
859 ## replace v (value = id) where v.#name = "strings_id"
860 ## append to strings (string_id = id, string = name)
862 if (ingres_errno) return(sms_errcode);
863 *(int *)argv[1] = id;
869 /* FOLLOWUP ROUTINES */
871 /* generic set_modtime routine. This takes the table name from the query,
872 * and will update the modtime, modby, and modwho fields in the entry in
873 * the table whose name field matches argv[0].
876 set_modtime(q, argv, cl)
881 ## char *name, *entity, *table;
889 ## replace table (modtime = "now", modby = who, modwith = entity)
890 ## where table.#name = name
894 /* generic set_modtime_by_id routine. This takes the table name from
895 * the query, and the id name from the validate record,
896 * and will update the modtime, modby, and modwho fields in the entry in
897 * the table whose id matches argv[0].
900 set_modtime_by_id(q, argv, cl)
905 ## char *entity, *table, *id_name;
911 id_name = q->validate->object_id;
913 id = *(int *)argv[0];
914 ## replace table (modtime = "now", modby = who, modwith = entity)
915 ## where table.id_name = id
920 /* Sets the finger modtime on a user record. The users_id will be in argv[0].
923 set_finger_modtime(q, argv, cl)
928 ## int users_id, who;
933 users_id = *(int *)argv[0];
935 ## repeat replace u (fmodtime = "now", fmodby = @who, fmodwith = @entity)
936 ## where u.#users_id = @users_id
941 /* Sets the pobox modtime on a user record. The users_id will be in argv[0].
944 set_pobox_modtime(q, argv, cl)
949 ## int users_id, who;
954 users_id = *(int *)argv[0];
956 ## repeat replace users (pmodtime = "now", pmodby = @who, pmodwith = @entity)
957 ## where users.#users_id = @users_id
962 /* Like set_modtime, but uppercases the name first.
965 set_uppercase_modtime(q, argv, cl)
970 ## char *name, *entity, *table;
978 ## replace table (modtime = "now", modby = who, modwith = entity)
979 ## where table.#name = uppercase(name)
984 /* Sets the modtime on the machine whose mach_id is in argv[0]. This routine
985 * is necessary for add_machine_to_cluster becuase the table that query
986 * operates on is "mcm", not "machine".
989 set_mach_modtime_by_id(q, argv, cl)
1000 id = *(int *)argv[0];
1001 ## range of m is machine
1002 ## repeat replace m (modtime = "now", modby = @who, modwith = @entity)
1003 ## where m.mach_id = @id
1004 return(SMS_SUCCESS);
1008 /* Sets the modtime on the cluster whose mach_id is in argv[0]. This routine
1009 * is necessary for add_cluster_data and delete_cluster_data becuase the
1010 * table that query operates on is "svc", not "cluster".
1013 set_cluster_modtime_by_id(q, argv, cl)
1021 entity = cl->entity;
1022 who = cl->client_id;
1024 id = *(int *)argv[0];
1025 ## range of c is cluster
1026 ## repeat replace c (modtime = "now", modby = @who, modwith = @entity)
1027 ## where c.clu_id = @id
1028 return(SMS_SUCCESS);
1032 /* sets the modtime on the serverhost where the service name is in argv[0]
1033 * and the mach_id is in argv[1].
1036 set_serverhost_modtime(q, argv, cl)
1041 ## char *entity, *serv;
1044 entity = cl->entity;
1045 who = cl->client_id;
1048 id = *(int *)argv[1];
1049 ## repeat replace sh (modtime = "now", modby = @who, modwith = @entity)
1050 ## where sh.service = uppercase(@serv) and sh.mach_id = @id
1051 return(SMS_SUCCESS);
1055 /* sets the modtime on the nfsphys where the mach_id is in argv[0] and the
1056 * directory name is in argv[1].
1059 set_nfsphys_modtime(q, argv, cl)
1064 ## char *entity, *dir;
1067 entity = cl->entity;
1068 who = cl->client_id;
1070 id = *(int *)argv[0];
1072 ## repeat replace np (modtime = "now", modby = @who, modwith = @entity)
1073 ## where np.#dir = @dir and np.mach_id = @id
1074 return(SMS_SUCCESS);
1078 /* sets the modtime on a filesystem, where argv[0] contains the filesys
1082 set_filesys_modtime(q, argv, cl)
1087 ## char *label, *entity;
1090 entity = cl->entity;
1091 who = cl->client_id;
1094 if (!strcmp(q->shortname, "ufil"))
1097 ## repeat replace fs (modtime = "now", modby = @who, modwith = @entity,
1098 ## #phys_id = @var_phys_id) where fs.#label = @label
1099 return(SMS_SUCCESS);
1103 /* sets the modtime on a zephyr class, where argv[0] contains the class
1107 set_zephyr_modtime(q, argv, cl)
1112 ## char *class, *entity;
1115 entity = cl->entity;
1116 who = cl->client_id;
1120 ## repeat replace z (modtime = "now", modby = @who, modwith = @entity)
1121 ## where z.#class = @class
1122 return(SMS_SUCCESS);
1126 /* fixes the modby field. This will be the second to last thing in the
1127 * argv, the argv length is determined from the query structure. It is
1128 * passed as a pointer to an integer. This will either turn it into a
1129 * username, or # + the users_id.
1131 followup_fix_modby(q, sq, v, action, actarg, cl)
1133 register struct save_queue *sq;
1135 register int (*action)();
1136 register int actarg;
1140 char **argv, *malloc();
1141 ## int id, rowcount;
1145 while (sq_get_data(sq, &argv)) {
1148 argv[i] = malloc(256);
1151 ## repeat retrieve (name = users.login) where users.users_id = @id
1154 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1157 ## inquire_equel(rowcount = "rowcount")
1158 if (rowcount != 1) {
1159 sprintf(argv[i], "#%d", id);
1161 (*action)(q->vcnt, argv, actarg);
1162 for (j = 0; j < q->vcnt; j++)
1167 if (ingres_errno) return(sms_errcode);
1168 return(SMS_SUCCESS);
1173 ** followup_ausr - add finger and pobox entries, set_user_modtime
1176 ** argv[0] - login (add_user)
1177 ** argv[3] - last name
1178 ** argv[4] - first name
1179 ** argv[5] - middle name
1183 followup_ausr(q, argv, cl)
1189 ## char *login, *entity;
1190 ## char fullname[129];
1193 who = cl->client_id;
1194 entity = cl->entity;
1196 /* build fullname */
1197 if (strlen(argv[4]) && strlen(argv[5]))
1198 sprintf(fullname, "%s %s %s", argv[4], argv[5], argv[3]);
1199 else if (strlen(argv[4]))
1200 sprintf(fullname, "%s %s", argv[4], argv[3]);
1202 sprintf(fullname, "%s", argv[3]);
1204 /* create finger entry, pobox & set modtime on user */
1205 ## repeat replace u (modtime = "now", modby=@who, modwith=@entity,
1206 ## #fullname=@fullname, mit_affil = u.mit_year,
1207 ## fmodtime="now", fmodby=@who, fmodwith=@entity,
1208 ## potype="NONE", pmodtime="now", pmodby=@who, pmodwith=@entity)
1209 ## where u.#login = @login
1211 return(SMS_SUCCESS);
1215 /* followup_gpob: fixes argv[2] based on the IDs currently there and the
1216 * type in argv[1]. Then completes the upcall to the user.
1218 * argv[2] is of the form "123:234" where the first integer is the machine
1219 * ID if it is a pop box, and the second is the string ID if it is an SMTP
1220 * box. argv[1] should be "POP", "SMTP", or "NONE". Boxes of type NONE
1224 followup_gpob(q, sq, v, action, actarg, cl)
1225 register struct query *q;
1226 register struct save_queue *sq;
1227 register struct validate *v;
1228 register int (*action)();
1232 char **argv, *index();
1234 ## char box[129], *name;
1235 ## int mid, sid, rowcount;
1238 while (sq_get_data(sq, &argv)) {
1239 sms_trim_args(2, argv);
1241 p = index(argv[2], ':');
1243 mid = atoi(argv[2]);
1247 if (!strcmp(ptype, "POP")) {
1248 ## repeat retrieve (box=machine.#name) where machine.mach_id=@mid
1249 ## inquire_equel(rowcount = "rowcount")
1251 return(SMS_MACHINE);
1252 } else if (!strcmp(ptype, "SMTP")) {
1253 ## repeat retrieve (box=strings.string) where strings.string_id=@sid
1254 ## inquire_equel(rowcount = "rowcount")
1257 } else /* ptype == "NONE" */ {
1261 if (!strcmp(q->shortname, "gpob")) {
1262 sid = atoi(argv[4]);
1264 argv[4] = malloc(256);
1267 ## repeat retrieve (name = users.login) where users.users_id = @sid
1270 ## repeat retrieve (name = strings.string)
1271 ## where strings.string_id = @sid
1274 ## inquire_equel(rowcount = "rowcount")
1276 sprintf(name, "#%d", sid);
1280 (*action)(q->vcnt, argv, actarg);
1282 /* free saved data */
1290 return (SMS_SUCCESS);
1294 /* followup_glin: fix the ace_name in argv[8]. argv[7] will contain the
1295 * ace_type: "LIST", "USER", or "NONE". Decode the id in argv[8] into the
1296 * proper name based on the type, and repace that string in the argv.
1297 * Also fixes the modby field by called followup_fix_modby.
1300 followup_glin(q, sq, v, action, actarg, cl)
1301 register struct query *q;
1302 register struct save_queue *sq;
1303 register struct validate *v;
1304 register int (*action)();
1308 char **argv, *malloc(), *realloc(), *type;
1310 ## int id, rowcount;
1314 if (!strcmp(q->shortname, "gsin"))
1317 while (sq_get_data(sq, &argv)) {
1318 sms_trim_args(q->vcnt, argv);
1320 id = atoi(argv[i = q->vcnt - 2]);
1322 name = argv[i] = malloc(256);
1324 ## repeat retrieve (name = users.login) where users.users_id = @id
1327 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1330 ## inquire_equel(rowcount = "rowcount")
1332 sprintf(argv[i], "#%d", id);
1334 id = atoi(argv[idx]);
1335 type = argv[idx - 1];
1336 if ((name = malloc(33)) == NULL)
1339 if (!strcmp(type, "LIST")) {
1340 ## repeat retrieve (name = list.#name) where list.list_id = @id
1341 ## inquire_equel(rowcount = "rowcount")
1343 strcpy(name, "???");
1344 } else if (!strcmp(type, "USER")) {
1345 ## repeat retrieve (name = users.login) where users.users_id = @id
1346 ## inquire_equel(rowcount = "rowcount")
1348 strcpy(name, "???");
1349 } else if (!strcmp(type, "KERBEROS")) {
1350 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1351 ## inquire_equel(rowcount = "rowcount")
1353 strcpy(name, "???");
1354 } else if (!strcmp(type, "NONE")) {
1355 strcpy(name, "NONE");
1357 strcpy(name, "???");
1361 if (!strcmp(q->shortname, "glin") && atoi(argv[6]) == -1) {
1362 argv[6] = realloc(argv[6], strlen(UNIQUE_GID) + 1);
1363 strcpy(argv[6], UNIQUE_GID);
1367 (*action)(q->vcnt, argv, actarg);
1369 /* free saved data */
1370 for (i = 0; i < q->vcnt; i++)
1376 return (SMS_SUCCESS);
1380 /** followup_amtl - followup for amtl and dmfl; when adding a list
1381 ** member to a maillist, make member list a maillist also
1382 ** unless list is a user-group.
1383 ** Then set_list_modtime_by_id.
1386 ** argv[0] - list_id
1387 ** argv[1] - member_type
1388 ** argv[2] - member_id
1392 followup_amtl(q, argv, cl)
1402 list_id = *(int *)argv[0];
1403 entity = cl->entity;
1404 who = cl->client_id;
1406 ## range of l is list
1407 ## repeat replace l (modtime = "now", modby = @who, modwith = @entity)
1408 ## where l.#list_id = @list_id
1410 /* if query is not amtl or if member_type is not LIST then return */
1411 if (bcmp(q->shortname, "amtl", 4) || bcmp(argv[1], "LIST", 4))
1412 return(SMS_SUCCESS);
1414 member_id = *(int *)argv[2];
1416 /* is parent list a mailing list? */
1417 ## repeat retrieve (exists = l.maillist) where l.#list_id=@list_id
1419 return(SMS_SUCCESS);
1421 /* list is not a user-group; add list to maillist table */
1422 ## repeat replace l (maillist = 1) where l.#list_id = @member_id
1423 return(SMS_SUCCESS);
1427 /* followup_gnfq: Fix the directory name & modby fields
1428 * argv[0] = filsys_id
1429 * argv[2] = ascii(quota)
1432 followup_gnfq(q, sq, v, action, actarg, cl)
1434 register struct save_queue *sq;
1436 register int (*action)();
1437 register int actarg;
1441 char **argv, *malloc();
1442 ## int id, rowcount;
1443 ## char *name, *label;
1445 while (sq_get_data(sq, &argv)) {
1448 argv[3] = malloc(256);
1452 ## repeat retrieve (name = filesys.#name) where filesys.#label = @label
1454 ## repeat retrieve (name = nfsphys.dir) where nfsphys.nfsphys_id = @id
1456 ## inquire_equel(rowcount = "rowcount")
1457 if (rowcount != 1) {
1458 sprintf(argv[3], "#%d", id);
1463 argv[6] = malloc(256);
1466 ## repeat retrieve (name = users.login) where users.users_id = @id
1469 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1472 ## inquire_equel(rowcount = "rowcount")
1473 if (rowcount != 1) {
1474 sprintf(argv[6], "#%d", id);
1476 (*action)(q->vcnt, argv, actarg);
1477 for (j = 0; j < q->vcnt; j++)
1482 return(SMS_SUCCESS);
1486 /* followup_anfq: Add allocation to nfsphys after creating quota.
1487 * argv[0] = filsys_id
1488 * argv[2] = ascii(quota)
1491 followup_anfq(q, argv, cl)
1496 ## int quota, user, fs, who;
1499 fs = *(int *)argv[0];
1500 user = *(int *)argv[1];
1501 quota = atoi(argv[2]);
1502 who = cl->client_id;
1503 entity = cl->entity;
1505 ## repeat replace nq (modtime = "now", modby = @who, modwith = @entity)
1506 ## where nq.filsys_id = @fs and nq.users_id = @user
1507 ## repeat replace nfsphys (allocated = nfsphys.allocated + @quota)
1508 ## where nfsphys.nfsphys_id = filesys.#phys_id and filesys.filsys_id = @fs
1509 if (ingres_errno) return(sms_errcode);
1510 return(SMS_SUCCESS);
1517 followup_gzcl(q, sq, v, action, actarg, cl)
1518 register struct query *q;
1519 register struct save_queue *sq;
1520 register struct validate *v;
1521 register int (*action)();
1526 ## int rowcount, id;
1530 while (sq_get_data(sq, &argv)) {
1531 sms_trim_args(q->vcnt, argv);
1533 id = atoi(argv[i = q->vcnt - 2]);
1535 name = argv[i] = malloc(256);
1537 ## repeat retrieve (name = users.login) where users.users_id = @id
1540 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1543 ## inquire_equel(rowcount = "rowcount")
1545 sprintf(argv[i], "#%d", id);
1547 for (i = 1; i < 8; i+=2) {
1548 id = atoi(argv[i+1]);
1550 if ((name = argv[i+1] = malloc(33)) == NULL)
1552 if (!strcmp(argv[i], "LIST")) {
1553 ## repeat retrieve (name = list.#name) where list.list_id = @id
1554 ## inquire_equel(rowcount = "rowcount")
1556 strcpy(name, "???");
1557 } else if (!strcmp(argv[i], "USER")) {
1558 ## repeat retrieve (name = users.login) where users.users_id = @id
1559 ## inquire_equel(rowcount = "rowcount")
1561 strcpy(name, "???");
1562 } else if (!strcmp(argv[i], "KERBEROS")) {
1563 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1564 ## inquire_equel(rowcount = "rowcount")
1566 strcpy(name, "???");
1567 } else if (!strcmp(argv[i], "NONE")) {
1568 strcpy(name, "NONE");
1570 strcpy(name, "???");
1575 (*action)(q->vcnt, argv, actarg);
1577 /* free saved data */
1578 for (i = 0; i < q->vcnt; i++)
1583 return(SMS_SUCCESS);
1590 followup_gsha(q, sq, v, action, actarg, cl)
1591 register struct query *q;
1592 register struct save_queue *sq;
1593 register struct validate *v;
1594 register int (*action)();
1599 ## int rowcount, id;
1603 while (sq_get_data(sq, &argv)) {
1604 sms_trim_args(q->vcnt, argv);
1608 name = argv[4] = malloc(256);
1610 ## repeat retrieve (name = users.login) where users.users_id = @id
1613 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1616 ## inquire_equel(rowcount = "rowcount")
1618 sprintf(argv[4], "#%d", id);
1622 if ((name = argv[2] = malloc(33)) == NULL)
1624 if (!strcmp(argv[1], "LIST")) {
1625 ## repeat retrieve (name = list.#name) where list.list_id = @id
1626 ## inquire_equel(rowcount = "rowcount")
1628 strcpy(name, "???");
1629 } else if (!strcmp(argv[1], "USER")) {
1630 ## repeat retrieve (name = users.login) where users.users_id = @id
1631 ## inquire_equel(rowcount = "rowcount")
1633 strcpy(name, "???");
1634 } else if (!strcmp(argv[1], "KERBEROS")) {
1635 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1636 ## inquire_equel(rowcount = "rowcount")
1638 strcpy(name, "???");
1639 } else if (!strcmp(argv[1], "NONE")) {
1640 strcpy(name, "NONE");
1642 strcpy(name, "???");
1646 (*action)(q->vcnt, argv, actarg);
1648 /* free saved data */
1649 for (i = 0; i < q->vcnt; i++)
1654 return(SMS_SUCCESS);
1659 /* Special query routines */
1661 /* set_pobox - this does all of the real work.
1662 * argv = user_id, type, box
1663 * if type is POP, then box should be a machine, and its ID should be put in
1664 * pop_id. If type is SMTP, then box should be a string and its ID should
1665 * be put in box_id. If type is NONE, then box doesn't matter.
1668 int set_pobox(q, argv, cl)
1673 ## int user, id, rowcount;
1674 ## char *box, potype[9];
1677 user = *(int *)argv[0];
1679 ## repeat retrieve (id = users.pop_id, potype = users.#potype)
1680 ## where users.users_id = @user
1681 if (ingres_errno) return(sms_errcode);
1682 if (!strcmp(strtrim(potype), "POP"))
1683 set_pop_usage(id, -1);
1685 if (!strcmp(argv[1], "POP")) {
1686 ## repeat retrieve (id=machine.mach_id) where machine.name=uppercase(@box)
1687 ## inquire_equel(rowcount = "rowcount")
1689 return(SMS_MACHINE);
1690 ## repeat replace users (#potype = "POP", pop_id = @id)
1691 ## where users.users_id = @user
1692 set_pop_usage(id, 1);
1693 } else if (!strcmp(argv[1], "SMTP")) {
1694 if (index(box, '/') || index(box, '|'))
1695 return(SMS_BAD_CHAR);
1696 ## range of s is strings
1697 ## repeat retrieve (id = s.string_id) where s.string = @box
1698 ## inquire_equel (rowcount = "rowcount")
1699 if (rowcount == 0) {
1700 ## range of v is values
1701 ## repeat retrieve (id = v.value) where v.name = "strings_id"
1703 ## repeat replace v (value = @id) where v.name = "strings_id"
1704 ## append to strings (string_id = id, string = box)
1706 ## repeat replace users (#potype = "SMTP", box_id = @id)
1707 ## where users.users_id = @user
1708 } else /* argv[1] == "NONE" */ {
1709 ## repeat replace users (#potype = "NONE") where users.users_id = @user
1712 set_pobox_modtime(q, argv, cl);
1713 ## repeat replace tblstats (updates = tblstats.updates + 1, modtime = "now")
1714 ## where tblstats.#table = "users"
1715 if (ingres_errno) return(sms_errcode);
1716 return(SMS_SUCCESS);
1720 /* get_list_info: passed a wildcard list name, returns lots of stuff about
1721 * each list. This is tricky: first build a queue of all requested
1722 * data. Rest of processing consists of fixing gid, ace_name, and modby.
1725 get_list_info(q, aargv, cl, action, actarg)
1726 register struct query *q;
1729 register int (*action)();
1732 char *argv[13], *malloc(), *realloc();
1733 ## char *name, acl_type[9], listname[33], active[5], public[5], hidden[5];
1734 ## char maillist[5], group[5], gid[6], acl_name[33], desc[256], modtime[27];
1735 ## char modby[256], modwith[9];
1736 ## int id, rowcount, acl_id, hid, modby_id;
1738 struct save_queue *sq, *sq_create();
1740 returned = rowcount = 0;
1744 ## range of l is list
1745 ## repeat retrieve (id = l.list_id) where l.#name = @name {
1746 sq_save_data(sq, id);
1749 if (ingres_errno) return(sms_errcode);
1751 return(SMS_NO_MATCH);
1753 argv[0] = listname; argv[1] = active; argv[2] = public; argv[3] = hidden;
1754 argv[4] = maillist; argv[5] = group; argv[6] = gid; argv[7] = acl_type;
1755 argv[8] = acl_name; argv[9] = desc; argv[10] = modtime; argv[11] = modby;
1758 while (sq_get_data(sq, &id)) {
1762 ## repeat retrieve (listname = l.#name, active = text(l.#active),
1763 ## public = text(l.#public), hidden = text(l.#hidden),
1764 ## hid = l.#hidden, maillist = text(l.#maillist),
1765 ## group = text(l.#group), gid = text(l.#gid),
1766 ## acl_type = trim(l.#acl_type), acl_id = l.#acl_id,
1767 ## desc = l.#desc, modtime = l.#modtime, modby_id = l.#modby,
1768 ## modwith =l.#modwith)
1769 ## where l.list_id = @id
1770 if (ingres_errno) return(sms_errcode);
1772 if (atoi(gid) == -1)
1773 argv[6] = UNIQUE_GID;
1775 if (!strcmp(acl_type, "LIST")) {
1776 ## repeat retrieve (acl_name = l.#name) where l.list_id = @acl_id
1777 ## inquire_equel(rowcount = "rowcount")
1779 strcpy(acl_name, "???");
1780 } else if (!strcmp(acl_type, "USER")) {
1781 ## repeat retrieve (acl_name = users.#login)
1782 ## where users.users_id = @acl_id
1783 ## inquire_equel(rowcount = "rowcount")
1785 strcpy(acl_name, "???");
1786 } else if (!strcmp(acl_type, "KERBEROS")) {
1787 ## repeat retrieve (acl_name = strings.string)
1788 ## where strings.string_id = @acl_id
1789 ## inquire_equel(rowcount = "rowcount")
1791 strcpy(acl_name, "???");
1792 } else if (!strcmp(acl_type, "NONE")) {
1793 strcpy(acl_name, "NONE");
1795 strcpy(acl_name, "???");
1798 ## repeat retrieve (modby = users.login) where users.users_id = @modby_id
1800 modby_id = -modby_id;
1801 ## repeat retrieve (modby = strings.string)
1802 ## where strings.string_id = @modby_id
1803 modby_id = -modby_id;
1805 ## inquire_equel(rowcount = "rowcount")
1807 sprintf(modby, "#%d", modby_id);
1808 if (ingres_errno) return(sms_errcode);
1810 sms_trim_args(q->vcnt, argv);
1812 (*action)(q->vcnt, argv, actarg);
1816 if (ingres_errno) return(sms_errcode);
1817 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
1818 ## where tblstats.#table = "list"
1820 return (SMS_SUCCESS);
1824 /* Add_member_to_list: do list flattening as we go! MAXLISTDEPTH is
1825 * how many different ancestors a member is allowed to have.
1828 #define MAXLISTDEPTH 100
1830 int add_member_to_list(q, argv, cl)
1835 ## int id, lid, mid, exists, error;
1836 ## char *mtype, dtype[9], buf[256];
1837 int ancestors[MAXLISTDEPTH], acount, a;
1838 int descendants[MAXLISTDEPTH], dcount, d;
1839 char *dtypes[MAXLISTDEPTH];
1842 ## range of m is imembers
1843 lid = *(int *)argv[0];
1845 mid = *(int *)argv[2];
1846 ## repeat retrieve (exists = any(m.list_id where m.list_id=@lid and
1847 ## m.member_id = @mid and m.member_type = @mtype
1848 ## and m.direct = 1))
1851 if (!strcasecmp(mtype, "STRING")) {
1852 ## repeat retrieve (buf = strings.string) where strings.string_id = @mid
1853 if (index(buf, '/') || index(buf, '|'))
1854 return(SMS_BAD_CHAR);
1859 ## repeat retrieve (id = m.list_id)
1860 ## where m.member_id = @lid and m.member_type = "LIST" {
1861 ancestors[acount++] = id;
1862 if (acount >= MAXLISTDEPTH) {
1866 if (ingres_errno) return(sms_errcode);
1867 if (acount >= MAXLISTDEPTH) {
1868 return(SMS_INTERNAL);
1870 descendants[0] = mid;
1874 if (!strcmp(mtype, "LIST")) {
1875 ## repeat retrieve (id = m.member_id, dtype = m.member_type)
1876 ## where m.list_id = @mid {
1879 dtypes[dcount] = "LIST";
1882 dtypes[dcount] = "USER";
1885 dtypes[dcount] = "STRING";
1888 dtypes[dcount] = "KERBEROS";
1894 descendants[dcount++] = id;
1895 if (dcount >= MAXLISTDEPTH) {
1900 if (ingres_errno) return(sms_errcode);
1902 return(SMS_INTERNAL);
1904 for (a = 0; a < acount; a++) {
1906 for (d = 0; d < dcount; d++) {
1907 mid = descendants[d];
1909 if (mid == lid && !strcmp(mtype, "LIST")) {
1910 return(SMS_LISTLOOP);
1912 ## repeat retrieve (exists = any(m.ref_count where m.list_id = @lid
1913 ## and m.member_id = @mid
1914 ## and m.member_type = @mtype))
1916 if (a == 0 && d == 0)
1917 ## replace m (ref_count = m.ref_count+1, direct = 1)
1918 ## where m.list_id = lid and m.member_id = mid and
1919 ## m.member_type = mtype
1921 ## replace m (ref_count = m.ref_count+1)
1922 ## where m.list_id = lid and m.member_id = mid and
1923 ## m.member_type = mtype
1925 incremental_clear_before();
1926 if (a == 0 && d == 0)
1927 ## append imembers (list_id=lid, member_id = mid, direct = 1,
1928 ## member_type=mtype, ref_count = 1)
1930 ## append imembers (list_id=lid, member_id = mid,
1931 ## member_type=mtype, ref_count = 1)
1932 iargv[0] = (char *)lid;
1934 iargv[2] = (char *)mid;
1935 incremental_after("members", 0, iargv);
1939 if (ingres_errno) return(sms_errcode);
1940 return(SMS_SUCCESS);
1944 /* Delete_member_from_list: do list flattening as we go!
1947 int delete_member_from_list(q, argv, cl)
1952 ## int id, lid, mid, cnt, exists, error;
1953 ## char *mtype, dtype[9];
1954 int ancestors[MAXLISTDEPTH], acount, a;
1955 int descendants[MAXLISTDEPTH], dcount, d;
1956 char *dtypes[MAXLISTDEPTH];
1959 ## range of m is imembers
1960 lid = *(int *)argv[0];
1962 mid = *(int *)argv[2];
1963 ## repeat retrieve (exists = any(m.list_id where m.list_id=@lid and
1964 ## m.member_id = @mid and m.member_type = @mtype
1965 ## and m.direct = 1))
1966 if (ingres_errno) return(sms_errcode);
1968 return(SMS_NO_MATCH);
1971 ## repeat retrieve (id = m.list_id)
1972 ## where m.member_id = @lid and m.member_type = "LIST" {
1973 ancestors[acount++] = id;
1974 if (acount >= MAXLISTDEPTH)
1977 if (ingres_errno) return(sms_errcode);
1978 if (acount >= MAXLISTDEPTH)
1979 return(SMS_INTERNAL);
1980 descendants[0] = mid;
1984 if (!strcmp(mtype, "LIST")) {
1985 ## repeat retrieve (id = m.member_id, dtype = m.member_type)
1986 ## where m.list_id = @mid {
1989 dtypes[dcount] = "LIST";
1992 dtypes[dcount] = "USER";
1995 dtypes[dcount] = "STRING";
1998 dtypes[dcount] = "KERBEROS";
2004 descendants[dcount++] = id;
2005 if (dcount >= MAXLISTDEPTH)
2008 if (ingres_errno) return(sms_errcode);
2010 return(SMS_INTERNAL);
2012 for (a = 0; a < acount; a++) {
2014 for (d = 0; d < dcount; d++) {
2015 mid = descendants[d];
2017 if (mid == lid && !strcmp(mtype, "LIST")) {
2018 return(SMS_LISTLOOP);
2020 ## repeat retrieve (cnt = m.ref_count)
2021 ## where m.list_id = @lid and m.member_id = @mid
2022 ## and m.member_type = @mtype
2024 iargv[0] = (char *)lid;
2026 iargv[2] = (char *)mid;
2027 incremental_before("members", 0, iargv);
2028 ## delete m where m.list_id = lid and m.member_id = mid and
2029 ## m.member_type = mtype
2030 incremental_clear_after();
2031 } else if (a == 0 && d == 0) {
2032 ## replace m (ref_count = m.ref_count-1, direct = 0)
2033 ## where m.list_id = lid and m.member_id = mid and
2034 ## m.member_type = mtype
2036 ## replace m (ref_count = m.ref_count-1)
2037 ## where m.list_id = lid and m.member_id = mid and
2038 ## m.member_type = mtype
2042 if (ingres_errno) return(sms_errcode);
2043 return(SMS_SUCCESS);
2047 /* get_ace_use - given a type and a name, return a type and a name.
2048 * The ace_type is one of "LIST", "USER", "RLIST", or "RUSER" in argv[0],
2049 * and argv[1] will contain the ID of the entity in question. The R*
2050 * types mean to recursively look at every containing list, not just
2051 * when the object in question is a direct member. On return, the
2052 * usage type will be one of LIST, SERVICE, FILESYS, QUOTA, QUERY, or ZEPHYR.
2055 int get_ace_use(q, argv, cl, action, actarg)
2064 ## int aid, listid, id;
2065 struct save_queue *sq, *sq_create();
2067 ## range of m is imembers
2069 aid = *(int *)argv[1];
2070 if (!strcmp(atype, "LIST") || !strcmp(atype, "USER") ||
2071 !strcmp(atype, "KERBEROS")) {
2072 return(get_ace_internal(atype, aid, action, actarg));
2076 if (!strcmp(atype, "RLIST")) {
2077 sq_save_data(sq, aid);
2078 /* get all the list_id's of containing lists */
2079 ## range of m is imembers
2080 ## repeat retrieve (listid = m.list_id)
2081 ## where m.member_type = "LIST" and m.member_id = @id {
2082 sq_save_unique_data(sq, listid);
2084 /* now process each one */
2085 while (sq_get_data(sq, &id)) {
2086 if (get_ace_internal("LIST", id, action, actarg) == SMS_SUCCESS)
2091 if (!strcmp(atype, "RUSER")) {
2092 ## repeat retrieve (listid = m.list_id)
2093 ## where m.member_type = "USER" and m.member_id = @aid {
2094 sq_save_data(sq, listid);
2096 /* now process each one */
2097 while (sq_get_data(sq, &id)) {
2098 if (get_ace_internal("LIST", id, action, actarg) == SMS_SUCCESS)
2101 if (get_ace_internal("USER", aid, action, actarg) == SMS_SUCCESS)
2105 if (!strcmp(atype, "RKERBERO")) {
2106 ## repeat retrieve (listid = m.list_id)
2107 ## where m.member_type = "KERBEROS" and m.member_id = @aid {
2108 sq_save_data(sq, listid);
2110 /* now process each one */
2111 while (sq_get_data(sq, &id)) {
2112 if (get_ace_internal("LIST", id, action, actarg) == SMS_SUCCESS)
2115 if (get_ace_internal("KERBEROS", aid, action, actarg) == SMS_SUCCESS)
2120 if (ingres_errno) return(sms_errcode);
2121 if (!found) return(SMS_NO_MATCH);
2122 return(SMS_SUCCESS);
2126 /* This looks up a single list or user for ace use. atype must be "USER"
2127 * or "LIST", and aid is the ID of the corresponding object. This is used
2128 * by get_ace_use above.
2131 ##get_ace_internal(atype, aid, action, actarg)
2142 if (!strcmp(atype, "LIST")) {
2143 rargv[0] = "FILESYS";
2144 ## repeat retrieve (name = filesys.label)
2145 ## where filesys.owners = @aid {
2146 (*action)(2, rargv, actarg);
2151 ## repeat retrieve (name = capacls.capability)
2152 ## where capacls.list_id = @aid {
2153 (*action)(2, rargv, actarg);
2156 } else if (!strcmp(atype, "USER")) {
2157 rargv[0] = "FILESYS";
2158 ## repeat retrieve (name = filesys.label)
2159 ## where filesys.owner = @aid {
2160 (*action)(2, rargv, actarg);
2166 ## repeat retrieve (name = list.#name)
2167 ## where list.acl_type = @atype and list.acl_id = @aid {
2168 (*action)(2, rargv, actarg);
2172 rargv[0] = "SERVICE";
2173 ## repeat retrieve (name = servers.#name)
2174 ## where servers.acl_type = @atype and servers.acl_id = @aid {
2175 (*action)(2, rargv, actarg);
2179 rargv[0] = "HOSTACCESS";
2180 ## repeat retrieve (name = machine.#name)
2181 ## where machine.mach_id = hostaccess.mach_id and
2182 ## hostaccess.acl_type = @atype and hostaccess.acl_id = @aid {
2183 (*action)(2, rargv, actarg);
2186 rargv[0] = "ZEPHYR";
2187 ## repeat retrieve (name = zephyr.class)
2188 ## where zephyr.xmt_type = @atype and zephyr.xmt_id = @aid or
2189 ## zephyr.sub_type = @atype and zephyr.sub_id = @aid or
2190 ## zephyr.iws_type = @atype and zephyr.iws_id = @aid or
2191 ## zephyr.iui_type = @atype and zephyr.iui_id = @aid {
2192 (*action)(2, rargv, actarg);
2196 if (!found) return(SMS_NO_MATCH);
2197 return(SMS_SUCCESS);
2201 /* get_lists_of_member - given a type and a name, return the name and flags
2202 * of all of the lists of the given member. The member_type is one of
2203 * "LIST", "USER", "STRING", "RLIST", "RUSER", or "RSTRING" in argv[0],
2204 * and argv[1] will contain the ID of the entity in question. The R*
2205 * types mean to recursively look at every containing list, not just
2206 * when the object in question is a direct member.
2209 int get_lists_of_member(q, argv, cl, action, actarg)
2216 int found = 0, direct = 1;
2219 ## int aid, listid, id;
2220 ## char name[33], active[5], public[5], hidden[5], maillist[5], group[5];
2223 aid = *(int *)argv[1];
2224 if (!strcmp(atype, "RLIST")) {
2228 if (!strcmp(atype, "RUSER")) {
2232 if (!strcmp(atype, "RSTRING")) {
2236 if (!strcmp(atype, "RKERBEROS")) {
2245 rargv[4] = maillist;
2248 ## repeat retrieve (name = list.#name, active = text(list.#active),
2249 ## public = text(list.#public), hidden = text(list.#hidden),
2250 ## maillist = text(list.#maillist), group = text(list.#group))
2251 ## where list.list_id = m.list_id and m.direct = 1 and
2252 ## m.member_type = @atype and m.member_id = @aid {
2253 (*action)(6, rargv, actarg);
2257 ## repeat retrieve (name = list.#name, active = text(list.#active),
2258 ## public = text(list.#public), hidden = text(list.#hidden),
2259 ## maillist = text(list.#maillist), group = text(list.#group))
2260 ## where list.list_id = m.list_id and
2261 ## m.member_type = @atype and m.member_id = @aid {
2262 (*action)(6, rargv, actarg);
2267 if (ingres_errno) return(sms_errcode);
2268 if (!found) return(SMS_NO_MATCH);
2269 return(SMS_SUCCESS);
2273 /* qualified_get_lists: passed "TRUE", "FALSE", or "DONTCARE" for each of
2274 * the five flags associated with each list. It will return the name of
2275 * each list that meets the quailifications. It does this by building a
2276 * where clause based on the arguments, then doing a retrieve.
2279 static char *lflags[5] = { "active", "public", "hidden", "maillist", "group" };
2281 int qualified_get_lists(q, argv, cl, action, actarg)
2288 return(qualified_get(q, argv, action, actarg, "l.list_id != 0",
2289 "l", "name", lflags));
2293 /** get_members_of_list - optimized query for retrieval of list members
2296 ** argv[0] - list_id
2299 ** - retrieve USER members, then LIST members, then STRING members
2302 get_members_of_list(q, argv, cl, action, actarg)
2310 ## char member_name[129];
2313 list_id = *(int *)argv[0];
2315 targv[1] = member_name;
2317 ## range of m is imembers
2318 ## repeat retrieve (member_name = users.login)
2319 ## where m.#list_id = @list_id and m.member_type = "USER"
2320 ## and m.member_id = users.users_id and m.direct = 1
2321 ## sort by #member_name
2323 (*action)(2, targv, actarg);
2325 if (ingres_errno) return(sms_errcode);
2328 ## repeat retrieve (member_name = list.name)
2329 ## where m.#list_id = @list_id and m.member_type = "LIST"
2330 ## and m.member_id = list.#list_id and m.direct = 1
2331 ## sort by #member_name
2333 (*action)(2, targv, actarg);
2335 if (ingres_errno) return(sms_errcode);
2337 targv[0] = "STRING";
2338 ## repeat retrieve (member_name = strings.string)
2339 ## where m.#list_id = @list_id and m.member_type = "STRING"
2340 ## and m.member_id = strings.string_id and m.direct = 1
2341 ## sort by #member_name
2343 (*action)(2, targv, actarg);
2345 if (ingres_errno) return(sms_errcode);
2347 targv[0] = "KERBEROS";
2348 ## repeat retrieve (member_name = strings.string)
2349 ## where m.#list_id = @list_id and m.member_type = "KERBEROS"
2350 ## and m.member_id = strings.string_id and m.direct = 1
2351 ## sort by #member_name
2353 (*action)(2, targv, actarg);
2355 if (ingres_errno) return(sms_errcode);
2357 return(SMS_SUCCESS);
2361 /* count_members_of_list: this is a simple query, but it cannot be done
2362 * through the dispatch table.
2365 int count_members_of_list(q, argv, cl, action, actarg)
2372 ## int list, ct = 0;
2373 char *rargv[1], countbuf[5];
2375 list = *(int *)argv[0];
2376 rargv[0] = countbuf;
2377 ## repeat retrieve (ct = count(imembers.list_id
2378 ## where imembers.list_id = @list and
2379 ## imembers.direct = 1))
2380 if (ingres_errno) return(sms_errcode);
2381 sprintf(countbuf, "%d", ct);
2382 (*action)(1, rargv, actarg);
2383 return(SMS_SUCCESS);
2387 /* qualified_get_server: passed "TRUE", "FALSE", or "DONTCARE" for each of
2388 * the three flags associated with each service. It will return the name of
2389 * each service that meets the quailifications. It does this by building a
2390 * where clause based on the arguments, then doing a retrieve.
2393 static char *sflags[3] = { "enable", "inprogress", "harderror" };
2395 int qualified_get_server(q, argv, cl, action, actarg)
2402 return(qualified_get(q, argv, action, actarg, "s.name != \"\"",
2403 "s", "name", sflags));
2407 /* generic qualified get routine, used by qualified_get_lists,
2408 * qualified_get_server, and qualified_get_serverhost.
2410 * start - a simple where clause, must not be empty
2411 * range - the name of the range variable
2412 * field - the field to return
2413 * flags - an array of strings, names of the flag variables
2416 int qualified_get(q, argv, action, actarg, start, range, field, flags)
2426 ## char name[33], qual[256], *rvar, *rtbl, *rfield;
2427 char *rargv[1], buf[32];
2430 strcpy(qual, start);
2431 for (i = 0; i < q->argc; i++) {
2432 if (!strcmp(argv[i], "TRUE")) {
2433 sprintf(buf, " and %s.%s != 0", range, flags[i]);
2434 (void) strcat(qual, buf);
2435 } else if (!strcmp(argv[i], "FALSE")) {
2436 sprintf(buf, " and %s.%s = 0", range, flags[i]);
2437 (void) strcat(qual, buf);
2445 ## range of rvar is rtbl
2446 ## retrieve (name = rvar.rfield) where qual {
2447 (*action)(1, rargv, actarg);
2449 if (ingres_errno) return(sms_errcode);
2450 ## inquire_equel(rowcount = "rowcount")
2451 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
2452 ## where tblstats.#table = @rtbl
2454 return(SMS_NO_MATCH);
2455 return(SMS_SUCCESS);
2459 /* qualified_get_serverhost: passed "TRUE", "FALSE", or "DONTCARE" for each of
2460 * the five flags associated with each serverhost. It will return the name of
2461 * each service and host that meets the quailifications. It does this by
2462 * building a where clause based on the arguments, then doing a retrieve.
2465 static char *shflags[6] = { "service", "enable", "override", "success",
2466 "inprogress", "hosterror" };
2468 int qualified_get_serverhost(q, argv, cl, action, actarg)
2475 ## char sname[33], mname[33], qual[256];
2476 char *rargv[2], buf[32];
2479 sprintf(qual, "machine.mach_id = sh.mach_id and sh.service = uppercase(\"%s\")",
2481 for (i = 1; i < q->argc; i++) {
2482 if (!strcmp(argv[i], "TRUE")) {
2483 sprintf(buf, " and sh.%s != 0", shflags[i]);
2485 } else if (!strcmp(argv[i], "FALSE")) {
2486 sprintf(buf, " and sh.%s = 0", shflags[i]);
2493 ## range of sh is serverhosts
2494 ## retrieve (sname = sh.service, mname = machine.name) where qual {
2495 (*action)(2, rargv, actarg);
2497 if (ingres_errno) return(sms_errcode);
2498 ## inquire_equel(rowcount = "rowcount")
2499 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
2500 ## where tblstats.#table = "serverhosts"
2502 return(SMS_NO_MATCH);
2503 return(SMS_SUCCESS);
2507 /* register_user - change user's login name and allocate a pobox, group,
2508 * filesystem, and quota for them. The user's status must start out as 0,
2509 * and is left as 2. Arguments are: user's UID, new login name, and user's
2510 * type for filesystem allocation (SMS_FS_STUDENT, SMS_FS_FACULTY,
2511 * SMS_FS_STAFF, SMS_FS_MISC).
2514 register_user(q, argv, cl)
2519 ## char *login, dir[65], *entity, *directory, machname[33];
2520 ## int who, rowcount, mid, uid, users_id, flag, utype, nid, list_id, quota;
2521 ## int size, alloc, pid, m_id;
2522 char buffer[256], *aargv[3];
2525 entity = cl->entity;
2526 who = cl->client_id;
2528 uid = atoi(argv[0]);
2530 utype = atoi(argv[2]);
2532 ## range of u is users
2533 ## range of l is list
2534 ## range of sh is serverhosts
2535 ## range of n is nfsphys
2536 ## range of m is machine
2539 ## repeat retrieve (users_id = u.#users_id)
2540 ## where u.#uid = @uid and (u.status = 0 or u.status = 5)
2541 ## inquire_equel(rowcount = "rowcount");
2543 return(SMS_NO_MATCH);
2545 return(SMS_NOT_UNIQUE);
2547 /* check new login name */
2548 ## repeat retrieve (flag = any(u.#login where u.#login = @login and
2549 ## u.#users_id != users_id))
2550 if (ingres_errno) return(sms_errcode);
2551 if (flag) return(SMS_IN_USE);
2552 ## repeat retrieve (flag = any(l.#name where l.#name = @login))
2553 if (ingres_errno) return(sms_errcode);
2554 if (flag) return(SMS_IN_USE);
2555 ## repeat retrieve (flag = any(filesys.#label where filesys.#label = @login))
2556 if (ingres_errno) return(sms_errcode);
2557 if (flag) return(SMS_IN_USE);
2558 com_err(whoami, 0, "new login name OK");
2560 /* choose place for pobox, put in mid */
2561 ## repeat retrieve (mid = sh.mach_id, machname = m.name)
2562 ## where sh.service = "POP" and m.mach_id = sh.mach_id and
2563 ## sh.value2 - sh.value1 = max(sh.value2-sh.value1 where sh.service="POP")
2564 if (ingres_errno) return(sms_errcode);
2565 ## inquire_equel(rowcount = "rowcount");
2567 return(SMS_NO_POBOX);
2569 /* change login name, set pobox */
2570 sprintf(buffer, "u.users_id = %d", users_id);
2571 incremental_before("users", buffer, 0);
2572 ## repeat replace u (#login = @login, status = 2, modtime = "now",
2573 ## modby = @who, modwith = @entity, potype="POP",
2574 ## pop_id = @mid, pmodtime="now", pmodby=@who,
2575 ## pmodwith=@entity)
2576 ## where u.#users_id = @users_id
2577 ## inquire_equel(rowcount = "rowcount");
2578 if (ingres_errno) return(sms_errcode);
2580 return(SMS_INTERNAL);
2581 set_pop_usage(mid, 1);
2582 com_err(whoami, 0, "set login name to %s and pobox to %s", login,
2584 incremental_after("users", buffer, 0);
2586 /* create group list */
2587 if (set_next_object_id("gid", "list"))
2589 if (set_next_object_id("list_id", "list"))
2591 ## repeat retrieve (list_id = values.value) where values.name = "list_id"
2592 if (ingres_errno) return(sms_errcode);
2593 ## inquire_equel(rowcount = "rowcount");
2595 return(SMS_INTERNAL);
2596 incremental_clear_before();
2597 ## repeat append list (name = @login, #list_id = @list_id, active = 1,
2598 ## public = 0, hidden = 0, maillist = 0, group = 1,
2599 ## #gid = values.value, desc = "User Group",
2600 ## acl_type = "USER", acl_id = @users_id, modtime = "now",
2601 ## modby = @who, modwith = @entity)
2602 ## where values.name = "gid"
2603 if (ingres_errno) return(sms_errcode);
2604 ## inquire_equel(rowcount = "rowcount");
2606 return(SMS_INTERNAL);
2607 sprintf(buffer, "l.list_id = %d", list_id);
2608 incremental_after("list", buffer, 0);
2609 aargv[0] = (char *) list_id;
2611 aargv[2] = (char *) users_id;
2612 incremental_clear_before();
2613 ## repeat append imembers (#list_id = @list_id, member_type = "USER",
2614 ## member_id = @users_id, ref_count = 1, direct = 1)
2615 if (ingres_errno) return(sms_errcode);
2616 ## inquire_equel(rowcount = "rowcount");
2618 return(SMS_INTERNAL);
2619 incremental_after("members", 0, aargv);
2620 com_err(whoami, 0, "group list created");
2622 /* decide where to put filesystem */
2625 ## repeat retrieve (mid = n.mach_id, dir = trim(n.#dir), nid = n.nfsphys_id,
2626 ## flag = n.status, size = n.#size, alloc = n.allocated) {
2627 if ((flag & utype) && (size != 0) && (size - alloc > maxsize)) {
2628 maxsize = size - alloc;
2631 directory = strsave(dir);
2636 if (ingres_errno) return(sms_errcode);
2638 return(SMS_NO_FILESYS);
2640 /* create filesystem */
2641 if (set_next_object_id("filsys_id", "filesys"))
2643 incremental_clear_before();
2644 ## repeat append filesys (filsys_id = values.value, phys_id = @pid,
2645 ## label = @login, type = "NFS", mach_id = @m_id,
2646 ## name = @directory + "/" + @login,
2647 ## mount = "/mit/" + @login,
2648 ## access = "w", comments = "User Locker",
2649 ## owner = @users_id, owners = @list_id, createflg = 1,
2650 ## lockertype = "HOMEDIR", modtime = "now",
2651 ## modby = @who, modwith = @entity)
2652 ## where values.name = "filsys_id"
2653 if (ingres_errno) return(sms_errcode);
2654 ## inquire_equel(rowcount = "rowcount");
2656 return(SMS_INTERNAL);
2657 incremental_after("filesys",
2658 "fs.filsys_id = values.value and values.name = \"filsys_id\"",
2660 com_err(whoami, 0, "filesys created on mach %d in %s/%s", m_id,
2664 ## repeat retrieve (quota = values.value) where values.name = "def_quota"
2665 if (ingres_errno) return(sms_errcode);
2666 ## inquire_equel(rowcount = "rowcount");
2668 return(SMS_NO_QUOTA);
2669 incremental_clear_before();
2670 ## repeat append nfsquota (#users_id = @users_id, filsys_id = values.value,
2671 ## #quota = @quota, phys_id = @pid, modtime = "now",
2672 ## modby = @who, modwith = @entity)
2673 ## where values.name = "filsys_id"
2674 if (ingres_errno) return(sms_errcode);
2675 ## inquire_equel(rowcount = "rowcount");
2677 return(SMS_INTERNAL);
2678 ## repeat replace nfsphys (allocated = nfsphys.allocated + @quota)
2679 ## where nfsphys.nfsphys_id = filesys.#phys_id and
2680 ## filesys.filsys_id = values.value and values.name = "filsys_id"
2681 if (ingres_errno) return(sms_errcode);
2682 ## inquire_equel(rowcount = "rowcount");
2684 return(SMS_INTERNAL);
2687 sprintf(buffer, "nq.users_id = %d and nq.filsys_id = values.value and values.name = \"filsys_id\"", users_id);
2688 incremental_after("nfsquota", buffer, aargv);
2689 com_err(whoami, 0, "quota of %d assigned", quota);
2690 if (ingres_errno) return(sms_errcode);
2692 ## repeat replace tblstats (updates = tblstats.updates + 1, modtime = "now")
2693 ## where tblstats.table = "users"
2694 ## repeat replace tblstats (appends = tblstats.appends + 1, modtime = "now")
2695 ## where tblstats.table = "list" or tblstats.table = "filesys" or
2696 ## tblstats.table = "nfsquota"
2697 if (ingres_errno) return(sms_errcode);
2698 return(SMS_SUCCESS);
2703 /** set_pop_usage - incr/decr usage count for pop server in serverhosts talbe
2707 ** delta (will be +/- 1)
2710 ** - incr/decr value field in serverhosts table for pop/mach_id
2714 static int set_pop_usage(id, count)
2718 ## int mach_id = id;
2721 ## range of sh is serverhosts
2722 ## repeat replace sh (value1 = sh.value1 + @n)
2723 ## where sh.service = "POP" and sh.#mach_id = @mach_id
2725 if (ingres_errno) return(sms_errcode);
2726 return(SMS_SUCCESS);
2731 /* Validation Routines */
2733 validate_row(q, argv, v)
2734 register struct query *q;
2736 register struct validate *v;
2744 /* build where clause */
2745 build_qual(v->qual, v->argc, argv, qual);
2747 /* setup ingres variables */
2752 if (log_flags & LOG_VALID)
2753 /* tell the logfile what we're doing */
2754 com_err(whoami, 0, "validating row: %s", qual);
2756 /* look for the record */
2757 ## range of rvar is table
2758 ## retrieve (rowcount = count(rvar.name where qual))
2759 if (ingres_errno) return(sms_errcode);
2760 if (rowcount == 0) return(SMS_NO_MATCH);
2761 if (rowcount > 1) return(SMS_NOT_UNIQUE);
2765 validate_fields(q, argv, vo, n)
2767 register char *argv[];
2768 register struct valobj *vo;
2771 register int status;
2776 if (log_flags & LOG_VALID)
2777 com_err(whoami, 0, "validating %s in %s: %s",
2778 vo->namefield, vo->table, argv[vo->index]);
2779 status = validate_name(argv, vo);
2783 if (log_flags & LOG_VALID)
2784 com_err(whoami, 0, "validating %s in %s: %s",
2785 vo->idfield, vo->table, argv[vo->index]);
2786 status = validate_id(argv, vo);
2790 if (log_flags & LOG_VALID)
2791 com_err(whoami, 0, "validating date: %s", argv[vo->index]);
2792 status = validate_date(argv, vo);
2796 if (log_flags & LOG_VALID)
2797 com_err(whoami, 0, "validating %s type: %s",
2798 vo->table, argv[vo->index]);
2799 status = validate_type(argv, vo);
2803 if (log_flags & LOG_VALID)
2804 com_err(whoami, 0, "validating typed data (%s): %s",
2805 argv[vo->index - 1], argv[vo->index]);
2806 status = validate_typedata(q, argv, vo);
2810 if (log_flags & LOG_VALID)
2811 com_err(whoami, 0, "validating rename %s in %s",
2812 argv[vo->index], vo->table);
2813 status = validate_rename(argv, vo);
2817 if (log_flags & LOG_VALID)
2818 com_err(whoami, 0, "validating chars: %s", argv[vo->index]);
2819 status = validate_chars(argv[vo->index]);
2823 status = SMS_EXISTS;
2827 status = lock_table(vo);
2831 if (status != SMS_EXISTS) return(status);
2835 if (ingres_errno) return(sms_errcode);
2836 return(SMS_SUCCESS);
2840 /* validate_chars: verify that there are no illegal characters in
2841 * the string. Legal characters are printing chars other than
2842 * ", *, ?, \, [ and ].
2844 static int illegalchars[] = {
2845 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
2846 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
2847 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
2848 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
2849 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ - O */
2850 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* P - _ */
2851 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
2852 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
2853 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2854 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2855 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2856 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2857 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2858 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2859 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2860 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2867 if (illegalchars[*s++])
2868 return(SMS_BAD_CHAR);
2873 validate_id(argv, vo)
2875 register struct valobj *vo;
2885 name = argv[vo->index];
2887 /* minor kludge to upcasify machine names */
2888 if (!strcmp(table, "machine"))
2889 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
2890 namefield = vo->namefield;
2891 idfield = vo->idfield;
2892 if (!strcmp(namefield, "uid")) {
2893 ## retrieve (id = table.idfield) where table.namefield = int4(name)
2894 if (ingres_errno) return(sms_errcode);
2895 ## inquire_equel (rowcount = "rowcount")
2897 ## retrieve (id = table.idfield) where table.namefield = name
2898 if (ingres_errno) return(sms_errcode);
2899 ## inquire_equel (rowcount = "rowcount")
2901 if (rowcount != 1) return(vo->error);
2902 *(int *)argv[vo->index] = id;
2906 validate_name(argv, vo)
2908 register struct valobj *vo;
2916 name = argv[vo->index];
2918 namefield = vo->namefield;
2919 if (!strcmp(table, "servers") && !strcmp(namefield, "name")) {
2920 for (c = name; *c; c++)
2924 ## retrieve (rowcount = countu(table.namefield
2925 ## where table.namefield = name))
2926 if (ingres_errno) return(sms_errcode);
2927 return ((rowcount == 1) ? SMS_EXISTS : vo->error);
2930 validate_date(argv, vo)
2938 idate = argv[vo->index];
2940 ## retrieve (dd = interval("years", date(idate) - date("today")))
2941 ## inquire_equel (errorno = "errorno")
2942 if (errorno != 0 || dd > 5.0) return(SMS_DATE);
2947 validate_rename(argv, vo)
2951 ## char *name, *table, *namefield, *idfield;
2955 c = name = argv[vo->index];
2957 if (illegalchars[*c++])
2958 return(SMS_BAD_CHAR);
2960 /* minor kludge to upcasify machine names */
2961 if (!strcmp(table, "machine"))
2962 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
2963 namefield = vo->namefield;
2964 idfield = vo->idfield;
2967 if (!strcmp(argv[vo->index], argv[vo->index - 1]))
2969 ## retrieve (id = any(table.namefield where table.namefield = name))
2970 if (ingres_errno) return(sms_errcode);
2976 ## retrieve (id = table.idfield) where table.namefield = name
2977 if (ingres_errno) return(sms_errcode);
2978 if (id == -1 || id == *(int *)argv[vo->index - 1])
2985 validate_type(argv, vo)
2987 register struct valobj *vo;
2994 typename = vo->table;
2995 c = value = argv[vo->index];
2997 if (illegalchars[*c++])
2998 return(SMS_BAD_CHAR);
3000 /* uppercase type fields */
3001 for (c = value; *c; c++) if (islower(*c)) *c = toupper(*c);
3003 ## range of a is alias
3004 ## repeat retrieve (exists = any(a.trans where a.name = @typename and
3005 ## a.type = "TYPE" and
3006 ## a.trans = @value))
3007 if (ingres_errno) return(sms_errcode);
3008 return (exists ? SMS_EXISTS : vo->error);
3011 /* validate member or type-specific data field */
3013 validate_typedata(q, argv, vo)
3014 register struct query *q;
3015 register char *argv[];
3016 register struct valobj *vo;
3019 ## char *field_type;
3020 ## char data_type[129];
3026 /* get named object */
3027 name = argv[vo->index];
3029 /* get field type string (known to be at index-1) */
3030 field_type = argv[vo->index-1];
3032 /* get corresponding data type associated with field type name */
3033 ## repeat retrieve (data_type = alias.trans)
3034 ## where alias.#name = @field_type and alias.type = "TYPEDATA"
3035 if (ingres_errno) return(sms_errcode);
3036 ## inquire_equel (rowcount = "rowcount")
3037 if (rowcount != 1) return(SMS_TYPE);
3039 /* now retrieve the record id corresponding to the named object */
3040 if (index(data_type, ' '))
3041 *index(data_type, ' ') = 0;
3042 if (!strcmp(data_type, "user")) {
3044 ## repeat retrieve (id = users.users_id) where users.login = @name
3045 ## inquire_equel (rowcount = "rowcount")
3046 if (rowcount != 1) return(SMS_USER);
3048 } else if (!strcmp(data_type, "list")) {
3050 ## repeat retrieve (id = list.list_id) where list.#name = @name
3051 ## inquire_equel (rowcount = "rowcount")
3052 if (rowcount != 1) {
3053 /* if idfield is non-zero, then if argv[0] matches the string
3054 * that we're trying to resolve, we should get the value of
3055 * values.[idfield] for the id.
3057 if (vo->idfield && !strcmp(argv[0], argv[vo->index])) {
3058 set_next_object_id(q->validate->object_id, q->rtable);
3060 ## repeat retrieve (id = values.value) where values.#name = @name
3061 ## inquire_equel(rowcount = "rowcount")
3062 if (rowcount != 1) return(SMS_LIST);
3066 } else if (!strcmp(data_type, "machine")) {
3068 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3069 ## repeat retrieve (id = machine.mach_id) where machine.#name = @name
3070 ## inquire_equel (rowcount = "rowcount")
3071 if (rowcount != 1) return(SMS_MACHINE);
3073 } else if (!strcmp(data_type, "string")) {
3075 ## range of s is strings
3076 ## repeat retrieve (id = s.string_id) where s.string = @name
3077 ## inquire_equel (rowcount = "rowcount")
3078 if (rowcount == 0) {
3079 if (q->type != APPEND) return(SMS_STRING);
3080 ## range of v is values
3081 ## retrieve (id = v.value) where v.#name = "strings_id"
3083 ## replace v (value = id) where v.#name = "strings_id"
3084 ## append to strings (string_id = id, string = name)
3086 } else if (!strcmp(data_type, "none")) {
3092 /* now set value in argv */
3093 *(int *)argv[vo->index] = id;
3095 return (SMS_EXISTS);
3099 /* Lock the table named by the validation object */
3104 ## char *table, *idfield;
3108 idfield = vo->idfield;
3109 ## replace table (modtime = "now") where table.idfield = 0
3110 if (ingres_errno) return(sms_errcode);
3111 ## inquire_equel (rowcount = "rowcount")
3119 /* Check the database at startup time. For now this just resets the
3120 * inprogress flags that the DCM uses.
3123 sanity_check_database()