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];
700 fid = *(int *)argv[0];
702 if (!strcmp(type, "NFS")) {
703 status = check_nfs(mach_id, name, access);
704 ## replace nfsquota (phys_id = var_phys_id) where nfsquota.filsys_id = fid
705 if (ingres_errno) return(sms_errcode);
707 } else if (!strcmp(type, "AFS")) {
709 ## retrieve (total = sum(nfsquota.quota where nfsquota.filsys_id = fid))
710 if (ingres_errno) return(sms_errcode);
712 ## delete nfsquota where nfsquota.filsys_id = fid
713 if (ingres_errno) return(sms_errcode);
714 ## append nfsquota (quota = total, filsys_id = fid,
715 ## phys_id = 0, users_id = 0)
716 if (ingres_errno) return(sms_errcode);
719 ## replace nfsquota (phys_id = 0) where nfsquota.filsys_id = fid
720 if (ingres_errno) return(sms_errcode);
726 /* Find the NFS physical partition that the named directory is on.
727 * This is done by comparing the dir against the mount point of the
728 * partition. To make sure we get the correct match when there is
729 * more than one, we sort the query in reverse order by dir name.
732 ##check_nfs(mach_id, name, access)
743 caccess = (isupper(*access)) ? tolower(*access) : *access;
744 if (caccess != 'r' && caccess != 'w' && caccess != 'n')
745 return(SMS_FILESYS_ACCESS);
748 ## range of np is nfsphys
749 ## repeat retrieve (var_phys_id = np.#nfsphys_id, dir = trim(np.#dir))
750 ## where np.#mach_id = @mach_id sort by #dir:d {
754 if (*cp1++ != *cp2) break;
758 status = SMS_SUCCESS;
768 /* setup_dfil: free any quota records and fsgroup info associated with
769 * a filesystem when it is deleted. Also adjust the allocation numbers.
772 setup_dfil(q, argv, cl)
779 id = *(int *)argv[0];
780 ## range of q is nfsquota
781 ## range of fs is filesys
782 ## range of n is nfsphys
783 ## repeat replace n (allocated=n.allocated-sum(q.quota where q.filsys_id=@id))
784 ## where n.nfsphys_id = fs.phys_id and fs.filsys_id = @id
786 ## repeat delete q where q.filsys_id = @id
787 ## repeat delete fsgroup where fsgroup.filsys_id = @id
788 ## repeat delete fsgroup where fsgroup.group_id = @id
789 if (ingres_errno) return(sms_errcode);
794 /* setup_dnfp: check to see that the nfs physical partition does not have
795 * any filesystems assigned to it before allowing it to be deleted.
798 setup_dnfp(q, argv, cl)
805 id = *(int *)argv[0];
806 ## repeat retrieve (exists = any(filesys.label where filesys.phys_id = @id))
815 /* setup_dnfq: Remove allocation from nfsphys before deleting quota.
816 * argv[0] = filsys_id
820 setup_dnfq(q, argv, cl)
825 ## int quota, fs, user;
827 fs = *(int *)argv[0];
828 user = *(int *)argv[1];
830 ## range of q is nfsquota
831 ## repeat retrieve (quota = q.#quota) where q.users_id = @user and
833 ## repeat replace nfsphys (allocated = nfsphys.allocated - @quota)
834 ## where nfsphys.nfsphys_id = filesys.#phys_id and filesys.filsys_id = @fs
835 if (ingres_errno) return(sms_errcode);
840 /* setup_sshi: don't exclusive lock the machine table during
841 * set_server_host_internal.
844 setup_sshi(q, argv, cl)
849 ## set lockmode session where readlock = system
853 /* setup add_kerberos_user_mapping: add the string to the string
854 * table if necessary.
857 setup_akum(q, argv, cl)
866 ## range of s is strings
867 ## repeat retrieve (id = s.string_id) where s.string = @name
868 ## inquire_equel (rowcount = "rowcount")
870 if (q->type != APPEND) return(SMS_STRING);
871 ## range of v is values
872 ## retrieve (id = v.value) where v.#name = "strings_id"
874 ## replace v (value = id) where v.#name = "strings_id"
875 ## append to strings (string_id = id, string = name)
877 if (ingres_errno) return(sms_errcode);
878 *(int *)argv[1] = id;
884 /* FOLLOWUP ROUTINES */
886 /* generic set_modtime routine. This takes the table name from the query,
887 * and will update the modtime, modby, and modwho fields in the entry in
888 * the table whose name field matches argv[0].
891 set_modtime(q, argv, cl)
896 ## char *name, *entity, *table;
904 ## replace table (modtime = "now", modby = who, modwith = entity)
905 ## where table.#name = name
909 /* generic set_modtime_by_id routine. This takes the table name from
910 * the query, and the id name from the validate record,
911 * and will update the modtime, modby, and modwho fields in the entry in
912 * the table whose id matches argv[0].
915 set_modtime_by_id(q, argv, cl)
920 ## char *entity, *table, *id_name;
926 id_name = q->validate->object_id;
928 id = *(int *)argv[0];
929 ## replace table (modtime = "now", modby = who, modwith = entity)
930 ## where table.id_name = id
935 /* Sets the finger modtime on a user record. The users_id will be in argv[0].
938 set_finger_modtime(q, argv, cl)
943 ## int users_id, who;
948 users_id = *(int *)argv[0];
950 ## repeat replace u (fmodtime = "now", fmodby = @who, fmodwith = @entity)
951 ## where u.#users_id = @users_id
956 /* Sets the pobox modtime on a user record. The users_id will be in argv[0].
959 set_pobox_modtime(q, argv, cl)
964 ## int users_id, who;
969 users_id = *(int *)argv[0];
971 ## repeat replace users (pmodtime = "now", pmodby = @who, pmodwith = @entity)
972 ## where users.#users_id = @users_id
977 /* Like set_modtime, but uppercases the name first.
980 set_uppercase_modtime(q, argv, cl)
985 ## char *name, *entity, *table;
993 ## replace table (modtime = "now", modby = who, modwith = entity)
994 ## where table.#name = uppercase(name)
999 /* Sets the modtime on the machine whose mach_id is in argv[0]. This routine
1000 * is necessary for add_machine_to_cluster becuase the table that query
1001 * operates on is "mcm", not "machine".
1004 set_mach_modtime_by_id(q, argv, cl)
1012 entity = cl->entity;
1013 who = cl->client_id;
1015 id = *(int *)argv[0];
1016 ## range of m is machine
1017 ## repeat replace m (modtime = "now", modby = @who, modwith = @entity)
1018 ## where m.mach_id = @id
1019 return(SMS_SUCCESS);
1023 /* Sets the modtime on the cluster whose mach_id is in argv[0]. This routine
1024 * is necessary for add_cluster_data and delete_cluster_data becuase the
1025 * table that query operates on is "svc", not "cluster".
1028 set_cluster_modtime_by_id(q, argv, cl)
1036 entity = cl->entity;
1037 who = cl->client_id;
1039 id = *(int *)argv[0];
1040 ## range of c is cluster
1041 ## repeat replace c (modtime = "now", modby = @who, modwith = @entity)
1042 ## where c.clu_id = @id
1043 return(SMS_SUCCESS);
1047 /* sets the modtime on the serverhost where the service name is in argv[0]
1048 * and the mach_id is in argv[1].
1051 set_serverhost_modtime(q, argv, cl)
1056 ## char *entity, *serv;
1059 entity = cl->entity;
1060 who = cl->client_id;
1063 id = *(int *)argv[1];
1064 ## repeat replace sh (modtime = "now", modby = @who, modwith = @entity)
1065 ## where sh.service = uppercase(@serv) and sh.mach_id = @id
1066 return(SMS_SUCCESS);
1070 /* sets the modtime on the nfsphys where the mach_id is in argv[0] and the
1071 * directory name is in argv[1].
1074 set_nfsphys_modtime(q, argv, cl)
1079 ## char *entity, *dir;
1082 entity = cl->entity;
1083 who = cl->client_id;
1085 id = *(int *)argv[0];
1087 ## repeat replace np (modtime = "now", modby = @who, modwith = @entity)
1088 ## where np.#dir = @dir and np.mach_id = @id
1089 return(SMS_SUCCESS);
1093 /* sets the modtime on a filesystem, where argv[0] contains the filesys
1097 set_filesys_modtime(q, argv, cl)
1102 ## char *label, *entity;
1105 entity = cl->entity;
1106 who = cl->client_id;
1109 if (!strcmp(q->shortname, "ufil"))
1112 ## repeat replace fs (modtime = "now", modby = @who, modwith = @entity,
1113 ## #phys_id = @var_phys_id) where fs.#label = @label
1114 return(SMS_SUCCESS);
1118 /* sets the modtime on a zephyr class, where argv[0] contains the class
1122 set_zephyr_modtime(q, argv, cl)
1127 ## char *class, *entity;
1130 entity = cl->entity;
1131 who = cl->client_id;
1135 ## repeat replace z (modtime = "now", modby = @who, modwith = @entity)
1136 ## where z.#class = @class
1137 return(SMS_SUCCESS);
1141 /* fixes the modby field. This will be the second to last thing in the
1142 * argv, the argv length is determined from the query structure. It is
1143 * passed as a pointer to an integer. This will either turn it into a
1144 * username, or # + the users_id.
1146 followup_fix_modby(q, sq, v, action, actarg, cl)
1148 register struct save_queue *sq;
1150 register int (*action)();
1151 register int actarg;
1155 char **argv, *malloc();
1156 ## int id, rowcount;
1160 while (sq_get_data(sq, &argv)) {
1163 argv[i] = malloc(256);
1166 ## repeat retrieve (name = users.login) where users.users_id = @id
1169 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1172 ## inquire_equel(rowcount = "rowcount")
1173 if (rowcount != 1) {
1174 sprintf(argv[i], "#%d", id);
1176 (*action)(q->vcnt, argv, actarg);
1177 for (j = 0; j < q->vcnt; j++)
1182 if (ingres_errno) return(sms_errcode);
1183 return(SMS_SUCCESS);
1188 ** followup_ausr - add finger and pobox entries, set_user_modtime
1191 ** argv[0] - login (add_user)
1192 ** argv[3] - last name
1193 ** argv[4] - first name
1194 ** argv[5] - middle name
1198 followup_ausr(q, argv, cl)
1204 ## char *login, *entity;
1205 ## char fullname[129];
1208 who = cl->client_id;
1209 entity = cl->entity;
1211 /* build fullname */
1212 if (strlen(argv[4]) && strlen(argv[5]))
1213 sprintf(fullname, "%s %s %s", argv[4], argv[5], argv[3]);
1214 else if (strlen(argv[4]))
1215 sprintf(fullname, "%s %s", argv[4], argv[3]);
1217 sprintf(fullname, "%s", argv[3]);
1219 /* create finger entry, pobox & set modtime on user */
1220 ## repeat replace u (modtime = "now", modby=@who, modwith=@entity,
1221 ## #fullname=@fullname, mit_affil = u.mit_year,
1222 ## fmodtime="now", fmodby=@who, fmodwith=@entity,
1223 ## potype="NONE", pmodtime="now", pmodby=@who, pmodwith=@entity)
1224 ## where u.#login = @login
1226 return(SMS_SUCCESS);
1230 /* followup_gpob: fixes argv[2] based on the IDs currently there and the
1231 * type in argv[1]. Then completes the upcall to the user.
1233 * argv[2] is of the form "123:234" where the first integer is the machine
1234 * ID if it is a pop box, and the second is the string ID if it is an SMTP
1235 * box. argv[1] should be "POP", "SMTP", or "NONE". Boxes of type NONE
1239 followup_gpob(q, sq, v, action, actarg, cl)
1240 register struct query *q;
1241 register struct save_queue *sq;
1242 register struct validate *v;
1243 register int (*action)();
1247 char **argv, *index();
1249 ## char box[129], *name;
1250 ## int mid, sid, rowcount;
1253 while (sq_get_data(sq, &argv)) {
1254 sms_trim_args(2, argv);
1256 p = index(argv[2], ':');
1258 mid = atoi(argv[2]);
1262 if (!strcmp(ptype, "POP")) {
1263 ## repeat retrieve (box=machine.#name) where machine.mach_id=@mid
1264 ## inquire_equel(rowcount = "rowcount")
1266 return(SMS_MACHINE);
1267 } else if (!strcmp(ptype, "SMTP")) {
1268 ## repeat retrieve (box=strings.string) where strings.string_id=@sid
1269 ## inquire_equel(rowcount = "rowcount")
1272 } else /* ptype == "NONE" */ {
1276 if (!strcmp(q->shortname, "gpob")) {
1277 sid = atoi(argv[4]);
1279 argv[4] = malloc(256);
1282 ## repeat retrieve (name = users.login) where users.users_id = @sid
1285 ## repeat retrieve (name = strings.string)
1286 ## where strings.string_id = @sid
1289 ## inquire_equel(rowcount = "rowcount")
1291 sprintf(name, "#%d", sid);
1295 (*action)(q->vcnt, argv, actarg);
1297 /* free saved data */
1305 return (SMS_SUCCESS);
1309 /* followup_glin: fix the ace_name in argv[8]. argv[7] will contain the
1310 * ace_type: "LIST", "USER", or "NONE". Decode the id in argv[8] into the
1311 * proper name based on the type, and repace that string in the argv.
1312 * Also fixes the modby field by called followup_fix_modby.
1315 followup_glin(q, sq, v, action, actarg, cl)
1316 register struct query *q;
1317 register struct save_queue *sq;
1318 register struct validate *v;
1319 register int (*action)();
1323 char **argv, *malloc(), *realloc(), *type;
1325 ## int id, rowcount;
1329 if (!strcmp(q->shortname, "gsin"))
1332 while (sq_get_data(sq, &argv)) {
1333 sms_trim_args(q->vcnt, argv);
1335 id = atoi(argv[i = q->vcnt - 2]);
1337 name = argv[i] = malloc(256);
1339 ## repeat retrieve (name = users.login) where users.users_id = @id
1342 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1345 ## inquire_equel(rowcount = "rowcount")
1347 sprintf(argv[i], "#%d", id);
1349 id = atoi(argv[idx]);
1350 type = argv[idx - 1];
1351 if ((name = malloc(33)) == NULL)
1354 if (!strcmp(type, "LIST")) {
1355 ## repeat retrieve (name = list.#name) where list.list_id = @id
1356 ## inquire_equel(rowcount = "rowcount")
1358 strcpy(name, "???");
1359 } else if (!strcmp(type, "USER")) {
1360 ## repeat retrieve (name = users.login) where users.users_id = @id
1361 ## inquire_equel(rowcount = "rowcount")
1363 strcpy(name, "???");
1364 } else if (!strcmp(type, "KERBEROS")) {
1365 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1366 ## inquire_equel(rowcount = "rowcount")
1368 strcpy(name, "???");
1369 } else if (!strcmp(type, "NONE")) {
1370 strcpy(name, "NONE");
1372 strcpy(name, "???");
1376 if (!strcmp(q->shortname, "glin") && atoi(argv[6]) == -1) {
1377 argv[6] = realloc(argv[6], strlen(UNIQUE_GID) + 1);
1378 strcpy(argv[6], UNIQUE_GID);
1382 (*action)(q->vcnt, argv, actarg);
1384 /* free saved data */
1385 for (i = 0; i < q->vcnt; i++)
1391 return (SMS_SUCCESS);
1395 /* followup_gnfq: Fix the directory name & modby fields
1396 * argv[0] = filsys_id
1397 * argv[2] = ascii(quota)
1400 followup_gnfq(q, sq, v, action, actarg, cl)
1402 register struct save_queue *sq;
1404 register int (*action)();
1405 register int actarg;
1409 char **argv, *malloc();
1410 ## int id, rowcount;
1411 ## char *name, *label;
1413 while (sq_get_data(sq, &argv)) {
1416 argv[3] = malloc(256);
1420 ## repeat retrieve (name = filesys.#name) where filesys.#label = @label
1422 ## repeat retrieve (name = nfsphys.dir) where nfsphys.nfsphys_id = @id
1424 ## inquire_equel(rowcount = "rowcount")
1425 if (rowcount != 1) {
1426 sprintf(argv[3], "#%d", id);
1431 argv[6] = malloc(256);
1434 ## repeat retrieve (name = users.login) where users.users_id = @id
1437 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1440 ## inquire_equel(rowcount = "rowcount")
1441 if (rowcount != 1) {
1442 sprintf(argv[6], "#%d", id);
1444 (*action)(q->vcnt, argv, actarg);
1445 for (j = 0; j < q->vcnt; j++)
1450 return(SMS_SUCCESS);
1454 /* followup_anfq: Add allocation to nfsphys after creating quota.
1455 * argv[0] = filsys_id
1456 * argv[2] = ascii(quota)
1459 followup_anfq(q, argv, cl)
1464 ## int quota, user, fs, who;
1467 fs = *(int *)argv[0];
1468 user = *(int *)argv[1];
1469 quota = atoi(argv[2]);
1470 who = cl->client_id;
1471 entity = cl->entity;
1473 ## repeat replace nq (modtime = "now", modby = @who, modwith = @entity)
1474 ## where nq.filsys_id = @fs and nq.users_id = @user
1475 ## repeat replace nfsphys (allocated = nfsphys.allocated + @quota)
1476 ## where nfsphys.nfsphys_id = filesys.#phys_id and filesys.filsys_id = @fs
1477 if (ingres_errno) return(sms_errcode);
1478 return(SMS_SUCCESS);
1485 followup_gzcl(q, sq, v, action, actarg, cl)
1486 register struct query *q;
1487 register struct save_queue *sq;
1488 register struct validate *v;
1489 register int (*action)();
1494 ## int rowcount, id;
1498 while (sq_get_data(sq, &argv)) {
1499 sms_trim_args(q->vcnt, argv);
1501 id = atoi(argv[i = q->vcnt - 2]);
1503 name = argv[i] = malloc(256);
1505 ## repeat retrieve (name = users.login) where users.users_id = @id
1508 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1511 ## inquire_equel(rowcount = "rowcount")
1513 sprintf(argv[i], "#%d", id);
1515 for (i = 1; i < 8; i+=2) {
1516 id = atoi(argv[i+1]);
1518 if ((name = argv[i+1] = malloc(33)) == NULL)
1520 if (!strcmp(argv[i], "LIST")) {
1521 ## repeat retrieve (name = list.#name) where list.list_id = @id
1522 ## inquire_equel(rowcount = "rowcount")
1524 strcpy(name, "???");
1525 } else if (!strcmp(argv[i], "USER")) {
1526 ## repeat retrieve (name = users.login) where users.users_id = @id
1527 ## inquire_equel(rowcount = "rowcount")
1529 strcpy(name, "???");
1530 } else if (!strcmp(argv[i], "KERBEROS")) {
1531 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1532 ## inquire_equel(rowcount = "rowcount")
1534 strcpy(name, "???");
1535 } else if (!strcmp(argv[i], "NONE")) {
1536 strcpy(name, "NONE");
1538 strcpy(name, "???");
1543 (*action)(q->vcnt, argv, actarg);
1545 /* free saved data */
1546 for (i = 0; i < q->vcnt; i++)
1551 return(SMS_SUCCESS);
1558 followup_gsha(q, sq, v, action, actarg, cl)
1559 register struct query *q;
1560 register struct save_queue *sq;
1561 register struct validate *v;
1562 register int (*action)();
1567 ## int rowcount, id;
1571 while (sq_get_data(sq, &argv)) {
1572 sms_trim_args(q->vcnt, argv);
1576 name = argv[4] = malloc(256);
1578 ## repeat retrieve (name = users.login) where users.users_id = @id
1581 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1584 ## inquire_equel(rowcount = "rowcount")
1586 sprintf(argv[4], "#%d", id);
1590 if ((name = argv[2] = malloc(33)) == NULL)
1592 if (!strcmp(argv[1], "LIST")) {
1593 ## repeat retrieve (name = list.#name) where list.list_id = @id
1594 ## inquire_equel(rowcount = "rowcount")
1596 strcpy(name, "???");
1597 } else if (!strcmp(argv[1], "USER")) {
1598 ## repeat retrieve (name = users.login) where users.users_id = @id
1599 ## inquire_equel(rowcount = "rowcount")
1601 strcpy(name, "???");
1602 } else if (!strcmp(argv[1], "KERBEROS")) {
1603 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1604 ## inquire_equel(rowcount = "rowcount")
1606 strcpy(name, "???");
1607 } else if (!strcmp(argv[1], "NONE")) {
1608 strcpy(name, "NONE");
1610 strcpy(name, "???");
1614 (*action)(q->vcnt, argv, actarg);
1616 /* free saved data */
1617 for (i = 0; i < q->vcnt; i++)
1622 return(SMS_SUCCESS);
1627 /* Special query routines */
1629 /* set_pobox - this does all of the real work.
1630 * argv = user_id, type, box
1631 * if type is POP, then box should be a machine, and its ID should be put in
1632 * pop_id. If type is SMTP, then box should be a string and its ID should
1633 * be put in box_id. If type is NONE, then box doesn't matter.
1636 int set_pobox(q, argv, cl)
1641 ## int user, id, rowcount;
1642 ## char *box, potype[9];
1645 user = *(int *)argv[0];
1647 ## repeat retrieve (id = users.pop_id, potype = users.#potype)
1648 ## where users.users_id = @user
1649 if (ingres_errno) return(sms_errcode);
1650 if (!strcmp(strtrim(potype), "POP"))
1651 set_pop_usage(id, -1);
1653 if (!strcmp(argv[1], "POP")) {
1654 ## repeat retrieve (id=machine.mach_id) where machine.name=uppercase(@box)
1655 ## inquire_equel(rowcount = "rowcount")
1657 return(SMS_MACHINE);
1658 ## repeat replace users (#potype = "POP", pop_id = @id)
1659 ## where users.users_id = @user
1660 set_pop_usage(id, 1);
1661 } else if (!strcmp(argv[1], "SMTP")) {
1662 if (index(box, '/') || index(box, '|'))
1663 return(SMS_BAD_CHAR);
1664 ## range of s is strings
1665 ## repeat retrieve (id = s.string_id) where s.string = @box
1666 ## inquire_equel (rowcount = "rowcount")
1667 if (rowcount == 0) {
1668 ## range of v is values
1669 ## repeat retrieve (id = v.value) where v.name = "strings_id"
1671 ## repeat replace v (value = @id) where v.name = "strings_id"
1672 ## append to strings (string_id = id, string = box)
1674 ## repeat replace users (#potype = "SMTP", box_id = @id)
1675 ## where users.users_id = @user
1676 } else /* argv[1] == "NONE" */ {
1677 ## repeat replace users (#potype = "NONE") where users.users_id = @user
1680 set_pobox_modtime(q, argv, cl);
1681 ## repeat replace tblstats (updates = tblstats.updates + 1, modtime = "now")
1682 ## where tblstats.#table = "users"
1683 if (ingres_errno) return(sms_errcode);
1684 return(SMS_SUCCESS);
1688 /* get_list_info: passed a wildcard list name, returns lots of stuff about
1689 * each list. This is tricky: first build a queue of all requested
1690 * data. Rest of processing consists of fixing gid, ace_name, and modby.
1693 get_list_info(q, aargv, cl, action, actarg)
1694 register struct query *q;
1697 register int (*action)();
1700 char *argv[13], *malloc(), *realloc();
1701 ## char *name, acl_type[9], listname[33], active[5], public[5], hidden[5];
1702 ## char maillist[5], group[5], gid[6], acl_name[256], desc[256], modtime[27];
1703 ## char modby[256], modwith[9];
1704 ## int id, rowcount, acl_id, hid, modby_id;
1706 struct save_queue *sq, *sq_create();
1708 returned = rowcount = 0;
1712 ## range of l is list
1713 ## repeat retrieve (id = l.list_id) where l.#name = @name {
1714 sq_save_data(sq, id);
1717 if (ingres_errno) return(sms_errcode);
1719 return(SMS_NO_MATCH);
1721 argv[0] = listname; argv[1] = active; argv[2] = public; argv[3] = hidden;
1722 argv[4] = maillist; argv[5] = group; argv[6] = gid; argv[7] = acl_type;
1723 argv[8] = acl_name; argv[9] = desc; argv[10] = modtime; argv[11] = modby;
1726 while (sq_get_data(sq, &id)) {
1730 ## repeat retrieve (listname = l.#name, active = text(l.#active),
1731 ## public = text(l.#public), hidden = text(l.#hidden),
1732 ## hid = l.#hidden, maillist = text(l.#maillist),
1733 ## group = text(l.#group), gid = text(l.#gid),
1734 ## acl_type = trim(l.#acl_type), acl_id = l.#acl_id,
1735 ## desc = l.#desc, modtime = l.#modtime, modby_id = l.#modby,
1736 ## modwith =l.#modwith)
1737 ## where l.list_id = @id
1738 if (ingres_errno) return(sms_errcode);
1740 if (atoi(gid) == -1)
1741 argv[6] = UNIQUE_GID;
1743 if (!strcmp(acl_type, "LIST")) {
1744 ## repeat retrieve (acl_name = l.#name) where l.list_id = @acl_id
1745 ## inquire_equel(rowcount = "rowcount")
1747 strcpy(acl_name, "???");
1748 } else if (!strcmp(acl_type, "USER")) {
1749 ## repeat retrieve (acl_name = users.#login)
1750 ## where users.users_id = @acl_id
1751 ## inquire_equel(rowcount = "rowcount")
1753 strcpy(acl_name, "???");
1754 } else if (!strcmp(acl_type, "KERBEROS")) {
1755 ## repeat retrieve (acl_name = strings.string)
1756 ## where strings.string_id = @acl_id
1757 ## inquire_equel(rowcount = "rowcount")
1759 strcpy(acl_name, "???");
1760 } else if (!strcmp(acl_type, "NONE")) {
1761 strcpy(acl_name, "NONE");
1763 strcpy(acl_name, "???");
1766 ## repeat retrieve (modby = users.login) where users.users_id = @modby_id
1768 modby_id = -modby_id;
1769 ## repeat retrieve (modby = strings.string)
1770 ## where strings.string_id = @modby_id
1771 modby_id = -modby_id;
1773 ## inquire_equel(rowcount = "rowcount")
1775 sprintf(modby, "#%d", modby_id);
1776 if (ingres_errno) return(sms_errcode);
1778 sms_trim_args(q->vcnt, argv);
1780 (*action)(q->vcnt, argv, actarg);
1784 if (ingres_errno) return(sms_errcode);
1785 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
1786 ## where tblstats.#table = "list"
1788 return (SMS_SUCCESS);
1792 /* Add_member_to_list: do list flattening as we go! MAXLISTDEPTH is
1793 * how many different ancestors a member is allowed to have.
1796 #define MAXLISTDEPTH 100
1798 int add_member_to_list(q, argv, cl)
1803 ## int id, lid, mid, exists, error, who, ref;
1804 ## char *mtype, dtype[9], buf[256], *entity;
1805 int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a;
1806 int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d;
1807 char *dtypes[MAXLISTDEPTH];
1810 ## range of m is imembers
1811 lid = *(int *)argv[0];
1813 mid = *(int *)argv[2];
1814 /* if the member is already a direct member of the list, punt */
1815 ## repeat retrieve (exists = any(m.list_id where m.list_id=@lid and
1816 ## m.member_id = @mid and m.member_type = @mtype
1817 ## and m.direct = 1))
1820 if (!strcasecmp(mtype, "STRING")) {
1821 ## repeat retrieve (buf = strings.string) where strings.string_id = @mid
1822 if (index(buf, '/') || index(buf, '|'))
1823 return(SMS_BAD_CHAR);
1829 ## repeat retrieve (id = m.list_id, ref = m.ref_count)
1830 ## where m.member_id = @lid and m.member_type = "LIST" {
1832 ancestors[acount++] = id;
1833 if (acount >= MAXLISTDEPTH) {
1837 if (ingres_errno) return(sms_errcode);
1838 if (acount >= MAXLISTDEPTH) {
1839 return(SMS_INTERNAL);
1841 descendants[0] = mid;
1846 if (!strcmp(mtype, "LIST")) {
1847 ## repeat retrieve (id = m.member_id, dtype = m.member_type,
1848 ## ref = m.ref_count)
1849 ## where m.list_id = @mid {
1852 dtypes[dcount] = "LIST";
1855 dtypes[dcount] = "USER";
1858 dtypes[dcount] = "STRING";
1861 dtypes[dcount] = "KERBEROS";
1868 descendants[dcount++] = id;
1869 if (dcount >= MAXLISTDEPTH) {
1874 if (ingres_errno) return(sms_errcode);
1876 return(SMS_INTERNAL);
1878 for (a = 0; a < acount; a++) {
1880 for (d = 0; d < dcount; d++) {
1881 mid = descendants[d];
1883 if (mid == lid && !strcmp(mtype, "LIST")) {
1884 return(SMS_LISTLOOP);
1886 ## repeat retrieve (exists = any(m.ref_count where m.list_id = @lid
1887 ## and m.member_id = @mid
1888 ## and m.member_type = @mtype))
1889 ref = aref[a] * dref[d];
1891 if (a == 0 && d == 0)
1892 ## replace m (ref_count = m.ref_count+ref, direct = 1)
1893 ## where m.list_id = lid and m.member_id = mid and
1894 ## m.member_type = mtype
1896 ## replace m (ref_count = m.ref_count+ref)
1897 ## where m.list_id = lid and m.member_id = mid and
1898 ## m.member_type = mtype
1900 incremental_clear_before();
1901 if (a == 0 && d == 0)
1902 ## append imembers (list_id=lid, member_id = mid, direct = 1,
1903 ## member_type=mtype, ref_count = 1)
1905 ## append imembers (list_id=lid, member_id = mid,
1906 ## member_type=mtype, ref_count = ref)
1907 iargv[0] = (char *)lid;
1909 iargv[2] = (char *)mid;
1910 incremental_after("members", 0, iargv);
1914 lid = *(int *)argv[0];
1915 entity = cl->entity;
1916 who = cl->client_id;
1917 ## repeat replace list (modtime = "now", modby = @who, modwith = @entity)
1918 ## where list.#list_id = @lid
1919 if (ingres_errno) return(sms_errcode);
1920 return(SMS_SUCCESS);
1924 /* Delete_member_from_list: do list flattening as we go!
1927 int delete_member_from_list(q, argv, cl)
1932 ## int id, lid, mid, cnt, exists, error, who, ref;
1933 ## char *mtype, dtype[9], *entity;
1934 int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a;
1935 int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d;
1936 char *dtypes[MAXLISTDEPTH];
1939 ## range of m is imembers
1940 lid = *(int *)argv[0];
1942 mid = *(int *)argv[2];
1943 /* if the member is not a direct member of the list, punt */
1944 ## repeat retrieve (exists = any(m.list_id where m.list_id=@lid and
1945 ## m.member_id = @mid and m.member_type = @mtype
1946 ## and m.direct = 1))
1947 if (ingres_errno) return(sms_errcode);
1949 return(SMS_NO_MATCH);
1953 ## repeat retrieve (id = m.list_id, ref = m.ref_count)
1954 ## where m.member_id = @lid and m.member_type = "LIST" {
1956 ancestors[acount++] = id;
1957 if (acount >= MAXLISTDEPTH)
1960 if (ingres_errno) return(sms_errcode);
1961 if (acount >= MAXLISTDEPTH)
1962 return(SMS_INTERNAL);
1963 descendants[0] = mid;
1968 if (!strcmp(mtype, "LIST")) {
1969 ## repeat retrieve (id = m.member_id, dtype = m.member_type,
1970 ## ref = m.ref_count)
1971 ## where m.list_id = @mid {
1974 dtypes[dcount] = "LIST";
1977 dtypes[dcount] = "USER";
1980 dtypes[dcount] = "STRING";
1983 dtypes[dcount] = "KERBEROS";
1990 descendants[dcount++] = id;
1991 if (dcount >= MAXLISTDEPTH)
1994 if (ingres_errno) return(sms_errcode);
1996 return(SMS_INTERNAL);
1998 for (a = 0; a < acount; a++) {
2000 for (d = 0; d < dcount; d++) {
2001 mid = descendants[d];
2003 if (mid == lid && !strcmp(mtype, "LIST")) {
2004 return(SMS_LISTLOOP);
2006 ## repeat retrieve (cnt = m.ref_count)
2007 ## where m.list_id = @lid and m.member_id = @mid
2008 ## and m.member_type = @mtype
2009 ref = aref[a] * dref[d];
2011 iargv[0] = (char *)lid;
2013 iargv[2] = (char *)mid;
2014 incremental_before("members", 0, iargv);
2015 ## delete m where m.list_id = lid and m.member_id = mid and
2016 ## m.member_type = mtype
2017 incremental_clear_after();
2018 } else if (a == 0 && d == 0) {
2019 ## replace m (ref_count = m.ref_count-ref, direct = 0)
2020 ## where m.list_id = lid and m.member_id = mid and
2021 ## m.member_type = mtype
2023 ## replace m (ref_count = m.ref_count-ref)
2024 ## where m.list_id = lid and m.member_id = mid and
2025 ## m.member_type = mtype
2029 lid = *(int *)argv[0];
2030 entity = cl->entity;
2031 who = cl->client_id;
2032 ## repeat replace list (modtime = "now", modby = @who, modwith = @entity)
2033 ## where list.#list_id = @lid
2034 if (ingres_errno) return(sms_errcode);
2035 return(SMS_SUCCESS);
2039 /* get_ace_use - given a type and a name, return a type and a name.
2040 * The ace_type is one of "LIST", "USER", "RLIST", or "RUSER" in argv[0],
2041 * and argv[1] will contain the ID of the entity in question. The R*
2042 * types mean to recursively look at every containing list, not just
2043 * when the object in question is a direct member. On return, the
2044 * usage type will be one of LIST, SERVICE, FILESYS, QUOTA, QUERY, or ZEPHYR.
2047 int get_ace_use(q, argv, cl, action, actarg)
2056 ## int aid, listid, id;
2057 struct save_queue *sq, *sq_create();
2059 ## range of m is imembers
2061 aid = *(int *)argv[1];
2062 if (!strcmp(atype, "LIST") || !strcmp(atype, "USER") ||
2063 !strcmp(atype, "KERBEROS")) {
2064 return(get_ace_internal(atype, aid, action, actarg));
2068 if (!strcmp(atype, "RLIST")) {
2069 sq_save_data(sq, aid);
2070 /* get all the list_id's of containing lists */
2071 ## range of m is imembers
2072 ## repeat retrieve (listid = m.list_id)
2073 ## where m.member_type = "LIST" and m.member_id = @id {
2074 sq_save_unique_data(sq, listid);
2076 /* now process each one */
2077 while (sq_get_data(sq, &id)) {
2078 if (get_ace_internal("LIST", id, action, actarg) == SMS_SUCCESS)
2083 if (!strcmp(atype, "RUSER")) {
2084 ## repeat retrieve (listid = m.list_id)
2085 ## where m.member_type = "USER" and m.member_id = @aid {
2086 sq_save_data(sq, listid);
2088 /* now process each one */
2089 while (sq_get_data(sq, &id)) {
2090 if (get_ace_internal("LIST", id, action, actarg) == SMS_SUCCESS)
2093 if (get_ace_internal("USER", aid, action, actarg) == SMS_SUCCESS)
2097 if (!strcmp(atype, "RKERBERO")) {
2098 ## repeat retrieve (listid = m.list_id)
2099 ## where m.member_type = "KERBEROS" and m.member_id = @aid {
2100 sq_save_data(sq, listid);
2102 /* now process each one */
2103 while (sq_get_data(sq, &id)) {
2104 if (get_ace_internal("LIST", id, action, actarg) == SMS_SUCCESS)
2107 if (get_ace_internal("KERBEROS", aid, action, actarg) == SMS_SUCCESS)
2112 if (ingres_errno) return(sms_errcode);
2113 if (!found) return(SMS_NO_MATCH);
2114 return(SMS_SUCCESS);
2118 /* This looks up a single list or user for ace use. atype must be "USER"
2119 * or "LIST", and aid is the ID of the corresponding object. This is used
2120 * by get_ace_use above.
2123 ##get_ace_internal(atype, aid, action, actarg)
2134 if (!strcmp(atype, "LIST")) {
2135 rargv[0] = "FILESYS";
2136 ## repeat retrieve (name = filesys.label)
2137 ## where filesys.owners = @aid {
2138 (*action)(2, rargv, actarg);
2143 ## repeat retrieve (name = capacls.capability)
2144 ## where capacls.list_id = @aid {
2145 (*action)(2, rargv, actarg);
2148 } else if (!strcmp(atype, "USER")) {
2149 rargv[0] = "FILESYS";
2150 ## repeat retrieve (name = filesys.label)
2151 ## where filesys.owner = @aid {
2152 (*action)(2, rargv, actarg);
2158 ## repeat retrieve (name = list.#name)
2159 ## where list.acl_type = @atype and list.acl_id = @aid {
2160 (*action)(2, rargv, actarg);
2164 rargv[0] = "SERVICE";
2165 ## repeat retrieve (name = servers.#name)
2166 ## where servers.acl_type = @atype and servers.acl_id = @aid {
2167 (*action)(2, rargv, actarg);
2171 rargv[0] = "HOSTACCESS";
2172 ## repeat retrieve (name = machine.#name)
2173 ## where machine.mach_id = hostaccess.mach_id and
2174 ## hostaccess.acl_type = @atype and hostaccess.acl_id = @aid {
2175 (*action)(2, rargv, actarg);
2178 rargv[0] = "ZEPHYR";
2179 ## repeat retrieve (name = zephyr.class)
2180 ## where zephyr.xmt_type = @atype and zephyr.xmt_id = @aid or
2181 ## zephyr.sub_type = @atype and zephyr.sub_id = @aid or
2182 ## zephyr.iws_type = @atype and zephyr.iws_id = @aid or
2183 ## zephyr.iui_type = @atype and zephyr.iui_id = @aid {
2184 (*action)(2, rargv, actarg);
2188 if (!found) return(SMS_NO_MATCH);
2189 return(SMS_SUCCESS);
2193 /* get_lists_of_member - given a type and a name, return the name and flags
2194 * of all of the lists of the given member. The member_type is one of
2195 * "LIST", "USER", "STRING", "RLIST", "RUSER", or "RSTRING" in argv[0],
2196 * and argv[1] will contain the ID of the entity in question. The R*
2197 * types mean to recursively look at every containing list, not just
2198 * when the object in question is a direct member.
2201 int get_lists_of_member(q, argv, cl, action, actarg)
2208 int found = 0, direct = 1;
2211 ## int aid, listid, id;
2212 ## char name[33], active[5], public[5], hidden[5], maillist[5], group[5];
2215 aid = *(int *)argv[1];
2216 if (!strcmp(atype, "RLIST")) {
2220 if (!strcmp(atype, "RUSER")) {
2224 if (!strcmp(atype, "RSTRING")) {
2228 if (!strcmp(atype, "RKERBEROS")) {
2237 rargv[4] = maillist;
2239 ## range of m is imembers
2241 ## repeat retrieve (name = list.#name, active = text(list.#active),
2242 ## public = text(list.#public), hidden = text(list.#hidden),
2243 ## maillist = text(list.#maillist), group = text(list.#group))
2244 ## where list.list_id = m.list_id and m.direct = 1 and
2245 ## m.member_type = @atype and m.member_id = @aid {
2246 (*action)(6, rargv, actarg);
2250 ## repeat retrieve (name = list.#name, active = text(list.#active),
2251 ## public = text(list.#public), hidden = text(list.#hidden),
2252 ## maillist = text(list.#maillist), group = text(list.#group))
2253 ## where list.list_id = m.list_id and
2254 ## m.member_type = @atype and m.member_id = @aid {
2255 (*action)(6, rargv, actarg);
2260 if (ingres_errno) return(sms_errcode);
2261 if (!found) return(SMS_NO_MATCH);
2262 return(SMS_SUCCESS);
2266 /* qualified_get_lists: passed "TRUE", "FALSE", or "DONTCARE" for each of
2267 * the five flags associated with each list. It will return the name of
2268 * each list that meets the quailifications. It does this by building a
2269 * where clause based on the arguments, then doing a retrieve.
2272 static char *lflags[5] = { "active", "public", "hidden", "maillist", "group" };
2274 int qualified_get_lists(q, argv, cl, action, actarg)
2281 return(qualified_get(q, argv, action, actarg, "l.list_id != 0",
2282 "l", "name", lflags));
2286 /** get_members_of_list - optimized query for retrieval of list members
2289 ** argv[0] - list_id
2292 ** - retrieve USER members, then LIST members, then STRING members
2295 get_members_of_list(q, argv, cl, action, actarg)
2303 ## char member_name[129];
2306 list_id = *(int *)argv[0];
2308 targv[1] = member_name;
2310 ## range of m is imembers
2311 ## repeat retrieve (member_name = users.login)
2312 ## where m.#list_id = @list_id and m.member_type = "USER"
2313 ## and m.member_id = users.users_id and m.direct = 1
2314 ## sort by #member_name
2316 (*action)(2, targv, actarg);
2318 if (ingres_errno) return(sms_errcode);
2321 ## repeat retrieve (member_name = list.name)
2322 ## where m.#list_id = @list_id and m.member_type = "LIST"
2323 ## and m.member_id = list.#list_id and m.direct = 1
2324 ## sort by #member_name
2326 (*action)(2, targv, actarg);
2328 if (ingres_errno) return(sms_errcode);
2330 targv[0] = "STRING";
2331 ## repeat retrieve (member_name = strings.string)
2332 ## where m.#list_id = @list_id and m.member_type = "STRING"
2333 ## and m.member_id = strings.string_id and m.direct = 1
2334 ## sort by #member_name
2336 (*action)(2, targv, actarg);
2338 if (ingres_errno) return(sms_errcode);
2340 targv[0] = "KERBEROS";
2341 ## repeat retrieve (member_name = strings.string)
2342 ## where m.#list_id = @list_id and m.member_type = "KERBEROS"
2343 ## and m.member_id = strings.string_id and m.direct = 1
2344 ## sort by #member_name
2346 (*action)(2, targv, actarg);
2348 if (ingres_errno) return(sms_errcode);
2350 return(SMS_SUCCESS);
2354 /* count_members_of_list: this is a simple query, but it cannot be done
2355 * through the dispatch table.
2358 int count_members_of_list(q, argv, cl, action, actarg)
2365 ## int list, ct = 0;
2366 char *rargv[1], countbuf[5];
2368 list = *(int *)argv[0];
2369 rargv[0] = countbuf;
2370 ## repeat retrieve (ct = count(imembers.list_id
2371 ## where imembers.list_id = @list and
2372 ## imembers.direct = 1))
2373 if (ingres_errno) return(sms_errcode);
2374 sprintf(countbuf, "%d", ct);
2375 (*action)(1, rargv, actarg);
2376 return(SMS_SUCCESS);
2380 /* qualified_get_server: passed "TRUE", "FALSE", or "DONTCARE" for each of
2381 * the three flags associated with each service. It will return the name of
2382 * each service that meets the quailifications. It does this by building a
2383 * where clause based on the arguments, then doing a retrieve.
2386 static char *sflags[3] = { "enable", "inprogress", "harderror" };
2388 int qualified_get_server(q, argv, cl, action, actarg)
2395 return(qualified_get(q, argv, action, actarg, "s.name != \"\"",
2396 "s", "name", sflags));
2400 /* generic qualified get routine, used by qualified_get_lists,
2401 * qualified_get_server, and qualified_get_serverhost.
2403 * start - a simple where clause, must not be empty
2404 * range - the name of the range variable
2405 * field - the field to return
2406 * flags - an array of strings, names of the flag variables
2409 int qualified_get(q, argv, action, actarg, start, range, field, flags)
2419 ## char name[33], qual[256], *rvar, *rtbl, *rfield;
2420 char *rargv[1], buf[32];
2423 strcpy(qual, start);
2424 for (i = 0; i < q->argc; i++) {
2425 if (!strcmp(argv[i], "TRUE")) {
2426 sprintf(buf, " and %s.%s != 0", range, flags[i]);
2427 (void) strcat(qual, buf);
2428 } else if (!strcmp(argv[i], "FALSE")) {
2429 sprintf(buf, " and %s.%s = 0", range, flags[i]);
2430 (void) strcat(qual, buf);
2438 ## range of rvar is rtbl
2439 ## retrieve (name = rvar.rfield) where qual {
2440 (*action)(1, rargv, actarg);
2442 if (ingres_errno) return(sms_errcode);
2443 ## inquire_equel(rowcount = "rowcount")
2444 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
2445 ## where tblstats.#table = @rtbl
2447 return(SMS_NO_MATCH);
2448 return(SMS_SUCCESS);
2452 /* qualified_get_serverhost: passed "TRUE", "FALSE", or "DONTCARE" for each of
2453 * the five flags associated with each serverhost. It will return the name of
2454 * each service and host that meets the quailifications. It does this by
2455 * building a where clause based on the arguments, then doing a retrieve.
2458 static char *shflags[6] = { "service", "enable", "override", "success",
2459 "inprogress", "hosterror" };
2461 int qualified_get_serverhost(q, argv, cl, action, actarg)
2468 ## char sname[33], mname[33], qual[256];
2469 char *rargv[2], buf[32];
2472 sprintf(qual, "machine.mach_id = sh.mach_id and sh.service = uppercase(\"%s\")",
2474 for (i = 1; i < q->argc; i++) {
2475 if (!strcmp(argv[i], "TRUE")) {
2476 sprintf(buf, " and sh.%s != 0", shflags[i]);
2478 } else if (!strcmp(argv[i], "FALSE")) {
2479 sprintf(buf, " and sh.%s = 0", shflags[i]);
2486 ## range of sh is serverhosts
2487 ## retrieve (sname = sh.service, mname = machine.name) where qual {
2488 (*action)(2, rargv, actarg);
2490 if (ingres_errno) return(sms_errcode);
2491 ## inquire_equel(rowcount = "rowcount")
2492 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
2493 ## where tblstats.#table = "serverhosts"
2495 return(SMS_NO_MATCH);
2496 return(SMS_SUCCESS);
2500 /* register_user - change user's login name and allocate a pobox, group,
2501 * filesystem, and quota for them. The user's status must start out as 0,
2502 * and is left as 2. Arguments are: user's UID, new login name, and user's
2503 * type for filesystem allocation (SMS_FS_STUDENT, SMS_FS_FACULTY,
2504 * SMS_FS_STAFF, SMS_FS_MISC).
2507 register_user(q, argv, cl)
2512 ## char *login, dir[65], *entity, *directory, machname[33];
2513 ## int who, rowcount, mid, uid, users_id, flag, utype, nid, list_id, quota;
2514 ## int size, alloc, pid, m_id;
2515 char buffer[256], *aargv[3];
2518 entity = cl->entity;
2519 who = cl->client_id;
2521 uid = atoi(argv[0]);
2523 utype = atoi(argv[2]);
2525 ## range of u is users
2526 ## range of l is list
2527 ## range of sh is serverhosts
2528 ## range of n is nfsphys
2529 ## range of m is machine
2532 ## repeat retrieve (users_id = u.#users_id)
2533 ## where u.#uid = @uid and (u.status = 0 or u.status = 5)
2534 ## inquire_equel(rowcount = "rowcount");
2536 return(SMS_NO_MATCH);
2538 return(SMS_NOT_UNIQUE);
2540 /* check new login name */
2541 ## repeat retrieve (flag = any(u.#login where u.#login = @login and
2542 ## u.#users_id != users_id))
2543 if (ingres_errno) return(sms_errcode);
2544 if (flag) return(SMS_IN_USE);
2545 ## repeat retrieve (flag = any(l.#name where l.#name = @login))
2546 if (ingres_errno) return(sms_errcode);
2547 if (flag) return(SMS_IN_USE);
2548 ## repeat retrieve (flag = any(filesys.#label where filesys.#label = @login))
2549 if (ingres_errno) return(sms_errcode);
2550 if (flag) return(SMS_IN_USE);
2551 com_err(whoami, 0, "new login name OK");
2553 /* choose place for pobox, put in mid */
2554 ## repeat retrieve (mid = sh.mach_id, machname = m.name)
2555 ## where sh.service = "POP" and m.mach_id = sh.mach_id and
2556 ## sh.value2 - sh.value1 = max(sh.value2-sh.value1 where sh.service="POP")
2557 if (ingres_errno) return(sms_errcode);
2558 ## inquire_equel(rowcount = "rowcount");
2560 return(SMS_NO_POBOX);
2562 /* change login name, set pobox */
2563 sprintf(buffer, "u.users_id = %d", users_id);
2564 incremental_before("users", buffer, 0);
2565 ## repeat replace u (#login = @login, status = 2, modtime = "now",
2566 ## modby = @who, modwith = @entity, potype="POP",
2567 ## pop_id = @mid, pmodtime="now", pmodby=@who,
2568 ## pmodwith=@entity)
2569 ## where u.#users_id = @users_id
2570 ## inquire_equel(rowcount = "rowcount");
2571 if (ingres_errno) return(sms_errcode);
2573 return(SMS_INTERNAL);
2574 set_pop_usage(mid, 1);
2575 com_err(whoami, 0, "set login name to %s and pobox to %s", login,
2577 incremental_after("users", buffer, 0);
2579 /* create group list */
2580 if (set_next_object_id("gid", "list"))
2582 if (set_next_object_id("list_id", "list"))
2584 ## repeat retrieve (list_id = values.value) where values.name = "list_id"
2585 if (ingres_errno) return(sms_errcode);
2586 ## inquire_equel(rowcount = "rowcount");
2588 return(SMS_INTERNAL);
2589 incremental_clear_before();
2590 ## repeat append list (name = @login, #list_id = @list_id, active = 1,
2591 ## public = 0, hidden = 0, maillist = 0, group = 1,
2592 ## #gid = values.value, desc = "User Group",
2593 ## acl_type = "USER", acl_id = @users_id, modtime = "now",
2594 ## modby = @who, modwith = @entity)
2595 ## where values.name = "gid"
2596 if (ingres_errno) return(sms_errcode);
2597 ## inquire_equel(rowcount = "rowcount");
2599 return(SMS_INTERNAL);
2600 sprintf(buffer, "l.list_id = %d", list_id);
2601 incremental_after("list", buffer, 0);
2602 aargv[0] = (char *) list_id;
2604 aargv[2] = (char *) users_id;
2605 incremental_clear_before();
2606 ## repeat append imembers (#list_id = @list_id, member_type = "USER",
2607 ## member_id = @users_id, ref_count = 1, direct = 1)
2608 if (ingres_errno) return(sms_errcode);
2609 ## inquire_equel(rowcount = "rowcount");
2611 return(SMS_INTERNAL);
2612 incremental_after("members", 0, aargv);
2613 com_err(whoami, 0, "group list created");
2615 /* decide where to put filesystem */
2618 ## repeat retrieve (mid = n.mach_id, dir = trim(n.#dir), nid = n.nfsphys_id,
2619 ## flag = n.status, size = n.#size, alloc = n.allocated) {
2620 if ((flag & utype) && (size != 0) && (size - alloc > maxsize)) {
2621 maxsize = size - alloc;
2624 directory = strsave(dir);
2629 if (ingres_errno) return(sms_errcode);
2631 return(SMS_NO_FILESYS);
2633 /* create filesystem */
2634 if (set_next_object_id("filsys_id", "filesys"))
2636 incremental_clear_before();
2637 ## repeat append filesys (filsys_id = values.value, phys_id = @pid,
2638 ## label = @login, type = "NFS", mach_id = @m_id,
2639 ## name = @directory + "/" + @login,
2640 ## mount = "/mit/" + @login,
2641 ## access = "w", comments = "User Locker",
2642 ## owner = @users_id, owners = @list_id, createflg = 1,
2643 ## lockertype = "HOMEDIR", modtime = "now",
2644 ## modby = @who, modwith = @entity)
2645 ## where values.name = "filsys_id"
2646 if (ingres_errno) return(sms_errcode);
2647 ## inquire_equel(rowcount = "rowcount");
2649 return(SMS_INTERNAL);
2650 incremental_after("filesys",
2651 "fs.filsys_id = values.value and values.name = \"filsys_id\"",
2653 com_err(whoami, 0, "filesys created on mach %d in %s/%s", m_id,
2657 ## repeat retrieve (quota = values.value) where values.name = "def_quota"
2658 if (ingres_errno) return(sms_errcode);
2659 ## inquire_equel(rowcount = "rowcount");
2661 return(SMS_NO_QUOTA);
2662 incremental_clear_before();
2663 ## repeat append nfsquota (#users_id = @users_id, filsys_id = values.value,
2664 ## #quota = @quota, phys_id = @pid, modtime = "now",
2665 ## modby = @who, modwith = @entity)
2666 ## where values.name = "filsys_id"
2667 if (ingres_errno) return(sms_errcode);
2668 ## inquire_equel(rowcount = "rowcount");
2670 return(SMS_INTERNAL);
2671 ## repeat replace nfsphys (allocated = nfsphys.allocated + @quota)
2672 ## where nfsphys.nfsphys_id = filesys.#phys_id and
2673 ## filesys.filsys_id = values.value and values.name = "filsys_id"
2674 if (ingres_errno) return(sms_errcode);
2675 ## inquire_equel(rowcount = "rowcount");
2677 return(SMS_INTERNAL);
2680 sprintf(buffer, "nq.users_id = %d and nq.filsys_id = values.value and values.name = \"filsys_id\"", users_id);
2681 incremental_after("nfsquota", buffer, aargv);
2682 com_err(whoami, 0, "quota of %d assigned", quota);
2683 if (ingres_errno) return(sms_errcode);
2685 ## repeat replace tblstats (updates = tblstats.updates + 1, modtime = "now")
2686 ## where tblstats.table = "users"
2687 ## repeat replace tblstats (appends = tblstats.appends + 1, modtime = "now")
2688 ## where tblstats.table = "list" or tblstats.table = "filesys" or
2689 ## tblstats.table = "nfsquota"
2690 if (ingres_errno) return(sms_errcode);
2691 return(SMS_SUCCESS);
2696 /** set_pop_usage - incr/decr usage count for pop server in serverhosts talbe
2700 ** delta (will be +/- 1)
2703 ** - incr/decr value field in serverhosts table for pop/mach_id
2707 static int set_pop_usage(id, count)
2711 ## int mach_id = id;
2714 ## range of sh is serverhosts
2715 ## repeat replace sh (value1 = sh.value1 + @n)
2716 ## where sh.service = "POP" and sh.#mach_id = @mach_id
2718 if (ingres_errno) return(sms_errcode);
2719 return(SMS_SUCCESS);
2724 /* Validation Routines */
2726 validate_row(q, argv, v)
2727 register struct query *q;
2729 register struct validate *v;
2737 /* build where clause */
2738 build_qual(v->qual, v->argc, argv, qual);
2740 /* setup ingres variables */
2745 if (log_flags & LOG_VALID)
2746 /* tell the logfile what we're doing */
2747 com_err(whoami, 0, "validating row: %s", qual);
2749 /* look for the record */
2750 ## range of rvar is table
2751 ## retrieve (rowcount = count(rvar.name where qual))
2752 if (ingres_errno) return(sms_errcode);
2753 if (rowcount == 0) return(SMS_NO_MATCH);
2754 if (rowcount > 1) return(SMS_NOT_UNIQUE);
2758 validate_fields(q, argv, vo, n)
2760 register char *argv[];
2761 register struct valobj *vo;
2764 register int status;
2769 if (log_flags & LOG_VALID)
2770 com_err(whoami, 0, "validating %s in %s: %s",
2771 vo->namefield, vo->table, argv[vo->index]);
2772 status = validate_name(argv, vo);
2776 if (log_flags & LOG_VALID)
2777 com_err(whoami, 0, "validating %s in %s: %s",
2778 vo->idfield, vo->table, argv[vo->index]);
2779 status = validate_id(argv, vo);
2783 if (log_flags & LOG_VALID)
2784 com_err(whoami, 0, "validating date: %s", argv[vo->index]);
2785 status = validate_date(argv, vo);
2789 if (log_flags & LOG_VALID)
2790 com_err(whoami, 0, "validating %s type: %s",
2791 vo->table, argv[vo->index]);
2792 status = validate_type(argv, vo);
2796 if (log_flags & LOG_VALID)
2797 com_err(whoami, 0, "validating typed data (%s): %s",
2798 argv[vo->index - 1], argv[vo->index]);
2799 status = validate_typedata(q, argv, vo);
2803 if (log_flags & LOG_VALID)
2804 com_err(whoami, 0, "validating rename %s in %s",
2805 argv[vo->index], vo->table);
2806 status = validate_rename(argv, vo);
2810 if (log_flags & LOG_VALID)
2811 com_err(whoami, 0, "validating chars: %s", argv[vo->index]);
2812 status = validate_chars(argv[vo->index]);
2816 status = SMS_EXISTS;
2820 status = lock_table(vo);
2824 if (status != SMS_EXISTS) return(status);
2828 if (ingres_errno) return(sms_errcode);
2829 return(SMS_SUCCESS);
2833 /* validate_chars: verify that there are no illegal characters in
2834 * the string. Legal characters are printing chars other than
2835 * ", *, ?, \, [ and ].
2837 static int illegalchars[] = {
2838 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
2839 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
2840 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
2841 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
2842 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ - O */
2843 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* P - _ */
2844 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
2845 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
2846 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2847 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2848 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2849 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2850 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2851 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2852 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2853 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2860 if (illegalchars[*s++])
2861 return(SMS_BAD_CHAR);
2866 validate_id(argv, vo)
2868 register struct valobj *vo;
2878 name = argv[vo->index];
2880 /* minor kludge to upcasify machine names */
2881 if (!strcmp(table, "machine"))
2882 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
2883 namefield = vo->namefield;
2884 idfield = vo->idfield;
2885 if (!strcmp(namefield, "uid")) {
2886 ## retrieve (id = table.idfield) where table.namefield = int4(name)
2887 if (ingres_errno) return(sms_errcode);
2888 ## inquire_equel (rowcount = "rowcount")
2890 ## retrieve (id = table.idfield) where table.namefield = name
2891 if (ingres_errno) return(sms_errcode);
2892 ## inquire_equel (rowcount = "rowcount")
2894 if (rowcount != 1) return(vo->error);
2895 *(int *)argv[vo->index] = id;
2899 validate_name(argv, vo)
2901 register struct valobj *vo;
2909 name = argv[vo->index];
2911 namefield = vo->namefield;
2912 if (!strcmp(table, "servers") && !strcmp(namefield, "name")) {
2913 for (c = name; *c; c++)
2917 ## retrieve (rowcount = countu(table.namefield
2918 ## where table.namefield = name))
2919 if (ingres_errno) return(sms_errcode);
2920 return ((rowcount == 1) ? SMS_EXISTS : vo->error);
2923 validate_date(argv, vo)
2931 idate = argv[vo->index];
2933 ## retrieve (dd = interval("years", date(idate) - date("today")))
2934 ## inquire_equel (errorno = "errorno")
2935 if (errorno != 0 || dd > 5.0) return(SMS_DATE);
2940 validate_rename(argv, vo)
2944 ## char *name, *table, *namefield, *idfield;
2948 c = name = argv[vo->index];
2950 if (illegalchars[*c++])
2951 return(SMS_BAD_CHAR);
2953 /* minor kludge to upcasify machine names */
2954 if (!strcmp(table, "machine"))
2955 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
2956 namefield = vo->namefield;
2957 idfield = vo->idfield;
2960 if (!strcmp(argv[vo->index], argv[vo->index - 1]))
2962 ## retrieve (id = any(table.namefield where table.namefield = name))
2963 if (ingres_errno) return(sms_errcode);
2969 ## retrieve (id = table.idfield) where table.namefield = name
2970 if (ingres_errno) return(sms_errcode);
2971 if (id == -1 || id == *(int *)argv[vo->index - 1])
2978 validate_type(argv, vo)
2980 register struct valobj *vo;
2987 typename = vo->table;
2988 c = value = argv[vo->index];
2990 if (illegalchars[*c++])
2991 return(SMS_BAD_CHAR);
2993 /* uppercase type fields */
2994 for (c = value; *c; c++) if (islower(*c)) *c = toupper(*c);
2996 ## range of a is alias
2997 ## repeat retrieve (exists = any(a.trans where a.name = @typename and
2998 ## a.type = "TYPE" and
2999 ## a.trans = @value))
3000 if (ingres_errno) return(sms_errcode);
3001 return (exists ? SMS_EXISTS : vo->error);
3004 /* validate member or type-specific data field */
3006 validate_typedata(q, argv, vo)
3007 register struct query *q;
3008 register char *argv[];
3009 register struct valobj *vo;
3012 ## char *field_type;
3013 ## char data_type[129];
3019 /* get named object */
3020 name = argv[vo->index];
3022 /* get field type string (known to be at index-1) */
3023 field_type = argv[vo->index-1];
3025 /* get corresponding data type associated with field type name */
3026 ## repeat retrieve (data_type = alias.trans)
3027 ## where alias.#name = @field_type and alias.type = "TYPEDATA"
3028 if (ingres_errno) return(sms_errcode);
3029 ## inquire_equel (rowcount = "rowcount")
3030 if (rowcount != 1) return(SMS_TYPE);
3032 /* now retrieve the record id corresponding to the named object */
3033 if (index(data_type, ' '))
3034 *index(data_type, ' ') = 0;
3035 if (!strcmp(data_type, "user")) {
3037 ## repeat retrieve (id = users.users_id) where users.login = @name
3038 ## inquire_equel (rowcount = "rowcount")
3039 if (rowcount != 1) return(SMS_USER);
3041 } else if (!strcmp(data_type, "list")) {
3043 ## repeat retrieve (id = list.list_id) where list.#name = @name
3044 ## inquire_equel (rowcount = "rowcount")
3045 if (rowcount != 1) {
3046 /* if idfield is non-zero, then if argv[0] matches the string
3047 * that we're trying to resolve, we should get the value of
3048 * values.[idfield] for the id.
3050 if (vo->idfield && !strcmp(argv[0], argv[vo->index])) {
3051 set_next_object_id(q->validate->object_id, q->rtable);
3053 ## repeat retrieve (id = values.value) where values.#name = @name
3054 ## inquire_equel(rowcount = "rowcount")
3055 if (rowcount != 1) return(SMS_LIST);
3059 } else if (!strcmp(data_type, "machine")) {
3061 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3062 ## repeat retrieve (id = machine.mach_id) where machine.#name = @name
3063 ## inquire_equel (rowcount = "rowcount")
3064 if (rowcount != 1) return(SMS_MACHINE);
3066 } else if (!strcmp(data_type, "string")) {
3068 ## range of s is strings
3069 ## repeat retrieve (id = s.string_id) where s.string = @name
3070 ## inquire_equel (rowcount = "rowcount")
3071 if (rowcount == 0) {
3072 if (q->type != APPEND && q->type != UPDATE) return(SMS_STRING);
3073 ## range of v is values
3074 ## retrieve (id = v.value) where v.#name = "strings_id"
3076 ## replace v (value = id) where v.#name = "strings_id"
3077 ## append to strings (string_id = id, string = name)
3079 } else if (!strcmp(data_type, "none")) {
3085 /* now set value in argv */
3086 *(int *)argv[vo->index] = id;
3088 return (SMS_EXISTS);
3092 /* Lock the table named by the validation object */
3097 ## char *table, *idfield;
3101 idfield = vo->idfield;
3102 ## replace table (modtime = "now") where table.idfield = 0
3103 if (ingres_errno) return(sms_errcode);
3104 ## inquire_equel (rowcount = "rowcount")
3112 /* Check the database at startup time. For now this just resets the
3113 * inprogress flags that the DCM uses.
3116 sanity_check_database()