6 * Copyright (C) 1987 by the Massachusetts Institute of Technology
11 static char *rcsid_qsupport_qc = "$Header$";
15 #include "sms_server.h"
19 extern char *whoami, *strsave();
22 /* Specialized Access Routines */
24 /* access_user - verify that client name equals specified login name
26 * - since field validation routines are called first, a users_id is
27 * now in argv[0] instead of the login name.
30 access_user(q, argv, cl)
35 if (cl->users_id != *(int *)argv[0])
43 /* access_login - verify that client name equals specified login name
45 * argv[0...n] contain search info. q->
48 access_login(q, argv, cl)
56 build_qual(q->qual, q->argc, argv, qual);
57 ## retrieve (id = u.users_id) where qual
58 ## inquire_equel(rowcount = "rowcount")
59 if (rowcount != 1 || id != cl->users_id)
67 /* access_list - check access for most list operations
69 * Inputs: argv[0] - list_id
71 * argv[2] - member ID (only for queries "amtl" and "dmfl")
74 * - check that client is a member of the access control list
75 * - OR, if the query is add_member_to_list or delete_member_from_list
76 * and the list is public, allow access if client = member
79 access_list(q, argv, cl)
84 ## int list_id, acl_id, flags, rowcount;
87 int client_id, status;
89 list_id = *(int *)argv[0];
90 ## repeat retrieve (acl_id = list.#acl_id, acl_type = list.#acl_type,
91 ## flags = list.#public)
92 ## where list.#list_id = @list_id
93 ## inquire_equel(rowcount = "rowcount")
97 /* parse client structure */
98 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
101 /* if amtl or dmfl and list is public allow client to add or delete self */
102 if ((!strcmp("amtl", q->shortname) || !strcmp("dmfl", q->shortname)) &&
103 (flags && !strcmp("USER", argv[1]))) {
104 if (*(int *)argv[2] == client_id) return(SMS_SUCCESS);
107 /* check for client in access control list */
108 status = find_member(acl_type, acl_id, client_type, client_id, 0);
109 if (!status) return(SMS_PERM);
115 /* access_visible_list - allow access to list only if it is not hidden,
116 * or if the client is on the ACL
118 * Inputs: argv[0] - list_id
119 * cl - client identifier
122 access_visible_list(q, argv, cl)
127 ## int list_id, acl_id, flags, rowcount;
130 int client_id, status;
132 list_id = *(int *)argv[0];
133 ## repeat retrieve (flags = list.hidden, acl_id = list.#acl_id,
134 ## acl_type = list.#acl_type) where list.#list_id = @list_id
135 ## inquire_equel(rowcount = "rowcount")
137 return(SMS_INTERNAL);
141 /* parse client structure */
142 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
145 /* check for client in access control list */
146 status = find_member(acl_type, acl_id, client_type, client_id, 0);
154 /* access_vis_list_by_name - allow access to list only if it is not hidden,
155 * or if the client is on the ACL
157 * Inputs: argv[0] - list name
158 * cl - client identifier
161 access_vis_list_by_name(q, argv, cl)
166 ## int acl_id, flags, rowcount;
167 ## char acl_type[9], *listname;
169 int client_id, status;
172 ## repeat retrieve (flags = list.hidden, acl_id = list.#acl_id,
173 ## acl_type = list.#acl_type) where list.#name = @listname
174 ## inquire_equel(rowcount = "rowcount");
176 return(SMS_WILDCARD);
178 return(SMS_NO_MATCH);
182 /* parse client structure */
183 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
186 /* check for client in access control list */
187 status = find_member(acl_type, acl_id, client_type, client_id, 0);
195 /* access_member - allow user to access member of type "USER" and name matches
196 * username, or to access member of type "LIST" and list is one that user is
197 * on the acl of, or the list is visible.
200 access_member(q, argv, cl)
205 if (!strcmp(argv[0], "LIST") || !strcmp(argv[0], "RLIST"))
206 return(access_visible_list(q, &argv[1], cl));
208 if (!strcmp(argv[0], "USER") || !strcmp(argv[0], "RUSER")) {
209 if (!strcmp(cl->kname.name, argv[1]))
217 /* access_qgli - special access routine for Qualified_get_lists. Allows
218 * access iff argv[0] == "TRUE" and argv[2] == "FALSE".
221 access_qgli(q, argv, cl)
226 if (!strcmp(argv[0], "TRUE") && !strcmp(argv[2], "FALSE"))
232 /* access_service - allow access if user is on ACL of service. Don't
233 * allow access if a wildcard is used.
236 access_service(q, argv, cl)
241 ## int acl_id, rowcount;
242 ## char *name, acl_type[9];
243 int client_id, status;
247 ## repeat retrieve (acl_id = servers.#acl_id, acl_type = servers.#acl_type)
248 ## where servers.#name = uppercase(@name)
249 ## inquire_equel(rowcount = "rowcount")
253 /* parse client structure */
254 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
257 /* check for client in access control list */
258 status = find_member(acl_type, acl_id, client_type, client_id, 0);
259 if (!status) return(SMS_PERM);
266 /* access_filesys - verify that client is owner or on owners list of filesystem
270 access_filesys(q, argv, cl)
275 ## int rowcount, users_id, list_id;
277 int status, client_id;
281 ## repeat retrieve (users_id = filesys.owner, list_id = filesys.owners)
282 ## where filesys.label = @name
283 ## inquire_equel(rowcount = "rowcount")
287 if (users_id == cl->users_id)
289 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
291 status = find_member("LIST", list_id, client_type, client_id, 0);
301 /* Setup routine for add_user
303 * Inputs: argv[0] - login
308 * - if argv[1] == UNIQUE_UID then set argv[1] = next(uid)
309 * - if argv[0] == UNIQUE_LOGIN then set argv[0] = "#<uid>"
312 setup_ausr(q, argv, cl)
314 register char *argv[];
317 ## int nuid, rowcount;
319 if (!strcmp(argv[1], UNIQUE_UID) || atoi(argv[1]) == -1) {
320 if (set_next_object_id("uid", "users"))
321 return(SMS_INGRES_ERR);
322 ## repeat retrieve (nuid = values.value) where values.name = "uid"
323 ## inquire_equel(rowcount = "rowcount")
325 return(SMS_INTERNAL);
326 sprintf(argv[1], "%d", nuid);
329 if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[1]) == -1) {
330 sprintf(argv[0], "#%s", argv[1]);
337 /* setup_dusr - verify that the user is no longer being referenced
338 * and may safely be deleted.
341 int setup_dusr(q, argv)
347 id = *(int *)argv[0];
348 ## repeat delete nfsquota where nfsquota.users_id = @id
349 ## repeat retrieve (flag = any(members.member_id where members.member_id=@id
350 ## and members.member_type = "USER"))
353 ## repeat retrieve (flag = any(filesys.label where filesys.owner=@id))
356 ## repeat retrieve (flag = any(list.name where list.acl_id=@id and
357 ## list.acl_type = "USER"))
360 ## repeat retrieve (flag = any(servers.name where servers.acl_id=@id and
361 ## servers.acl_type = "USER"))
364 ## repeat retrieve (flag=any(hostaccess.acl_id where hostaccess.acl_id=@id and
365 ## hostaccess.acl_type = "USER"))
373 /* setup_spop: verify that there is already a valid POP machine_id in the
374 * pop_id field. Also take care of keeping track of the post office usage.
376 int setup_spop(q, argv)
383 id = *(int *)argv[0];
384 ## repeat retrieve (type = u.potype, flag = any(machine.name
385 ## where machine.mach_id = u.pop_id
387 ## and u.users_id = @id))
390 if (strcmp(type, "POP"))
391 set_pop_usage(id, 1);
396 /* setup_dpob: Take care of keeping track of the post office usage.
398 int setup_dpob(q, argv)
405 user = *(int *)argv[0];
406 ## repeat retrieve (type = u.potype, id = u.pop_id)
407 ## where u.users_id = @user
409 if (strcmp(type, "POP"))
410 set_pop_usage(id, -1);
415 /* setup_dmac - verify that the machine is no longer being referenced
416 * and may safely be deleted.
419 int setup_dmac(q, argv)
425 id = *(int *)argv[0];
426 ## repeat retrieve (flag = any(users.login where users.potype = "POP"
427 ## and users.pop_id=@id))
430 ## repeat retrieve (flag = any(serverhosts.mach_id
431 ## where serverhosts.mach_id=@id))
434 ## repeat retrieve (flag = any(nfsphys.mach_id where nfsphys.mach_id=@id))
437 ## repeat retrieve (flag = any(hostaccess.mach_id where hostaccess.mach_id=@id))
441 ## repeat delete mcmap where mcmap.mach_id = @id
446 /* setup_dclu - verify that the cluster is no longer being referenced
447 * and may safely be deleted.
450 int setup_dclu(q, argv)
456 id = *(int *)argv[0];
457 ## repeat retrieve (flag = any(mcmap.mach_id where mcmap.clu_id=@id))
460 ## repeat retrieve (flag = any(svc.clu_id where svc.clu_id=@id))
468 /* setup_alis - if argv[5] is non-zero and argv[6] is UNIQUE_ID, then allocate
469 * a new gid and put it in argv[6]. Otherwise if argv[6] is UNIQUE_ID but
470 * argv[5] is not, then remember that UNIQUE_ID is being stored by putting
471 * a -1 there. Remember that this is also used for ulis, with the indexes
475 int setup_alis(q, argv)
483 if (!strcmp(q->shortname, "alis"))
485 else if (!strcmp(q->shortname, "ulis"))
488 if (!strcmp(argv[idx], UNIQUE_GID) || atoi(argv[idx]) == -1) {
489 if (atoi(argv[idx - 1])) {
490 if (set_next_object_id("gid", "list"))
491 return(SMS_INGRES_ERR);
492 ## repeat retrieve (ngid = values.value) where values.name = "gid"
493 sprintf(argv[idx], "%d", ngid);
495 strcpy(argv[idx], "-1");
503 /* setup_dlist - verify that the list is no longer being referenced
504 * and may safely be deleted.
507 int setup_dlis(q, argv)
513 id = *(int *)argv[0];
514 ## repeat retrieve (flag = any(members.member_id where members.member_id=@id
515 ## and members.member_type = "LIST"))
518 ## repeat retrieve (flag = any(members.member_id where members.list_id=@id))
521 ## repeat retrieve (flag = any(filesys.label where filesys.owners=@id))
524 ## repeat retrieve (flag = any(capacls.tag where capacls.list_id=@id))
527 ## repeat retrieve (flag = any(list.name where list.acl_id=@id and
528 ## list.acl_type = "LIST"))
531 ## repeat retrieve (flag = any(servers.name where servers.acl_id=@id and
532 ## servers.acl_type = "LIST"))
535 ## repeat retrieve (flag=any(hostaccess.acl_id where hostaccess.acl_id=@id and
536 ## hostaccess.acl_type = "LIST"))
539 ## repeat retrieve (flag = any(zephyr.class
540 ## where zephyr.xmt_type = "LIST" and zephyr.xmt_id = @id or
541 ## zephyr.sub_type = "LIST" and zephyr.sub_id = @id or
542 ## zephyr.iws_type = "LIST" and zephyr.iws_id = @id or
543 ## zephyr.iui_type = "LIST" and zephyr.iui_id = @id))
551 /* setup_dsin - verify that the service is no longer being referenced
552 * and may safely be deleted.
555 int setup_dsin(q, argv)
563 ## repeat retrieve (flag = any(serverhosts.service
564 ## where serverhosts.service=uppercase(@name)))
567 ## repeat retrieve (flag = servers.inprogress) where servers.#name = @name
575 /* setup_dshi - verify that the service-host is no longer being referenced
576 * and may safely be deleted.
579 int setup_dshi(q, argv)
587 id = *(int *)argv[1];
588 ## repeat retrieve (flag=serverhosts.inprogress)
589 ## where serverhosts.service=uppercase(@name) and serverhosts.mach_id=@id
598 ** setup_add_filesys - verify existance of referenced file systems
610 ** * extract directory prefix from name
611 ** * verify mach_id/dir in nfsphys
612 ** * verify access in {r, w, R, W}
614 ** Side effect: sets variable var_phys_id to the ID of the physical
615 ** filesystem (nfsphys_id for NFS, 0 for RVD)
618 ** SMS_NFS - specified directory not exported
619 ** SMS_FILESYS_ACCESS - invalid filesys access
623 ##static int var_phys_id;
635 mach_id = *(int *)argv[2];
640 if (!strcmp(type, "NFS"))
641 return (check_nfs(mach_id, name, access));
657 mach_id = *(int *)argv[3];
662 if (!strcmp(type, "NFS"))
663 return (check_nfs(mach_id, name, access));
669 /* Find the NFS physical partition that the named directory is on.
670 * This is done by comparing the dir against the mount point of the
671 * partition. To make sure we get the correct match when there is
672 * more than one, we sort the query in reverse order by dir name.
675 ##check_nfs(mach_id, name, access)
686 caccess = (isupper(*access)) ? tolower(*access) : *access;
687 if (caccess != 'r' && caccess != 'w') return(SMS_FILESYS_ACCESS);
690 ## range of np is nfsphys
691 ## repeat retrieve (var_phys_id = np.#nfsphys_id, dir = trim(np.#dir))
692 ## where np.#mach_id = @mach_id sort by #dir:d {
696 if (*cp1++ != *cp2) break;
700 status = SMS_SUCCESS;
709 /* setup_dfil: free any quota records associated with a filesystem
710 * when it is deleted.
713 setup_dfil(q, argv, cl)
720 id = *(int *)argv[0];
721 ## range of q is nfsquota
722 ## range of fs is filesys
723 ## range of n is nfsphys
724 ## repeat replace n (allocated=n.allocated-sum(q.quota where q.filsys_id=@id))
725 ## where n.nfsphys_id = fs.phys_id and fs.filsys_id = @id
727 ## repeat delete q where q.filsys_id = @id
732 /* setup_dnfp: check to see that the nfs physical partition does not have
733 * any filesystems assigned to it before allowing it to be deleted.
736 setup_dnfp(q, argv, cl)
743 id = *(int *)argv[0];
744 ## repeat retrieve (exists = any(filesys.label where filesys.phys_id = @id))
751 /* setup_dnfq: Remove allocation from nfsphys before deleting quota.
752 * argv[0] = filsys_id
756 setup_dnfq(q, argv, cl)
761 ## int quota, fs, user;
763 fs = *(int *)argv[0];
764 user = *(int *)argv[1];
766 ## range of q is nfsquota
767 ## repeat retrieve (quota = q.#quota) where q.users_id = @user and
769 ## repeat replace nfsphys (allocated = nfsphys.allocated - @quota)
770 ## where nfsphys.nfsphys_id = filesys.#phys_id and filesys.filsys_id = @fs
776 /* FOLLOWUP ROUTINES */
778 /* generic set_modtime routine. This takes the table name from the query,
779 * and will update the modtime, modby, and modwho fields in the entry in
780 * the table whose name field matches argv[0].
783 set_modtime(q, argv, cl)
788 ## char *name, *entity, *table;
796 ## replace table (modtime = "now", modby = who, modwith = entity)
797 ## where table.#name = name
801 /* generic set_modtime_by_id routine. This takes the table name from
802 * the query, and the id name from the validate record,
803 * and will update the modtime, modby, and modwho fields in the entry in
804 * the table whose id matches argv[0].
807 set_modtime_by_id(q, argv, cl)
812 ## char *entity, *table, *id_name;
818 id_name = q->validate->object_id;
820 id = *(int *)argv[0];
821 ## replace table (modtime = "now", modby = who, modwith = entity)
822 ## where table.id_name = id
827 /* Sets the finger modtime on a user record. The users_id will be in argv[0].
830 set_finger_modtime(q, argv, cl)
835 ## int users_id, who;
840 users_id = *(int *)argv[0];
842 ## repeat replace u (fmodtime = "now", fmodby = @who, fmodwith = @entity)
843 ## where u.#users_id = @users_id
848 /* Sets the pobox modtime on a user record. The users_id will be in argv[0].
851 set_pobox_modtime(q, argv, cl)
856 ## int users_id, who;
861 users_id = *(int *)argv[0];
863 ## repeat replace users (pmodtime = "now", pmodby = @who, pmodwith = @entity)
864 ## where users.#users_id = @users_id
869 /* Sets the modtime on a machine record. The machine name is in argv[0].
870 * This routine is different from the generic set_modtime in that the
871 * name is uppercased first.
874 set_mach_modtime(q, argv, cl)
879 ## char *host, *entity;
886 ## repeat replace m (modtime = "now", modby = @who, modwith = @entity)
887 ## where m.name = uppercase(@host)
892 /* Sets the modtime on the machine whose mach_id is in argv[0]. This routine
893 * is necessary for add_machine_to_cluster becuase the table that query
894 * operates on is "mcm", not "machine".
897 set_mach_modtime_by_id(q, argv, cl)
908 id = *(int *)argv[0];
909 ## range of m is machine
910 ## repeat replace m (modtime = "now", modby = @who, modwith = @entity)
911 ## where m.mach_id = @id
916 /* Sets the modtime on the cluster whose mach_id is in argv[0]. This routine
917 * is necessary for add_cluster_data and delete_cluster_data becuase the
918 * table that query operates on is "svc", not "cluster".
921 set_cluster_modtime_by_id(q, argv, cl)
932 id = *(int *)argv[0];
933 ## range of c is cluster
934 ## repeat replace c (modtime = "now", modby = @who, modwith = @entity)
935 ## where c.clu_id = @id
940 /* sets the modtime on the serverhost where the service name is in argv[0]
941 * and the mach_id is in argv[1].
944 set_serverhost_modtime(q, argv, cl)
949 ## char *entity, *serv;
956 id = *(int *)argv[1];
957 ## repeat replace sh (modtime = "now", modby = @who, modwith = @entity)
958 ## where sh.service = uppercase(@serv) and sh.mach_id = @id
963 /* sets the modtime on the nfsphys where the mach_id is in argv[0] and the
964 * directory name is in argv[1].
967 set_nfsphys_modtime(q, argv, cl)
972 ## char *entity, *dir;
978 id = *(int *)argv[0];
980 ## repeat replace np (modtime = "now", modby = @who, modwith = @entity)
981 ## where np.#dir = @dir and np.mach_id = @id
986 /* sets the modtime on a filesystem, where argv[0] contains the filesys
990 set_filesys_modtime(q, argv, cl)
995 ## char *label, *entity;
1002 if (!strcmp(q->shortname, "ufil"))
1005 ## repeat replace fs (modtime = "now", modby = @who, modwith = @entity,
1006 ## #phys_id = @var_phys_id) where fs.#label = @label
1007 return(SMS_SUCCESS);
1011 /* sets the modtime on a zephyr class, where argv[0] contains the class
1015 set_zephyr_modtime(q, argv, cl)
1020 ## char *class, *entity;
1023 entity = cl->entity;
1028 ## repeat replace z (modtime = "now", modby = @who, modwith = @entity)
1029 ## where z.#class = @class
1030 return(SMS_SUCCESS);
1034 /* fixes the modby field. This will be the second to last thing in the
1035 * argv, the argv length is determined from the query structure. It is
1036 * passed as a pointer to an integer. This will either turn it into a
1037 * username, or # + the users_id.
1039 followup_fix_modby(q, sq, v, action, actarg, cl)
1041 register struct save_queue *sq;
1043 register int (*action)();
1044 register int actarg;
1048 char **argv, *malloc();
1049 ## int id, rowcount;
1053 while (sq_get_data(sq, &argv)) {
1056 argv[i] = malloc(9);
1058 ## repeat retrieve (name = users.login) where users.users_id = @id
1059 ## inquire_equel(rowcount = "rowcount")
1060 if (rowcount != 1) {
1061 sprintf(argv[i], "#%d", id);
1063 (*action)(q->vcnt, argv, actarg);
1064 for (j = 0; j < q->vcnt; j++)
1069 return(SMS_SUCCESS);
1074 ** followup_ausr - add finger and pobox entries, set_user_modtime
1077 ** argv[0] - login (add_user)
1078 ** argv[3] - last name
1079 ** argv[4] - first name
1080 ** argv[5] - middle name
1084 followup_ausr(q, argv, cl)
1090 ## char *login, *entity;
1091 ## char fullname[129];
1095 entity = cl->entity;
1097 /* build fullname */
1098 if (strlen(argv[4]) && strlen(argv[5]))
1099 sprintf(fullname, "%s %s %s", argv[4], argv[5], argv[3]);
1100 else if (strlen(argv[4]))
1101 sprintf(fullname, "%s %s", argv[4], argv[3]);
1103 sprintf(fullname, "%s", argv[3]);
1105 /* create finger entry, pobox & set modtime on user */
1106 ## repeat replace u (modtime = "now", modby=@who, modwith=@entity,
1107 ## #fullname=@fullname, mit_affil = u.mit_year,
1108 ## fmodtime="now", fmodby=@who, fmodwith=@entity,
1109 ## potype="NONE", pmodtime="now", pmodby=@who, pmodwith=@entity)
1110 ## where u.#login = @login
1112 return(SMS_SUCCESS);
1116 /* followup_gpob: fixes argv[2] based on the IDs currently there and the
1117 * type in argv[1]. Then completes the upcall to the user.
1119 * argv[2] is of the form "123:234" where the first integer is the machine
1120 * ID if it is a pop box, and the second is the string ID if it is an SMTP
1121 * box. argv[1] should be "POP", "SMTP", or "NONE". Boxes of type NONE
1125 followup_gpob(q, sq, v, action, actarg, cl)
1126 register struct query *q;
1127 register struct save_queue *sq;
1128 register struct validate *v;
1129 register int (*action)();
1133 char **argv, *index();
1135 ## char box[129], *name;
1136 ## int mid, sid, rowcount;
1139 while (sq_get_data(sq, &argv)) {
1140 sms_trim_args(2, argv);
1142 p = index(argv[2], ':');
1144 mid = atoi(argv[2]);
1148 if (!strcmp(ptype, "POP")) {
1149 ## repeat retrieve (box=machine.#name) where machine.mach_id=@mid
1150 ## inquire_equel(rowcount = "rowcount")
1152 return(SMS_MACHINE);
1153 } else if (!strcmp(ptype, "SMTP")) {
1154 ## repeat retrieve (box=strings.string) where strings.string_id=@sid
1155 ## inquire_equel(rowcount = "rowcount")
1158 } else /* ptype == "NONE" */ {
1162 if (!strcmp(q->shortname, "gpob")) {
1163 sid = atoi(argv[4]);
1165 argv[4] = malloc(9);
1167 ## repeat retrieve (name = users.login) where users.users_id = @sid
1168 ## inquire_equel(rowcount = "rowcount")
1170 sprintf(name, "#%d", sid);
1174 (*action)(q->vcnt, argv, actarg);
1176 /* free saved data */
1183 return (SMS_SUCCESS);
1187 /* followup_glin: fix the ace_name in argv[8]. argv[7] will contain the
1188 * ace_type: "LIST", "USER", or "NONE". Decode the id in argv[8] into the
1189 * proper name based on the type, and repace that string in the argv.
1190 * Also fixes the modby field by called followup_fix_modby.
1193 followup_glin(q, sq, v, action, actarg, cl)
1194 register struct query *q;
1195 register struct save_queue *sq;
1196 register struct validate *v;
1197 register int (*action)();
1201 char **argv, *malloc(), *realloc(), *type;
1203 ## int id, rowcount;
1207 if (!strcmp(q->shortname, "gsin"))
1210 while (sq_get_data(sq, &argv)) {
1211 sms_trim_args(q->vcnt, argv);
1213 id = atoi(argv[i = q->vcnt - 2]);
1215 name = argv[i] = malloc(9);
1216 ## repeat retrieve (name = users.login) where users.users_id = @id
1217 ## inquire_equel(rowcount = "rowcount")
1219 sprintf(argv[i], "#%d", id);
1221 id = atoi(argv[idx]);
1222 type = argv[idx - 1];
1223 if ((name = malloc(33)) == NULL)
1226 if (!strcmp(type, "LIST")) {
1227 ## repeat retrieve (name = list.#name) where list.list_id = @id
1228 ## inquire_equel(rowcount = "rowcount")
1230 strcpy(name, "???");
1231 } else if (!strcmp(type, "USER")) {
1232 ## repeat retrieve (name = users.login) where users.users_id = @id
1233 ## inquire_equel(rowcount = "rowcount")
1235 strcpy(name, "???");
1236 } else if (!strcmp(type, "NONE")) {
1237 strcpy(name, "NONE");
1239 strcpy(name, "???");
1243 if (!strcmp(q->shortname, "glin") && atoi(argv[6]) == -1) {
1244 argv[6] = realloc(argv[6], strlen(UNIQUE_GID) + 1);
1245 strcpy(argv[6], UNIQUE_GID);
1249 (*action)(q->vcnt, argv, actarg);
1251 /* free saved data */
1252 for (i = 0; i < q->vcnt; i++)
1258 return (SMS_SUCCESS);
1262 /** followup_amtl - followup for amtl and dmfl; when adding a list
1263 ** member to a maillist, make member list a maillist also
1264 ** unless list is a user-group.
1265 ** Then set_list_modtime_by_id.
1268 ** argv[0] - list_id
1269 ** argv[1] - member_type
1270 ** argv[2] - member_id
1274 followup_amtl(q, argv, cl)
1284 list_id = *(int *)argv[0];
1285 entity = cl->entity;
1288 ## range of l is list
1289 ## repeat replace l (modtime = "now", modby = @who, modwith = @entity)
1290 ## where l.#list_id = @list_id
1292 /* if query is not amtl or if member_type is not LIST then return */
1293 if (bcmp(q->shortname, "amtl", 4) || bcmp(argv[1], "LIST", 4))
1294 return(SMS_SUCCESS);
1296 member_id = *(int *)argv[2];
1298 /* is parent list a mailing list? */
1299 ## repeat retrieve (exists = l.maillist) where l.#list_id=@list_id
1301 return(SMS_SUCCESS);
1303 /* list is not a user-group; add list to maillist table */
1304 ## repeat replace l (maillist = 1) where l.#list_id = @member_id
1305 return(SMS_SUCCESS);
1309 /* followup_anfq: Add allocation to nfsphys after creating quota.
1310 * argv[0] = filsys_id
1311 * argv[2] = ascii(quota)
1314 followup_anfq(q, argv, cl)
1319 ## int quota, user, fs, who;
1322 fs = *(int *)argv[0];
1323 user = *(int *)argv[1];
1324 quota = atoi(argv[2]);
1326 entity = cl->entity;
1328 ## repeat replace nq (modtime = "now", modby = @who, modwith = @entity)
1329 ## where nq.filsys_id = @fs and nq.users_id = @user
1330 ## repeat replace nfsphys (allocated = nfsphys.allocated + @quota)
1331 ## where nfsphys.nfsphys_id = filesys.#phys_id and filesys.filsys_id = @fs
1332 return(SMS_SUCCESS);
1339 followup_gzcl(q, sq, v, action, actarg, cl)
1340 register struct query *q;
1341 register struct save_queue *sq;
1342 register struct validate *v;
1343 register int (*action)();
1348 ## int rowcount, id;
1352 while (sq_get_data(sq, &argv)) {
1353 sms_trim_args(q->vcnt, argv);
1355 id = atoi(argv[i = q->vcnt - 2]);
1357 name = argv[i] = malloc(9);
1358 ## repeat retrieve (name = users.login) where users.users_id = @id
1359 ## inquire_equel(rowcount = "rowcount")
1361 sprintf(argv[i], "#%d", id);
1363 for (i = 1; i < 8; i+=2) {
1364 id = atoi(argv[i+1]);
1366 if ((name = argv[i+1] = malloc(33)) == NULL)
1368 if (!strcmp(argv[i], "LIST")) {
1369 ## repeat retrieve (name = list.#name) where list.list_id = @id
1370 ## inquire_equel(rowcount = "rowcount")
1372 strcpy(name, "???");
1373 } else if (!strcmp(argv[i], "USER")) {
1374 ## repeat retrieve (name = users.login) where users.users_id = @id
1375 ## inquire_equel(rowcount = "rowcount")
1377 strcpy(name, "???");
1378 } else if (!strcmp(argv[i], "NONE")) {
1379 strcpy(name, "NONE");
1381 strcpy(name, "???");
1386 (*action)(q->vcnt, argv, actarg);
1388 /* free saved data */
1389 for (i = 0; i < q->vcnt; i++)
1394 return(SMS_SUCCESS);
1401 followup_gsha(q, sq, v, action, actarg, cl)
1402 register struct query *q;
1403 register struct save_queue *sq;
1404 register struct validate *v;
1405 register int (*action)();
1410 ## int rowcount, id;
1414 while (sq_get_data(sq, &argv)) {
1415 sms_trim_args(q->vcnt, argv);
1419 name = argv[4] = malloc(9);
1420 ## repeat retrieve (name = users.login) where users.users_id = @id
1421 ## inquire_equel(rowcount = "rowcount")
1423 sprintf(argv[4], "#%d", id);
1427 if ((name = argv[2] = malloc(33)) == NULL)
1429 if (!strcmp(argv[1], "LIST")) {
1430 ## repeat retrieve (name = list.#name) where list.list_id = @id
1431 ## inquire_equel(rowcount = "rowcount")
1433 strcpy(name, "???");
1434 } else if (!strcmp(argv[1], "USER")) {
1435 ## repeat retrieve (name = users.login) where users.users_id = @id
1436 ## inquire_equel(rowcount = "rowcount")
1438 strcpy(name, "???");
1439 } else if (!strcmp(argv[1], "NONE")) {
1440 strcpy(name, "NONE");
1442 strcpy(name, "???");
1446 (*action)(q->vcnt, argv, actarg);
1448 /* free saved data */
1449 for (i = 0; i < q->vcnt; i++)
1454 return(SMS_SUCCESS);
1459 /* Special query routines */
1461 /* set_pobox - this does all of the real work.
1462 * argv = user_id, type, box
1463 * if type is POP, then box should be a machine, and its ID should be put in
1464 * pop_id. If type is SMTP, then box should be a string and its ID should
1465 * be put in box_id. If type is NONE, then box doesn't matter.
1468 int set_pobox(q, argv, cl)
1473 ## int user, id, rowcount;
1474 ## char *box, potype[9];
1477 user = *(int *)argv[0];
1479 ## repeat retrieve (id = users.pop_id, potype = users.#potype)
1480 ## where users.users_id = @user
1481 if (!strcmp(potype, "POP"))
1482 set_pop_usage(id, -1);
1484 if (!strcmp(argv[1], "POP")) {
1485 ## repeat retrieve (id=machine.mach_id) where machine.name=uppercase(@box)
1486 ## inquire_equel(rowcount = "rowcount")
1488 return(SMS_MACHINE);
1489 ## repeat replace users (#potype = "POP", pop_id = @id)
1490 ## where users.users_id = @user
1491 set_pop_usage(id, 1);
1492 } else if (!strcmp(argv[1], "SMTP")) {
1493 ## range of s is strings
1494 ## repeat retrieve (id = s.string_id) where s.string = @box
1495 ## inquire_equel (rowcount = "rowcount")
1496 if (rowcount == 0) {
1497 ## range of v is values
1498 ## repeat retrieve (id = v.value) where v.name = "strings_id"
1500 ## repeat replace v (value = @id) where v.name = "strings_id"
1501 ## append to strings (string_id = id, string = box)
1503 ## repeat replace users (#potype = "SMTP", box_id = @id)
1504 ## where users.users_id = @user
1505 } else /* argv[1] == "NONE" */ {
1506 ## repeat replace users (#potype = "NONE") where users.users_id = @user
1509 set_pobox_modtime(q, argv, cl);
1510 ## repeat replace tblstats (updates = tblstats.updates + 1, modtime = "now")
1511 ## where tblstats.#table = "users"
1512 return(SMS_SUCCESS);
1516 /* get_list_info: passed a wildcard list name, returns lots of stuff about
1517 * each list. This is tricky: first build a queue of all requested
1518 * data. Rest of processing consists of fixing gid, ace_name, and modby.
1521 get_list_info(q, aargv, cl, action, actarg)
1522 register struct query *q;
1525 register int (*action)();
1528 char *argv[13], *malloc(), *realloc();
1529 ## char *name, acl_type[9], listname[33], active[5], public[5], hidden[5];
1530 ## char maillist[5], group[5], gid[6], acl_name[33], desc[256], modtime[27];
1531 ## char modby[9], modwith[9];
1532 ## int id, rowcount, acl_id, hid, modby_id;
1534 struct save_queue *sq, *sq_create();
1536 returned = rowcount = 0;
1540 ## range of l is list
1541 ## repeat retrieve (id = l.list_id) where l.#name = @name {
1542 sq_save_data(sq, id);
1546 return(SMS_NO_MATCH);
1548 argv[0] = listname; argv[1] = active; argv[2] = public; argv[3] = hidden;
1549 argv[4] = maillist; argv[5] = group; argv[6] = gid; argv[7] = acl_type;
1550 argv[8] = acl_name; argv[9] = desc; argv[10] = modtime; argv[11] = modby;
1553 while (sq_get_data(sq, &id)) {
1557 ## repeat retrieve (listname = l.#name, active = text(l.#active),
1558 ## public = text(l.#public), hidden = text(l.#hidden),
1559 ## hid = l.#hidden, maillist = text(l.#maillist),
1560 ## group = text(l.#group), gid = text(l.#gid),
1561 ## acl_type = trim(l.#acl_type), acl_id = l.#acl_id,
1562 ## desc = l.#desc, modtime = l.#modtime, modby_id = l.#modby,
1563 ## modwith =l.#modwith)
1564 ## where l.list_id = @id
1566 if (atoi(gid) == -1)
1567 argv[6] = UNIQUE_GID;
1569 if (!strcmp(acl_type, "LIST")) {
1570 ## repeat retrieve (acl_name = l.#name) where l.list_id = @acl_id
1571 ## inquire_equel(rowcount = "rowcount")
1573 strcpy(acl_name, "???");
1574 } else if (!strcmp(acl_type, "USER")) {
1575 ## repeat retrieve (acl_name = users.#login)
1576 ## where users.users_id = @acl_id
1577 ## inquire_equel(rowcount = "rowcount")
1579 strcpy(acl_name, "???");
1580 } else if (!strcmp(acl_type, "NONE")) {
1581 strcpy(acl_name, "NONE");
1583 strcpy(acl_name, "???");
1585 ## repeat retrieve (modby = users.login) where users.users_id = @modby_id
1586 ## inquire_equel(rowcount = "rowcount")
1588 sprintf(modby, "#%d", id);
1590 sms_trim_args(q->vcnt, argv);
1592 (*action)(q->vcnt, argv, actarg);
1596 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
1597 ## where tblstats.#table = "list"
1599 return (SMS_SUCCESS);
1603 /* get_ace_use - given a type and a name, return a type and a name.
1604 * The ace_type is one of "LIST", "USER", "RLIST", or "RUSER" in argv[0],
1605 * and argv[1] will contain the ID of the entity in question. The R*
1606 * types mean to recursively look at every containing list, not just
1607 * when the object in question is a direct member. On return, the
1608 * usage type will be one of LIST, SERVICE, FILESYS, QUOTA, QUERY, or ZEPHYR.
1611 int get_ace_use(q, argv, cl, action, actarg)
1620 ## int aid, listid, id;
1621 struct save_queue *sq, *sq_create();
1624 aid = *(int *)argv[1];
1625 if (!strcmp(atype, "LIST") || !strcmp(atype, "USER")) {
1626 return(get_ace_internal(atype, aid, action, actarg));
1630 if (!strcmp(atype, "RLIST")) {
1631 sq_save_data(sq, aid);
1632 /* get all the list_id's of containing lists */
1633 ## range of m is members
1634 while (sq_get_data(sq, &id)) {
1635 ## repeat retrieve (listid = m.list_id)
1636 ## where m.member_type = "LIST" and m.member_id = @id {
1637 sq_save_unique_data(sq, listid);
1640 /* now process each one */
1641 while (sq_get_data(sq, &id)) {
1642 if (get_ace_internal("LIST", id, action, actarg) == SMS_SUCCESS)
1647 if (!strcmp(atype, "RUSER")) {
1648 ## range of m is members
1649 ## repeat retrieve (listid = m.list_id)
1650 ## where m.member_type = "USER" and m.member_id = @aid {
1651 sq_save_data(sq, listid);
1653 /* get all the list_id's of containing lists */
1654 while (sq_get_data(sq, &id)) {
1655 ## repeat retrieve (listid = m.list_id)
1656 ## where m.member_type = "LIST" and m.member_id = @id {
1657 sq_save_unique_data(sq, listid);
1660 /* now process each one */
1661 while (sq_get_data(sq, &id)) {
1662 if (get_ace_internal("LIST", id, action, actarg) == SMS_SUCCESS)
1665 if (get_ace_internal("USER", aid, action, actarg) == SMS_SUCCESS)
1670 if (!found) return(SMS_NO_MATCH);
1671 return(SMS_SUCCESS);
1675 /* This looks up a single list or user for ace use. atype must be "USER"
1676 * or "LIST", and aid is the ID of the corresponding object. This is used
1677 * by get_ace_use above.
1680 ##get_ace_internal(atype, aid, action, actarg)
1691 if (!strcmp(atype, "LIST")) {
1692 rargv[0] = "FILESYS";
1693 ## repeat retrieve (name = filesys.label)
1694 ## where filesys.owners = @aid {
1695 (*action)(2, rargv, actarg);
1700 ## repeat retrieve (name = capacls.capability)
1701 ## where capacls.list_id = @aid {
1702 (*action)(2, rargv, actarg);
1705 } else if (!strcmp(atype, "USER")) {
1706 rargv[0] = "FILESYS";
1707 ## repeat retrieve (name = filesys.label)
1708 ## where filesys.owner = @aid {
1709 (*action)(2, rargv, actarg);
1715 ## repeat retrieve (name = list.#name)
1716 ## where list.acl_type = @atype and list.acl_id = @aid {
1717 (*action)(2, rargv, actarg);
1721 rargv[0] = "SERVICE";
1722 ## repeat retrieve (name = servers.#name)
1723 ## where servers.acl_type = @atype and servers.acl_id = @aid {
1724 (*action)(2, rargv, actarg);
1728 rargv[0] = "HOSTACCESS";
1729 ## repeat retrieve (name = machine.#name)
1730 ## where machine.mach_id = hostaccess.mach_id and
1731 ## hostaccess.acl_type = @atype and hostaccess.acl_id = @aid {
1732 (*action)(2, rargv, actarg);
1735 rargv[0] = "ZEPHYR";
1736 ## repeat retrieve (name = zephyr.class)
1737 ## where zephyr.xmt_type = @atype and zephyr.xmt_id = @aid or
1738 ## zephyr.sub_type = @atype and zephyr.sub_id = @aid or
1739 ## zephyr.iws_type = @atype and zephyr.iws_id = @aid or
1740 ## zephyr.iui_type = @atype and zephyr.iui_id = @aid {
1741 (*action)(2, rargv, actarg);
1745 if (!found) return(SMS_NO_MATCH);
1746 return(SMS_SUCCESS);
1750 /* get_lists_of_member - given a type and a name, return the name and flags
1751 * of all of the lists of the given member. The member_type is one of
1752 * "LIST", "USER", "STRING", "RLIST", "RUSER", or "RSTRING" in argv[0],
1753 * and argv[1] will contain the ID of the entity in question. The R*
1754 * types mean to recursively look at every containing list, not just
1755 * when the object in question is a direct member.
1758 int get_lists_of_member(q, argv, cl, action, actarg)
1767 ## int aid, listid, id;
1768 struct save_queue *sq, *sq_create();
1771 aid = *(int *)argv[1];
1772 if (!strcmp(atype, "LIST") ||
1773 !strcmp(atype, "USER") ||
1774 !strcmp(atype, "STRING")) {
1775 return(glom_internal(atype, aid, action, actarg));
1779 if (!strcmp(atype, "RLIST")) {
1780 sq_save_data(sq, aid);
1781 /* get all the list_id's of containing lists */
1782 ## range of m is members
1783 while (sq_get_data(sq, &id)) {
1784 ## repeat retrieve (listid = m.list_id)
1785 ## where m.member_type = "LIST" and m.member_id = @id {
1786 sq_save_unique_data(sq, listid);
1789 /* now process each one */
1790 while (sq_get_data(sq, &id)) {
1791 if (glom_internal("LIST", id, action, actarg) == SMS_SUCCESS)
1796 if (!strcmp(atype, "RUSER")) {
1797 ## range of m is members
1798 ## repeat retrieve (listid = m.list_id)
1799 ## where m.member_type = "USER" and m.member_id = @aid {
1800 sq_save_data(sq, listid);
1802 /* get all the list_id's of containing lists */
1803 while (sq_get_data(sq, &id)) {
1804 ## repeat retrieve (listid = m.list_id)
1805 ## where m.member_type = "LIST" and m.member_id = @id {
1806 sq_save_unique_data(sq, listid);
1809 /* now process each one */
1810 while (sq_get_data(sq, &id)) {
1811 if (glom_internal("LIST", id, action, actarg) == SMS_SUCCESS)
1814 if (glom_internal("USER", aid, action, actarg) == SMS_SUCCESS)
1818 if (!strcmp(atype, "RSTRING")) {
1819 ## range of m is members
1820 ## repeat retrieve (listid = m.list_id)
1821 ## where m.member_type = "STRING" and m.member_id = @aid {
1822 sq_save_data(sq, listid);
1824 /* get all the list_id's of containing lists */
1825 while (sq_get_data(sq, &id)) {
1826 ## repeat retrieve (listid = m.list_id)
1827 ## where m.member_type = "LIST" and m.member_id = @id {
1828 sq_save_unique_data(sq, listid);
1831 /* now process each one */
1832 while (sq_get_data(sq, &id)) {
1833 if (glom_internal("LIST", id, action, actarg) == SMS_SUCCESS)
1836 if (glom_internal("STRING", aid, action, actarg) == SMS_SUCCESS)
1840 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
1841 ## where tblstats.#table = "members"
1843 if (!found) return(SMS_NO_MATCH);
1844 return(SMS_SUCCESS);
1848 /* This looks up a single list, user, or string as a member. atype must be
1849 * "USER", "LIST", or "STRING" and aid is the ID of the corresponding object.
1850 * This is used by get_lists_of_members above.
1853 ##glom_internal(atype, aid, action, actarg)
1861 ## char name[33], active[5], public[5], hidden[5], maillist[5], group[5];
1867 rargv[4] = maillist;
1869 ## repeat retrieve (name = list.#name, active = text(list.#active),
1870 ## public = text(list.#public), hidden = text(list.#hidden),
1871 ## maillist = text(list.#maillist), group = text(list.#group))
1872 ## where list.list_id = m.list_id and
1873 ## m.member_type = @atype and m.member_id = @aid {
1874 (*action)(6, rargv, actarg);
1878 if (!found) return(SMS_NO_MATCH);
1879 return(SMS_SUCCESS);
1883 /* qualified_get_lists: passed "TRUE", "FALSE", or "DONTCARE" for each of
1884 * the five flags associated with each list. It will return the name of
1885 * each list that meets the quailifications. It does this by building a
1886 * where clause based on the arguments, then doing a retrieve.
1889 static char *lflags[5] = { "active", "public", "hidden", "maillist", "group" };
1891 int qualified_get_lists(q, argv, cl, action, actarg)
1898 return(qualified_get(q, argv, action, actarg, "l.list_id != 0",
1899 "l", "name", lflags));
1903 /** get_members_of_list - optimized query for retrieval of list members
1906 ** argv[0] - list_id
1909 ** - retrieve USER members, then LIST members, then STRING members
1912 get_members_of_list(q, argv, cl, action, actarg)
1920 ## char member_name[129];
1923 list_id = *(int *)argv[0];
1925 targv[1] = member_name;
1927 ## range of m is members
1928 ## repeat retrieve (member_name = users.login)
1929 ## where m.#list_id = @list_id and m.member_type = "USER"
1930 ## and m.member_id = users.users_id
1931 ## sort by #member_name
1933 (*action)(2, targv, actarg);
1937 ## repeat retrieve (member_name = list.name)
1938 ## where m.#list_id = @list_id and m.member_type = "LIST"
1939 ## and m.member_id = list.#list_id
1940 ## sort by #member_name
1942 (*action)(2, targv, actarg);
1945 targv[0] = "STRING";
1946 ## repeat retrieve (member_name = strings.string)
1947 ## where m.#list_id = @list_id and m.member_type = "STRING"
1948 ## and m.member_id = strings.string_id
1949 ## sort by #member_name
1951 (*action)(2, targv, actarg);
1954 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
1955 ## where tblstats.#table = "members"
1956 return(SMS_SUCCESS);
1960 /* count_members_of_list: this is a simple query, but it cannot be done
1961 * through the dispatch table.
1964 int count_members_of_list(q, argv, cl, action, actarg)
1971 ## int list, ct = 0;
1972 char *rargv[1], countbuf[5];
1974 list = *(int *)argv[0];
1975 rargv[0] = countbuf;
1976 ## repeat retrieve (ct = count(members.list_id where members.list_id = @list))
1977 sprintf(countbuf, "%d", ct);
1978 (*action)(1, rargv, actarg);
1979 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
1980 ## where tblstats.#table = "members"
1981 return(SMS_SUCCESS);
1985 /* qualified_get_server: passed "TRUE", "FALSE", or "DONTCARE" for each of
1986 * the three flags associated with each service. It will return the name of
1987 * each service that meets the quailifications. It does this by building a
1988 * where clause based on the arguments, then doing a retrieve.
1991 static char *sflags[3] = { "enable", "inprogress", "harderror" };
1993 int qualified_get_server(q, argv, cl, action, actarg)
2000 return(qualified_get(q, argv, action, actarg, "s.name != \"\"",
2001 "s", "name", sflags));
2005 /* generic qualified get routine, used by qualified_get_lists,
2006 * qualified_get_server, and qualified_get_serverhost.
2008 * start - a simple where clause, must not be empty
2009 * range - the name of the range variable
2010 * field - the field to return
2011 * flags - an array of strings, names of the flag variables
2014 int qualified_get(q, argv, action, actarg, start, range, field, flags)
2024 ## char name[33], qual[256], *rvar, *rtbl, *rfield;
2025 char *rargv[1], buf[32];
2028 strcpy(qual, start);
2029 for (i = 0; i < q->argc; i++) {
2030 if (!strcmp(argv[i], "TRUE")) {
2031 sprintf(buf, " and %s.%s != 0", range, flags[i]);
2032 (void) strcat(qual, buf);
2033 } else if (!strcmp(argv[i], "FALSE")) {
2034 sprintf(buf, " and %s.%s = 0", range, flags[i]);
2035 (void) strcat(qual, buf);
2043 ## range of rvar is rtbl
2044 ## retrieve (name = rvar.rfield) where qual {
2045 (*action)(1, rargv, actarg);
2047 ## inquire_equel(rowcount = "rowcount")
2048 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
2049 ## where tblstats.#table = @rtbl
2051 return(SMS_NO_MATCH);
2052 return(SMS_SUCCESS);
2056 /* qualified_get_serverhost: passed "TRUE", "FALSE", or "DONTCARE" for each of
2057 * the five flags associated with each serverhost. It will return the name of
2058 * each service and host that meets the quailifications. It does this by
2059 * building a where clause based on the arguments, then doing a retrieve.
2062 static char *shflags[6] = { "service", "enable", "override", "success",
2063 "inprogress", "hosterror" };
2065 int qualified_get_serverhost(q, argv, cl, action, actarg)
2072 ## char sname[33], mname[33], qual[256];
2073 char *rargv[2], buf[32];
2076 sprintf(qual, "machine.mach_id = sh.mach_id and sh.service = uppercase(\"%s\")",
2078 for (i = 1; i < q->argc; i++) {
2079 if (!strcmp(argv[i], "TRUE")) {
2080 sprintf(buf, " and sh.%s != 0", shflags[i]);
2082 } else if (!strcmp(argv[i], "FALSE")) {
2083 sprintf(buf, " and sh.%s = 0", shflags[i]);
2090 ## range of sh is serverhosts
2091 ## retrieve (sname = sh.service, mname = machine.name) where qual {
2092 (*action)(2, rargv, actarg);
2094 ## inquire_equel(rowcount = "rowcount")
2095 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
2096 ## where tblstats.#table = "serverhosts"
2098 return(SMS_NO_MATCH);
2099 return(SMS_SUCCESS);
2103 /* register_user - change user's login name and allocate a pobox, group,
2104 * filesystem, and quota for them. The user's status must start out as 0,
2105 * and is left as 2. Arguments are: user's UID, new login name, and user's
2106 * type for filesystem allocation (SMS_FS_STUDENT, SMS_FS_FACULTY,
2107 * SMS_FS_STAFF, SMS_FS_MISC).
2110 register_user(q, argv, cl)
2115 ## char *login, dir[65], *entity, *directory, machname[33];
2116 ## int who, rowcount, mid, uid, users_id, flag, utype, nid, list_id, quota;
2117 ## int size, alloc, pid, m_id;
2120 entity = cl->entity;
2123 uid = atoi(argv[0]);
2125 utype = atoi(argv[2]);
2127 ## range of u is users
2128 ## range of l is list
2129 ## range of sh is serverhosts
2130 ## range of n is nfsphys
2131 ## range of m is machine
2134 ## repeat retrieve (users_id = u.#users_id)
2135 ## where u.#uid = @uid and u.status = 0
2136 ## inquire_equel(rowcount = "rowcount");
2138 return(SMS_NO_MATCH);
2140 return(SMS_NOT_UNIQUE);
2142 /* check new login name */
2143 ## repeat retrieve (flag = any(u.#login where u.#login = @login))
2146 ## repeat retrieve (flag = any(l.name where l.name = @login))
2149 ## repeat retrieve (flag = any(filesys.#name where filesys.#name = @login))
2152 com_err(whoami, 0, "new login name OK");
2154 /* choose place for pobox, put in mid */
2155 ## repeat retrieve (mid = sh.mach_id, machname = m.name)
2156 ## where sh.service = "POP" and m.mach_id = sh.mach_id and
2157 ## sh.value2 - sh.value1 = max(sh.value2-sh.value1 where sh.service="POP")
2158 ## inquire_equel(rowcount = "rowcount");
2160 return(SMS_NO_POBOX);
2162 /* change login name, set pobox */
2163 ## repeat replace u (#login = @login, status = 2, modtime = "now",
2164 ## modby = @who, modwith = @entity, potype="POP",
2165 ## pop_id = @mid, pmodtime="now", pmodby=@who,
2166 ## pmodwith=@entity)
2167 ## where u.#users_id = @users_id
2168 ## inquire_equel(rowcount = "rowcount");
2170 return(SMS_INTERNAL);
2171 set_pop_usage(mid, 1);
2172 com_err(whoami, 0, "set login name to %s and pobox to %s", login,
2175 /* create group list */
2176 if (set_next_object_id("gid", "list"))
2178 if (set_next_object_id("list_id", "list"))
2180 ## repeat retrieve (list_id = values.value) where values.name = "list_id"
2181 ## inquire_equel(rowcount = "rowcount");
2183 return(SMS_INTERNAL);
2184 ## repeat append list (name = @login, #list_id = @list_id, active = 1,
2185 ## public = 0, hidden = 0, maillist = 0, group = 1,
2186 ## #gid = values.value, desc = "User Group",
2187 ## acl_type = "USER", acl_id = @users_id, modtime = "now",
2188 ## modby = @who, modwith = @entity)
2189 ## where values.name = "gid"
2190 ## inquire_equel(rowcount = "rowcount");
2192 return(SMS_INTERNAL);
2193 ## repeat append members (#list_id = @list_id, member_type = "USER",
2194 ## member_id = @users_id)
2195 ## inquire_equel(rowcount = "rowcount");
2197 return(SMS_INTERNAL);
2198 com_err(whoami, 0, "group list created");
2200 /* decide where to put filesystem */
2203 ## repeat retrieve (mid = n.mach_id, dir = trim(n.#dir), nid = n.nfsphys_id,
2204 ## flag = n.status, size = n.#size, alloc = n.allocated) {
2205 if ((flag & utype) && (size != 0) && (size - alloc > maxsize)) {
2206 maxsize = size - alloc;
2209 directory = strsave(dir);
2215 return(SMS_NO_FILESYS);
2217 /* create filesystem */
2218 if (set_next_object_id("filsys_id", "filesys"))
2220 ## repeat append filesys (filsys_id = values.value, phys_id = @pid,
2221 ## label = @login, type = "NFS", mach_id = @m_id,
2222 ## name = @directory + @login, mount = "/mit/" + @login,
2223 ## access = "w", comments = "User Locker",
2224 ## owner = @users_id, owners = @list_id, createflg = 1,
2225 ## lockertype = "HOMEDIR", modtime = "now",
2226 ## modby = @who, modwith = @entity)
2227 ## where values.name = "filsys_id"
2228 ## inquire_equel(rowcount = "rowcount");
2230 return(SMS_INTERNAL);
2231 com_err(whoami, 0, "filesys created on mach %d in %s/%s", m_id,
2232 trim(directory), login);
2235 ## repeat retrieve (quota = values.value) where values.name = "def_quota"
2236 ## inquire_equel(rowcount = "rowcount");
2238 return(SMS_NO_QUOTA);
2239 ## repeat append nfsquota (#users_id = @users_id, filsys_id = values.value,
2240 ## #quota = @quota, modtime = "now", modby = @who,
2241 ## modwith = @entity)
2242 ## where values.name = "filsys_id"
2243 ## inquire_equel(rowcount = "rowcount");
2245 return(SMS_INTERNAL);
2246 ## repeat replace nfsphys (allocated = nfsphys.allocated + @quota)
2247 ## where nfsphys.nfsphys_id = filesys.#phys_id and
2248 ## filesys.filsys_id = values.value and values.name = "filsys_id"
2249 ## inquire_equel(rowcount = "rowcount");
2251 return(SMS_INTERNAL);
2252 com_err(whoami, 0, "quota of %d assigned", quota);
2254 return(SMS_SUCCESS);
2259 /** set_pop_usage - incr/decr usage count for pop server in serverhosts talbe
2263 ** delta (will be +/- 1)
2266 ** - incr/decr value field in serverhosts table for pop/mach_id
2270 static int set_pop_usage(id, count)
2274 ## int mach_id = id;
2277 ## range of sh is serverhosts
2278 ## repeat replace sh (value1 = sh.value1 + @n)
2279 ## where sh.service = "POP" and sh.#mach_id = @mach_id
2281 return(SMS_SUCCESS);
2286 /* Validation Routines */
2288 validate_row(q, argv, v)
2289 register struct query *q;
2291 register struct validate *v;
2299 /* build where clause */
2300 build_qual(v->qual, v->argc, argv, qual);
2302 /* setup ingres variables */
2307 if (log_flags & LOG_RES)
2308 /* tell the logfile what we're doing */
2309 com_err(whoami, 0, "validating row: %s", qual);
2311 /* look for the record */
2312 ## range of rvar is table
2313 ## retrieve (rowcount = count(rvar.name where qual))
2314 if (rowcount == 0) return(SMS_NO_MATCH);
2315 if (rowcount > 1) return(SMS_NOT_UNIQUE);
2319 validate_fields(q, argv, vo, n)
2321 register char *argv[];
2322 register struct valobj *vo;
2325 register int status;
2330 if (log_flags & LOG_RES)
2331 com_err(whoami, 0, "validating %s in %s: %s",
2332 vo->namefield, vo->table, argv[vo->index]);
2333 status = validate_name(argv, vo);
2337 if (log_flags & LOG_RES)
2338 com_err(whoami, 0, "validating %s in %s: %s",
2339 vo->idfield, vo->table, argv[vo->index]);
2340 status = validate_id(argv, vo);
2344 if (log_flags & LOG_RES)
2345 com_err(whoami, 0, "validating date: %s", argv[vo->index]);
2346 status = validate_date(argv, vo);
2350 if (log_flags & LOG_RES)
2351 com_err(whoami, 0, "validating %s type: %s",
2352 vo->table, argv[vo->index]);
2353 status = validate_type(argv, vo);
2357 if (log_flags & LOG_RES)
2358 com_err(whoami, 0, "validating typed data (%s): %s",
2359 argv[vo->index - 1], argv[vo->index]);
2360 status = validate_typedata(q, argv, vo);
2364 if (log_flags & LOG_RES)
2365 com_err(whoami, 0, "validating rename %s in %s",
2366 argv[vo->index], vo->table);
2367 status = validate_rename(argv, vo);
2371 if (log_flags & LOG_RES)
2372 com_err(whoami, 0, "validating chars: %s", argv[vo->index]);
2373 status = validate_chars(argv[vo->index]);
2377 status = SMS_EXISTS;
2382 if (status != SMS_EXISTS) return(status);
2386 return(SMS_SUCCESS);
2390 /* validate_chars: verify that there are no illegal characters in
2391 * the string. Legal characters are printing chars other than
2394 static int illegalchars[] = {
2395 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
2396 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
2397 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
2398 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
2399 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ - O */
2400 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, /* P - _ */
2401 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
2402 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
2403 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2404 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2405 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2406 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2407 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2408 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2409 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2410 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2417 if (illegalchars[*s++])
2418 return(SMS_BAD_CHAR);
2423 validate_id(argv, vo)
2425 register struct valobj *vo;
2435 name = argv[vo->index];
2437 /* minor kludge to upcasify machine names */
2438 if (!strcmp(table, "machine"))
2439 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
2440 namefield = vo->namefield;
2441 idfield = vo->idfield;
2442 if (!strcmp(namefield, "uid")) {
2443 ## retrieve (id = table.idfield) where table.namefield = int4(name)
2444 ## inquire_equel (rowcount = "rowcount")
2446 ## retrieve (id = table.idfield) where table.namefield = name
2447 ## inquire_equel (rowcount = "rowcount")
2449 if (rowcount != 1) return(vo->error);
2450 *(int *)argv[vo->index] = id;
2454 validate_name(argv, vo)
2456 register struct valobj *vo;
2464 name = argv[vo->index];
2466 namefield = vo->namefield;
2467 if (!strcmp(table, "servers") && !strcmp(namefield, "name")) {
2468 for (c = name; *c; c++)
2472 ## retrieve (rowcount = countu(table.namefield
2473 ## where table.namefield = name))
2474 return ((rowcount == 1) ? SMS_EXISTS : vo->error);
2477 validate_date(argv, vo)
2485 idate = argv[vo->index];
2487 ## retrieve (dd = interval("years", date(idate) - date("today")))
2488 ## inquire_equel (errorno = "errorno")
2489 if (errorno != 0 || dd > 5.0) return(SMS_DATE);
2494 validate_rename(argv, vo)
2498 ## char *name, *table, *namefield, *idfield;
2502 c = name = argv[vo->index];
2504 if (illegalchars[*c++])
2505 return(SMS_BAD_CHAR);
2507 /* minor kludge to upcasify machine names */
2508 if (!strcmp(table, "machine"))
2509 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
2510 namefield = vo->namefield;
2511 idfield = vo->idfield;
2514 if (!strcmp(argv[vo->index], argv[vo->index - 1]))
2516 ## retrieve (id = any(table.namefield where table.namefield = name))
2522 ## retrieve (id = table.idfield) where table.namefield = name
2523 if (id == -1 || id == *(int *)argv[vo->index - 1])
2530 validate_type(argv, vo)
2532 register struct valobj *vo;
2539 typename = vo->table;
2540 c = value = argv[vo->index];
2542 if (illegalchars[*c++])
2543 return(SMS_BAD_CHAR);
2545 /* uppercase type fields */
2546 for (c = value; *c; c++) if (islower(*c)) *c = toupper(*c);
2548 ## range of a is alias
2549 ## repeat retrieve (exists = any(a.trans where a.name = @typename and
2550 ## a.type = "TYPE" and
2551 ## a.trans = @value))
2552 return (exists ? SMS_EXISTS : vo->error);
2555 /* validate member or type-specific data field */
2557 validate_typedata(q, argv, vo)
2558 register struct query *q;
2559 register char *argv[];
2560 register struct valobj *vo;
2563 ## char *field_type;
2564 ## char data_type[129];
2570 /* get named object */
2571 name = argv[vo->index];
2573 /* get field type string (known to be at index-1) */
2574 field_type = argv[vo->index-1];
2576 /* get corresponding data type associated with field type name */
2577 ## repeat retrieve (data_type = alias.trans)
2578 ## where alias.#name = @field_type and alias.type = "TYPEDATA"
2579 ## inquire_equel (rowcount = "rowcount")
2580 if (rowcount != 1) return(SMS_TYPE);
2582 /* now retrieve the record id corresponding to the named object */
2583 if (index(data_type, ' '))
2584 *index(data_type, ' ') = 0;
2585 if (!strcmp(data_type, "user")) {
2587 ## repeat retrieve (id = users.users_id) where users.login = @name
2588 ## inquire_equel (rowcount = "rowcount")
2589 if (rowcount != 1) return(SMS_USER);
2591 } else if (!strcmp(data_type, "list")) {
2593 ## repeat retrieve (id = list.list_id) where list.#name = @name
2594 ## inquire_equel (rowcount = "rowcount")
2595 if (rowcount != 1) {
2596 /* if idfield is non-zero, then if argv[0] matches the string
2597 * that we're trying to resolve, we should get the value of
2598 * values.[idfield] for the id.
2600 if (vo->idfield && !strcmp(argv[0], argv[vo->index])) {
2602 ## repeat retrieve (id = values.value+1) where values.#name = @name
2603 ## inquire_equel(rowcount = "rowcount")
2604 if (rowcount != 1) return(SMS_LIST);
2608 } else if (!strcmp(data_type, "machine")) {
2610 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
2611 ## repeat retrieve (id = machine.mach_id) where machine.#name = @name
2612 ## inquire_equel (rowcount = "rowcount")
2613 if (rowcount != 1) return(SMS_MACHINE);
2615 } else if (!strcmp(data_type, "string")) {
2617 ## range of s is strings
2618 ## repeat retrieve (id = s.string_id) where s.string = @name
2619 ## inquire_equel (rowcount = "rowcount")
2620 if (rowcount == 0) {
2621 if (q->type != APPEND) return(SMS_STRING);
2622 ## range of v is values
2623 ## retrieve (id = v.value) where v.#name = "strings_id"
2625 ## replace v (value = id) where v.#name = "strings_id"
2626 ## append to strings (string_id = id, string = name)
2628 } else if (!strcmp(data_type, "none")) {
2634 /* now set value in argv */
2635 *(int *)argv[vo->index] = id;
2637 return (SMS_EXISTS);
2641 /* This looks up a login name and returns the SMS internal ID. It is used
2642 * by authenticate to put the users_id in the client structure.
2645 int get_users_id(name)
2648 ## int id, rowcount;
2653 ## range of u is users
2654 ## repeat retrieve (id = u.#users_id) where u.#login = @login
2655 ## inquire_equel (rowcount = "rowcount")
2664 /* Check the database at startup time. For now this just resets the
2665 * inprogress flags that the DCM uses.
2668 sanity_check_database()
2670 ## replace servers (inprogress = 0)
2671 ## replace serverhosts (inprogress = 0)