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 = @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 retrieve (flag = any(members.member_id where members.member_id=@id
349 ## and members.member_type = "USER"))
352 ## repeat retrieve (flag = any(filesys.label where filesys.owner=@id))
355 ## repeat retrieve (flag = any(list.name where list.acl_id=@id and
356 ## list.acl_type = "USER"))
359 ## repeat retrieve (flag = any(servers.name where servers.acl_id=@id and
360 ## servers.acl_type = "USER"))
368 /* setup_spop: verify that there is already a valid POP machine_id in the
369 * pop_id field. Also take care of keeping track of the post office usage.
371 int setup_spop(q, argv)
378 id = *(int *)argv[0];
379 ## repeat retrieve (type = u.potype, flag = any(machine.name
380 ## where machine.mach_id = u.pop_id
382 ## and u.users_id = @id))
385 if (strcmp(type, "POP"))
386 set_pop_usage(id, 1);
391 /* setup_dpob: Take care of keeping track of the post office usage.
393 int setup_dpob(q, argv)
400 user = *(int *)argv[0];
401 ## repeat retrieve (type = u.potype, id = u.pop_id)
402 ## where u.users_id = @user
404 if (strcmp(type, "POP"))
405 set_pop_usage(id, -1);
410 /* setup_dmac - verify that the machine is no longer being referenced
411 * and may safely be deleted.
414 int setup_dmac(q, argv)
420 id = *(int *)argv[0];
421 ## repeat retrieve (flag = any(users.login where users.potype = "POP"
422 ## and users.pop_id=@id))
425 ## repeat retrieve (flag = any(serverhosts.mach_id
426 ## where serverhosts.mach_id=@id))
429 ## repeat retrieve (flag = any(nfsphys.mach_id where nfsphys.mach_id=@id))
432 ## repeat retrieve (flag = any(hostaccess.mach_id where hostaccess.mach_id=@id))
440 /* setup_dclu - verify that the cluster is no longer being referenced
441 * and may safely be deleted.
444 int setup_dclu(q, argv)
450 id = *(int *)argv[0];
451 ## repeat retrieve (flag = any(mcmap.mach_id where mcmap.clu_id=@id))
454 ## repeat retrieve (flag = any(svc.clu_id where svc.clu_id=@id))
462 /* setup_alis - if argv[5] is non-zero and argv[6] is UNIQUE_ID, then allocate
463 * a new gid and put it in argv[6]. Otherwise if argv[6] is UNIQUE_ID but
464 * argv[5] is not, then remember that UNIQUE_ID is being stored by putting
465 * a -1 there. Remember that this is also used for ulis, with the indexes
469 int setup_alis(q, argv)
477 if (!strcmp(q->shortname, "alis"))
479 else if (!strcmp(q->shortname, "ulis"))
482 if (!strcmp(argv[idx], UNIQUE_GID) || atoi(argv[idx]) == -1) {
483 if (atoi(argv[idx - 1])) {
484 if (set_next_object_id("gid", "list"))
485 return(SMS_INGRES_ERR);
486 ## repeat retrieve (ngid = values.value) where values.name = "gid"
487 sprintf(argv[idx], "%d", ngid);
489 strcpy(argv[idx], "-1");
497 /* setup_dlist - verify that the list is no longer being referenced
498 * and may safely be deleted.
501 int setup_dlis(q, argv)
507 id = *(int *)argv[0];
508 ## repeat retrieve (flag = any(members.member_id where members.member_id=@id
509 ## and members.member_type = "LIST"))
512 ## repeat retrieve (flag = any(members.member_id where members.list_id=@id))
515 ## repeat retrieve (flag = any(filesys.label where filesys.owners=@id))
518 ## repeat retrieve (flag = any(capacls.tag where capacls.list_id=@id))
521 ## repeat retrieve (flag = any(list.name where list.acl_id=@id and
522 ## list.acl_type = "LIST"))
525 ## repeat retrieve (flag = any(servers.name where servers.acl_id=@id and
526 ## servers.acl_type = "LIST"))
529 ## repeat retrieve (flag = any(zephyr.class
530 ## where zephyr.xmt_type = "LIST" and zephyr.xmt_id = @id or
531 ## zephyr.sub_type = "LIST" and zephyr.sub_id = @id or
532 ## zephyr.iws_type = "LIST" and zephyr.iws_id = @id or
533 ## zephyr.iui_type = "LIST" and zephyr.iui_id = @id))
541 /* setup_dsin - verify that the service is no longer being referenced
542 * and may safely be deleted.
545 int setup_dsin(q, argv)
553 ## repeat retrieve (flag = any(serverhosts.service where serverhosts.service=@name))
556 ## repeat retrieve (flag = servers.inprogress) where servers.#name = @name
564 /* setup_dshi - verify that the service-host is no longer being referenced
565 * and may safely be deleted.
568 int setup_dshi(q, argv)
576 id = *(int *)argv[1];
577 ## repeat retrieve (flag=serverhosts.inprogress)
578 ## where serverhosts.service=@name and serverhosts.mach_id=@id
587 ** setup_add_filesys - verify existance of referenced file systems
599 ** * extract directory prefix from name
600 ** * verify mach_id/dir in nfsphys
601 ** * verify access in {r, w, R, W}
603 ** Side effect: sets variable var_phys_id to the ID of the physical
604 ** filesystem (nfsphys_id for NFS, 0 for RVD)
607 ** SMS_NFS - specified directory not exported
608 ** SMS_FILESYS_ACCESS - invalid filesys access
612 ##static int var_phys_id;
624 mach_id = *(int *)argv[2];
629 if (!strcmp(type, "NFS"))
630 return (check_nfs(mach_id, name, access));
646 mach_id = *(int *)argv[3];
651 if (!strcmp(type, "NFS"))
652 return (check_nfs(mach_id, name, access));
658 /* Find the NFS physical partition that the named directory is on.
659 * This is done by comparing the dir against the mount point of the
660 * partition. To make sure we get the correct match when there is
661 * more than one, we sort the query in reverse order by dir name.
664 ##check_nfs(mach_id, name, access)
675 caccess = (isupper(*access)) ? tolower(*access) : *access;
676 if (caccess != 'r' && caccess != 'w') return(SMS_FILESYS_ACCESS);
679 ## range of np is nfsphys
680 ## repeat retrieve (var_phys_id = np.#nfsphys_id, dir = trim(np.#dir))
681 ## where np.#mach_id = @mach_id sort by #dir:d {
685 if (*cp1++ != *cp2) break;
689 status = SMS_SUCCESS;
698 /* setup_dfil: free any quota records associated with a filesystem
699 * when it is deleted.
702 setup_dfil(q, argv, cl)
709 id = *(int *)argv[0];
710 ## range of q is nfsquota
711 ## repeat replace nfsphys (allocated = nfsphys.allocated - q.quota)
712 ## where nfsphys.nfsphys_id = fs.phys_id and
713 ## q.filsys_id = @id and fs.filsys_id = @id
715 ## repeat delete q where q.filsys_id = @id
720 /* setup_dnfp: check to see that the nfs physical partition does not have
721 * any filesystems assigned to it before allowing it to be deleted.
724 setup_dnfp(q, argv, cl)
731 id = *(int *)argv[0];
732 ## repeat retrieve (exists = any(filesys.label where filesys.phys_id = @id))
739 /* setup_ssif: check to see if lock is already set. If it is not set or
740 * it is set, but this request is turning it off, fine. Otherwise, give
741 * a lock error. setup_sshi is the same for each serverhost.
744 setup_ssif(q, argv, cl)
753 ## repeat retrieve (lock = s.inprogress) where s.name = @service
754 if (lock && atoi(argv[2]))
760 setup_sshi(q, argv, cl)
766 ## int lock, mach_id;
769 mach_id = *(int *)argv[1];
770 ## repeat retrieve (lock = sh.inprogress) where sh.#mach_id = @mach_id and
771 ## sh.#service = @service
772 if (lock && atoi(argv[4]))
778 /* setup_dnfq: Remove allocation from nfsphys before deleting quota.
779 * argv[0] = filsys_id
783 setup_dnfq(q, argv, cl)
788 ## int quota, fs, user;
790 fs = *(int *)argv[0];
791 user = *(int *)argv[1];
793 ## range of q is nfsquota
794 ## repeat retrieve (quota = q.#quota) where q.users_id = @user and
796 ## repeat replace nfsphys (allocated = nfsphys.allocated - @quota)
797 ## where nfsphys.nfsphys_id = filesys.#phys_id and filesys.filsys_id = @fs
803 /* FOLLOWUP ROUTINES */
805 /* generic set_modtime routine. This takes the table name from the query,
806 * and will update the modtime, modby, and modwho fields in the entry in
807 * the table whose name field matches argv[0].
810 set_modtime(q, argv, cl)
815 ## char *name, *entity, *table;
823 ## replace table (modtime = "now", modby = who, modwith = entity)
824 ## where table.#name = name
828 /* generic set_modtime_by_id routine. This takes the table name from
829 * the query, and the id name from the validate record,
830 * and will update the modtime, modby, and modwho fields in the entry in
831 * the table whose id matches argv[0].
834 set_modtime_by_id(q, argv, cl)
839 ## char *entity, *table, *id_name;
845 id_name = q->validate->object_id;
847 id = *(int *)argv[0];
848 ## replace table (modtime = "now", modby = who, modwith = entity)
849 ## where table.id_name = id
854 /* Sets the finger modtime on a user record. The users_id will be in argv[0].
857 set_finger_modtime(q, argv, cl)
862 ## int users_id, who;
867 users_id = *(int *)argv[0];
869 ## repeat replace u (fmodtime = "now", fmodby = @who, fmodwith = @entity)
870 ## where u.#users_id = @users_id
875 /* Sets the pobox modtime on a user record. The users_id will be in argv[0].
878 set_pobox_modtime(q, argv, cl)
883 ## int users_id, who;
888 users_id = *(int *)argv[0];
890 ## repeat replace users (pmodtime = "now", pmodby = @who, pmodwith = @entity)
891 ## where users.#users_id = @users_id
896 /* Sets the modtime on a machine record. The machine name is in argv[0].
897 * This routine is different from the generic set_modtime in that the
898 * name is uppercased first.
901 set_mach_modtime(q, argv, cl)
906 ## char *host, *entity;
913 ## repeat replace m (modtime = "now", modby = @who, modwith = @entity)
914 ## where m.name = uppercase(@host)
919 /* Sets the modtime on the machine whose mach_id is in argv[0]. This routine
920 * is necessary for add_machine_to_cluster becuase the table that query
921 * operates on is "mcm", not "machine".
924 set_mach_modtime_by_id(q, argv, cl)
935 id = *(int *)argv[0];
936 ## range of m is machine
937 ## repeat replace m (modtime = "now", modby = @who, modwith = @entity)
938 ## where m.mach_id = @id
943 /* Sets the modtime on the cluster whose mach_id is in argv[0]. This routine
944 * is necessary for add_cluster_data and delete_cluster_data becuase the
945 * table that query operates on is "svc", not "cluster".
948 set_cluster_modtime_by_id(q, argv, cl)
959 id = *(int *)argv[0];
960 ## range of c is cluster
961 ## repeat replace c (modtime = "now", modby = @who, modwith = @entity)
962 ## where c.clu_id = @id
967 /* sets the modtime on the serverhost where the service name is in argv[0]
968 * and the mach_id is in argv[1].
971 set_serverhost_modtime(q, argv, cl)
976 ## char *entity, *serv;
983 id = *(int *)argv[1];
984 ## repeat replace sh (modtime = "now", modby = @who, modwith = @entity)
985 ## where sh.service = @serv and sh.mach_id = @id
990 /* sets the modtime on the nfsphys where the mach_id is in argv[0] and the
991 * directory name is in argv[1].
994 set_nfsphys_modtime(q, argv, cl)
999 ## char *entity, *dir;
1002 entity = cl->entity;
1005 id = *(int *)argv[0];
1007 ## repeat replace np (modtime = "now", modby = @who, modwith = @entity)
1008 ## where np.#dir = @dir and np.mach_id = @id
1009 return(SMS_SUCCESS);
1013 /* sets the modtime on a filesystem, where argv[0] contains the filesys
1017 set_filesys_modtime(q, argv, cl)
1022 ## char *label, *entity;
1025 entity = cl->entity;
1029 if (!strcmp(q->shortname, "ufil"))
1032 ## repeat replace fs (modtime = "now", modby = @who, modwith = @entity,
1033 ## #phys_id = @var_phys_id) where fs.#label = @label
1034 return(SMS_SUCCESS);
1038 /* sets the modtime on a zephyr class, where argv[0] contains the class
1042 set_zephyr_modtime(q, argv, cl)
1047 ## char *class, *entity;
1050 entity = cl->entity;
1055 ## repeat replace z (modtime = "now", modby = @who, modwith = @entity)
1056 ## where z.#class = @class
1057 return(SMS_SUCCESS);
1061 /* fixes the modby field. This will be the second to last thing in the
1062 * argv, the argv length is determined from the query structure. It is
1063 * passed as a pointer to an integer. This will either turn it into a
1064 * username, or # + the users_id.
1066 followup_fix_modby(q, sq, v, action, actarg, cl)
1068 register struct save_queue *sq;
1070 register int (*action)();
1071 register int actarg;
1075 char **argv, *malloc();
1076 ## int id, rowcount;
1080 while (sq_get_data(sq, &argv)) {
1083 argv[i] = malloc(9);
1085 ## repeat retrieve (name = users.login) where users.users_id = @id
1086 ## inquire_equel(rowcount = "rowcount")
1087 if (rowcount != 1) {
1088 sprintf(argv[i], "#%d", id);
1090 (*action)(q->vcnt, argv, actarg);
1091 for (j = 0; j < q->vcnt; j++)
1096 return(SMS_SUCCESS);
1101 ** followup_ausr - add finger and pobox entries, set_user_modtime
1104 ** argv[0] - login (add_user)
1105 ** argv[3] - last name
1106 ** argv[4] - first name
1107 ** argv[5] - middle name
1111 followup_ausr(q, argv, cl)
1117 ## char *login, *entity;
1118 ## char fullname[129];
1122 entity = cl->entity;
1124 /* build fullname */
1125 if (strlen(argv[4]) && strlen(argv[5]))
1126 sprintf(fullname, "%s %s %s", argv[4], argv[5], argv[3]);
1127 else if (strlen(argv[4]))
1128 sprintf(fullname, "%s %s", argv[4], argv[3]);
1130 sprintf(fullname, "%s", argv[3]);
1132 /* create finger entry, pobox & set modtime on user */
1133 ## repeat replace u (modtime = "now", modby=@who, modwith=@entity,
1134 ## #fullname=@fullname, mit_affil = u.mit_year,
1135 ## fmodtime="now", fmodby=@who, fmodwith=@entity,
1136 ## potype="NONE", pmodtime="now", pmodby=@who, pmodwith=@entity)
1137 ## where u.#login = @login
1139 return(SMS_SUCCESS);
1143 /* followup_gpob: fixes argv[2] based on the IDs currently there and the
1144 * type in argv[1]. Then completes the upcall to the user.
1146 * argv[2] is of the form "123:234" where the first integer is the machine
1147 * ID if it is a pop box, and the second is the string ID if it is an SMTP
1148 * box. argv[1] should be "POP", "SMTP", or "NONE". Boxes of type NONE
1152 followup_gpob(q, sq, v, action, actarg, cl)
1153 register struct query *q;
1154 register struct save_queue *sq;
1155 register struct validate *v;
1156 register int (*action)();
1160 char **argv, *index();
1162 ## char box[129], *name;
1163 ## int mid, sid, rowcount;
1166 while (sq_get_data(sq, &argv)) {
1167 sms_trim_args(2, argv);
1169 p = index(argv[2], ':');
1171 mid = atoi(argv[2]);
1175 if (!strcmp(ptype, "POP")) {
1176 ## repeat retrieve (box=machine.#name) where machine.mach_id=@mid
1177 ## inquire_equel(rowcount = "rowcount")
1179 return(SMS_MACHINE);
1180 } else if (!strcmp(ptype, "SMTP")) {
1181 ## repeat retrieve (box=strings.string) where strings.string_id=@sid
1182 ## inquire_equel(rowcount = "rowcount")
1185 } else /* ptype == "NONE" */ {
1189 if (!strcmp(q->shortname, "gpob")) {
1190 sid = atoi(argv[4]);
1192 argv[4] = malloc(9);
1194 ## repeat retrieve (name = users.login) where users.users_id = @sid
1195 ## inquire_equel(rowcount = "rowcount")
1197 sprintf(name, "#%d", sid);
1201 (*action)(q->vcnt, argv, actarg);
1203 /* free saved data */
1210 return (SMS_SUCCESS);
1214 /* followup_glin: fix the acl_name in argv[8]. argv[7] will contain the
1215 * acl_type: "LIST", "USER", or "NONE". Decode the id in argv[8] into the
1216 * proper name based on the type, and repace that string in the argv.
1217 * Also fixes the modby field by called followup_fix_modby.
1220 followup_glin(q, sq, v, action, actarg, cl)
1221 register struct query *q;
1222 register struct save_queue *sq;
1223 register struct validate *v;
1224 register int (*action)();
1228 char **argv, *malloc(), *realloc(), *type;
1230 ## int id, rowcount;
1234 if (!strcmp(q->shortname, "gsin"))
1237 while (sq_get_data(sq, &argv)) {
1238 sms_trim_args(q->vcnt, argv);
1240 id = atoi(argv[i = q->vcnt - 2]);
1242 name = argv[i] = malloc(9);
1243 ## repeat retrieve (name = users.login) where users.users_id = @id
1244 ## inquire_equel(rowcount = "rowcount")
1246 sprintf(argv[i], "#%d", id);
1248 id = atoi(argv[idx]);
1249 type = argv[idx - 1];
1250 if ((name = malloc(33)) == NULL)
1253 if (!strcmp(type, "LIST")) {
1254 ## repeat retrieve (name = list.#name) where list.list_id = @id
1255 ## inquire_equel(rowcount = "rowcount")
1257 strcpy(name, "???");
1258 } else if (!strcmp(type, "USER")) {
1259 ## repeat retrieve (name = users.login) where users.users_id = @id
1260 ## inquire_equel(rowcount = "rowcount")
1262 strcpy(name, "???");
1263 } else if (!strcmp(type, "NONE")) {
1264 strcpy(name, "NONE");
1266 strcpy(name, "???");
1270 if (!strcmp(q->shortname, "glin") && atoi(argv[6]) == -1) {
1271 argv[6] = realloc(argv[6], strlen(UNIQUE_GID) + 1);
1272 strcpy(argv[6], UNIQUE_GID);
1276 (*action)(q->vcnt, argv, actarg);
1278 /* free saved data */
1279 for (i = 0; i < q->vcnt; i++)
1285 return (SMS_SUCCESS);
1289 /** followup_amtl - followup for amtl and dmfl; when adding a list
1290 ** member to a maillist, make member list a maillist also
1291 ** unless list is a user-group.
1292 ** Then set_list_modtime_by_id.
1295 ** argv[0] - list_id
1296 ** argv[1] - member_type
1297 ** argv[2] - member_id
1301 followup_amtl(q, argv, cl)
1311 list_id = *(int *)argv[0];
1312 entity = cl->entity;
1315 ## range of l is list
1316 ## repeat replace l (modtime = "now", modby = @who, modwith = @entity)
1317 ## where l.#list_id = @list_id
1319 /* if query is not amtl or if member_type is not LIST then return */
1320 if (bcmp(q->shortname, "amtl", 4) || bcmp(argv[1], "LIST", 4))
1321 return(SMS_SUCCESS);
1323 member_id = *(int *)argv[2];
1325 /* is parent list a mailing list? */
1326 ## repeat retrieve (exists = l.maillist) where l.#list_id=@list_id
1328 return(SMS_SUCCESS);
1330 /* list is not a user-group; add list to maillist table */
1331 ## repeat replace l (maillist = 1) where l.#list_id = @member_id
1332 return(SMS_SUCCESS);
1336 /* followup_anfq: Add allocation to nfsphys after creating quota.
1337 * argv[0] = filsys_id
1338 * argv[2] = ascii(quota)
1341 followup_anfq(q, argv, cl)
1346 ## int quota, user, fs, who;
1349 fs = *(int *)argv[0];
1350 user = *(int *)argv[1];
1351 quota = atoi(argv[2]);
1353 entity = cl->entity;
1355 ## repeat replace nq (modtime = "now", modby = @who, modwith = @entity)
1356 ## where nq.filsys_id = @fs and nq.users_id = @user
1357 ## repeat replace nfsphys (allocated = nfsphys.allocated + @quota)
1358 ## where nfsphys.nfsphys_id = filesys.#phys_id and filesys.filsys_id = @fs
1359 return(SMS_SUCCESS);
1366 followup_gzcl(q, sq, v, action, actarg, cl)
1367 register struct query *q;
1368 register struct save_queue *sq;
1369 register struct validate *v;
1370 register int (*action)();
1375 ## int rowcount, id;
1379 while (sq_get_data(sq, &argv)) {
1380 sms_trim_args(q->vcnt, argv);
1382 id = atoi(argv[i = q->vcnt - 2]);
1384 name = argv[i] = malloc(9);
1385 ## repeat retrieve (name = users.login) where users.users_id = @id
1386 ## inquire_equel(rowcount = "rowcount")
1388 sprintf(argv[i], "#%d", id);
1390 for (i = 1; i < 8; i+=2) {
1391 id = atoi(argv[i+1]);
1393 if ((name = argv[i+1] = malloc(33)) == NULL)
1395 if (!strcmp(argv[i], "LIST")) {
1396 ## repeat retrieve (name = list.#name) where list.list_id = @id
1397 ## inquire_equel(rowcount = "rowcount")
1399 strcpy(name, "???");
1400 } else if (!strcmp(argv[i], "USER")) {
1401 ## repeat retrieve (name = users.login) where users.users_id = @id
1402 ## inquire_equel(rowcount = "rowcount")
1404 strcpy(name, "???");
1405 } else if (!strcmp(argv[i], "NONE")) {
1406 strcpy(name, "NONE");
1408 strcpy(name, "???");
1413 (*action)(q->vcnt, argv, actarg);
1415 /* free saved data */
1416 for (i = 0; i < q->vcnt; i++)
1421 return(SMS_SUCCESS);
1428 followup_gsha(q, sq, v, action, actarg, cl)
1429 register struct query *q;
1430 register struct save_queue *sq;
1431 register struct validate *v;
1432 register int (*action)();
1437 ## int rowcount, id;
1441 while (sq_get_data(sq, &argv)) {
1442 sms_trim_args(q->vcnt, argv);
1446 name = argv[4] = malloc(9);
1447 ## repeat retrieve (name = users.login) where users.users_id = @id
1448 ## inquire_equel(rowcount = "rowcount")
1450 sprintf(argv[4], "#%d", id);
1454 if ((name = argv[2] = malloc(33)) == NULL)
1456 if (!strcmp(argv[1], "LIST")) {
1457 ## repeat retrieve (name = list.#name) where list.list_id = @id
1458 ## inquire_equel(rowcount = "rowcount")
1460 strcpy(name, "???");
1461 } else if (!strcmp(argv[1], "USER")) {
1462 ## repeat retrieve (name = users.login) where users.users_id = @id
1463 ## inquire_equel(rowcount = "rowcount")
1465 strcpy(name, "???");
1466 } else if (!strcmp(argv[1], "NONE")) {
1467 strcpy(name, "NONE");
1469 strcpy(name, "???");
1473 (*action)(q->vcnt, argv, actarg);
1475 /* free saved data */
1476 for (i = 0; i < q->vcnt; i++)
1481 return(SMS_SUCCESS);
1486 /* Special query routines */
1488 /* set_pobox - this does all of the real work.
1489 * argv = user_id, type, box
1490 * if type is POP, then box should be a machine, and its ID should be put in
1491 * pop_id. If type is SMTP, then box should be a string and its ID should
1492 * be put in box_id. If type is NONE, then box doesn't matter.
1495 int set_pobox(q, argv, cl)
1500 ## int user, id, rowcount;
1501 ## char *box, potype[9];
1504 user = *(int *)argv[0];
1506 ## repeat retrieve (id = users.pop_id, potype = users.#potype)
1507 ## where users.users_id = @user
1508 if (!strcmp(potype, "POP"))
1509 set_pop_usage(id, -1);
1511 if (!strcmp(argv[1], "POP")) {
1512 ## repeat retrieve (id=machine.mach_id) where machine.name=uppercase(@box)
1513 ## inquire_equel(rowcount = "rowcount")
1515 return(SMS_MACHINE);
1516 ## repeat replace users (#potype = "POP", pop_id = @id)
1517 ## where users.users_id = @user
1518 set_pop_usage(id, 1);
1519 } else if (!strcmp(argv[1], "SMTP")) {
1520 ## range of s is strings
1521 ## repeat retrieve (id = s.string_id) where s.string = @box
1522 ## inquire_equel (rowcount = "rowcount")
1523 if (rowcount == 0) {
1524 ## range of v is values
1525 ## repeat retrieve (id = v.value) where v.name = "strings_id"
1527 ## repeat replace v (value = @id) where v.name = "strings_id"
1528 ## append to strings (string_id = id, string = box)
1530 ## repeat replace users (#potype = "SMTP", box_id = @id)
1531 ## where users.users_id = @user
1532 } else /* argv[1] == "NONE" */ {
1533 ## repeat replace users (#potype = "NONE") where users.users_id = @user
1536 set_pobox_modtime(q, argv, cl);
1537 ## repeat replace tblstats (updates = tblstats.updates + 1, modtime = "now")
1538 ## where tblstats.#table = "users"
1539 return(SMS_SUCCESS);
1543 /* get_list_info: passed a wildcard list name, returns lots of stuff about
1544 * each list. This is tricky: first build a queue of all requested
1545 * data. Rest of processing consists of fixing gid, acl_name, and modby.
1548 get_list_info(q, aargv, cl, action, actarg)
1549 register struct query *q;
1552 register int (*action)();
1555 char *argv[13], *malloc(), *realloc();
1556 ## char *name, acl_type[9], listname[33], active[5], public[5], hidden[5];
1557 ## char maillist[5], group[5], gid[6], acl_name[33], desc[256], modtime[27];
1558 ## char modby[9], modwith[9];
1559 ## int id, rowcount, acl_id, hid, modby_id;
1561 struct save_queue *sq, *sq_create();
1563 returned = rowcount = 0;
1567 ## range of l is list
1568 ## repeat retrieve (id = l.list_id) where l.#name = @name {
1569 sq_save_data(sq, id);
1573 return(SMS_NO_MATCH);
1575 argv[0] = listname; argv[1] = active; argv[2] = public; argv[3] = hidden;
1576 argv[4] = maillist; argv[5] = group; argv[6] = gid; argv[7] = acl_type;
1577 argv[8] = acl_name; argv[9] = desc; argv[10] = modtime; argv[11] = modby;
1580 while (sq_get_data(sq, &id)) {
1584 ## repeat retrieve (listname = l.#name, active = text(l.#active),
1585 ## public = text(l.#public), hidden = text(l.#hidden),
1586 ## hid = l.#hidden, maillist = text(l.#maillist),
1587 ## group = text(l.#group), gid = text(l.#gid),
1588 ## acl_type = trim(l.#acl_type), acl_id = l.#acl_id,
1589 ## desc = l.#desc, modtime = l.#modtime, modby_id = l.#modby,
1590 ## modwith =l.#modwith)
1591 ## where l.list_id = @id
1593 if (atoi(gid) == -1)
1594 argv[6] = UNIQUE_GID;
1596 if (!strcmp(acl_type, "LIST")) {
1597 ## repeat retrieve (acl_name = l.#name) where l.list_id = @acl_id
1598 ## inquire_equel(rowcount = "rowcount")
1600 strcpy(acl_name, "???");
1601 } else if (!strcmp(acl_type, "USER")) {
1602 ## repeat retrieve (acl_name = users.#login)
1603 ## where users.users_id = @acl_id
1604 ## inquire_equel(rowcount = "rowcount")
1606 strcpy(acl_name, "???");
1607 } else if (!strcmp(acl_type, "NONE")) {
1608 strcpy(acl_name, "NONE");
1610 strcpy(acl_name, "???");
1612 ## repeat retrieve (modby = users.login) where users.users_id = @modby_id
1613 ## inquire_equel(rowcount = "rowcount")
1615 sprintf(modby, "#%d", id);
1617 sms_trim_args(q->vcnt, argv);
1619 (*action)(q->vcnt, argv, actarg);
1623 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
1624 ## where tblstats.#table = "list"
1626 return (SMS_SUCCESS);
1630 /* get_acl_use - given a type and a name, return a type and a name.
1631 * The acl_type is one of "LIST", "USER", "RLIST", or "RUSER" in argv[0],
1632 * and argv[1] will contain the ID of the entity in question. The R*
1633 * types mean to recursively look at every containing list, not just
1634 * when the object in question is a direct member. On return, the
1635 * usage type will be one of LIST, SERVICE, FILESYS, QUOTA, QUERY, or ZEPHYR.
1638 int get_acl_use(q, argv, cl, action, actarg)
1647 ## int aid, listid, id;
1648 struct save_queue *sq, *sq_create();
1651 aid = *(int *)argv[1];
1652 if (!strcmp(atype, "LIST") || !strcmp(atype, "USER")) {
1653 return(get_acl_internal(atype, aid, action, actarg));
1657 if (!strcmp(atype, "RLIST")) {
1658 sq_save_data(sq, aid);
1659 /* get all the list_id's of containing lists */
1660 ## range of m is members
1661 while (sq_get_data(sq, &id)) {
1662 ## repeat retrieve (listid = m.list_id)
1663 ## where m.member_type = "LIST" and m.member_id = @id {
1664 sq_save_unique_data(sq, listid);
1667 /* now process each one */
1668 while (sq_get_data(sq, &id)) {
1669 if (get_acl_internal("LIST", id, action, actarg) == SMS_SUCCESS)
1674 if (!strcmp(atype, "RUSER")) {
1675 ## range of m is members
1676 ## repeat retrieve (listid = m.list_id)
1677 ## where m.member_type = "USER" and m.member_id = @aid {
1678 sq_save_data(sq, listid);
1680 /* get all the list_id's of containing lists */
1681 while (sq_get_data(sq, &id)) {
1682 ## repeat retrieve (listid = m.list_id)
1683 ## where m.member_type = "LIST" and m.member_id = @id {
1684 sq_save_unique_data(sq, listid);
1687 /* now process each one */
1688 while (sq_get_data(sq, &id)) {
1689 if (get_acl_internal("LIST", id, action, actarg) == SMS_SUCCESS)
1692 if (get_acl_internal("USER", aid, action, actarg) == SMS_SUCCESS)
1697 if (!found) return(SMS_NO_MATCH);
1698 return(SMS_SUCCESS);
1702 /* This looks up a single list or user for acl use. atype must be "USER"
1703 * or "LIST", and aid is the ID of the corresponding object. This is used
1704 * by get_acl_use above.
1707 ##get_acl_internal(atype, aid, action, actarg)
1718 if (!strcmp(atype, "LIST")) {
1719 rargv[0] = "FILESYS";
1720 ## repeat retrieve (name = filesys.label)
1721 ## where filesys.owners = @aid {
1722 (*action)(2, rargv, actarg);
1727 ## repeat retrieve (name = capacls.capability)
1728 ## where capacls.list_id = @aid {
1729 (*action)(2, rargv, actarg);
1732 } else if (!strcmp(atype, "USER")) {
1733 rargv[0] = "FILESYS";
1734 ## repeat retrieve (name = filesys.label)
1735 ## where filesys.owner = @aid {
1736 (*action)(2, rargv, actarg);
1742 ## repeat retrieve (name = list.#name)
1743 ## where list.acl_type = @atype and list.acl_id = @aid {
1744 (*action)(2, rargv, actarg);
1748 rargv[0] = "SERVICE";
1749 ## repeat retrieve (name = servers.#name)
1750 ## where servers.acl_type = @atype and servers.acl_id = @aid {
1751 (*action)(2, rargv, actarg);
1755 rargv[0] = "HOSTACCESS";
1756 ## repeat retrieve (name = machine.#name)
1757 ## where machine.mach_id = hostaccess.mach_id and
1758 ## hostaccess.acl_type = @atype and hostaccess.acl_id = @aid {
1759 (*action)(2, rargv, actarg);
1762 rargv[0] = "ZEPHYR";
1763 ## repeat retrieve (name = zephyr.class)
1764 ## where zephyr.xmt_type = @atype and zephyr.xmt_id = @aid or
1765 ## zephyr.sub_type = @atype and zephyr.sub_id = @aid or
1766 ## zephyr.iws_type = @atype and zephyr.iws_id = @aid or
1767 ## zephyr.iui_type = @atype and zephyr.iui_id = @aid {
1768 (*action)(2, rargv, actarg);
1772 if (!found) return(SMS_NO_MATCH);
1773 return(SMS_SUCCESS);
1777 /* get_lists_of_member - given a type and a name, return the name and flags
1778 * of all of the lists of the given member. The member_type is one of
1779 * "LIST", "USER", "STRING", "RLIST", "RUSER", or "RSTRING" in argv[0],
1780 * and argv[1] will contain the ID of the entity in question. The R*
1781 * types mean to recursively look at every containing list, not just
1782 * when the object in question is a direct member.
1785 int get_lists_of_member(q, argv, cl, action, actarg)
1794 ## int aid, listid, id;
1795 struct save_queue *sq, *sq_create();
1798 aid = *(int *)argv[1];
1799 if (!strcmp(atype, "LIST") ||
1800 !strcmp(atype, "USER") ||
1801 !strcmp(atype, "STRING")) {
1802 return(glom_internal(atype, aid, action, actarg));
1806 if (!strcmp(atype, "RLIST")) {
1807 sq_save_data(sq, aid);
1808 /* get all the list_id's of containing lists */
1809 ## range of m is members
1810 while (sq_get_data(sq, &id)) {
1811 ## repeat retrieve (listid = m.list_id)
1812 ## where m.member_type = "LIST" and m.member_id = @id {
1813 sq_save_unique_data(sq, listid);
1816 /* now process each one */
1817 while (sq_get_data(sq, &id)) {
1818 if (glom_internal("LIST", id, action, actarg) == SMS_SUCCESS)
1823 if (!strcmp(atype, "RUSER")) {
1824 ## range of m is members
1825 ## repeat retrieve (listid = m.list_id)
1826 ## where m.member_type = "USER" and m.member_id = @aid {
1827 sq_save_data(sq, listid);
1829 /* get all the list_id's of containing lists */
1830 while (sq_get_data(sq, &id)) {
1831 ## repeat retrieve (listid = m.list_id)
1832 ## where m.member_type = "LIST" and m.member_id = @id {
1833 sq_save_unique_data(sq, listid);
1836 /* now process each one */
1837 while (sq_get_data(sq, &id)) {
1838 if (glom_internal("LIST", id, action, actarg) == SMS_SUCCESS)
1841 if (glom_internal("USER", aid, action, actarg) == SMS_SUCCESS)
1845 if (!strcmp(atype, "RSTRING")) {
1846 ## range of m is members
1847 ## repeat retrieve (listid = m.list_id)
1848 ## where m.member_type = "STRING" and m.member_id = @aid {
1849 sq_save_data(sq, listid);
1851 /* get all the list_id's of containing lists */
1852 while (sq_get_data(sq, &id)) {
1853 ## repeat retrieve (listid = m.list_id)
1854 ## where m.member_type = "LIST" and m.member_id = @id {
1855 sq_save_unique_data(sq, listid);
1858 /* now process each one */
1859 while (sq_get_data(sq, &id)) {
1860 if (glom_internal("LIST", id, action, actarg) == SMS_SUCCESS)
1863 if (glom_internal("STRING", aid, action, actarg) == SMS_SUCCESS)
1867 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
1868 ## where tblstats.#table = "members"
1870 if (!found) return(SMS_NO_MATCH);
1871 return(SMS_SUCCESS);
1875 /* This looks up a single list, user, or string as a member. atype must be
1876 * "USER", "LIST", or "STRING" and aid is the ID of the corresponding object.
1877 * This is used by get_lists_of_members above.
1880 ##glom_internal(atype, aid, action, actarg)
1888 ## char name[33], active[5], public[5], hidden[5], maillist[5], group[5];
1894 rargv[4] = maillist;
1896 ## repeat retrieve (name = list.#name, active = text(list.#active),
1897 ## public = text(list.#public), hidden = text(list.#hidden),
1898 ## maillist = text(list.#maillist), group = text(list.#group))
1899 ## where list.list_id = m.list_id and
1900 ## m.member_type = @atype and m.member_id = @aid {
1901 (*action)(6, rargv, actarg);
1905 if (!found) return(SMS_NO_MATCH);
1906 return(SMS_SUCCESS);
1910 /* qualified_get_lists: passed "TRUE", "FALSE", or "DONTCARE" for each of
1911 * the five flags associated with each list. It will return the name of
1912 * each list that meets the quailifications. It does this by building a
1913 * where clause based on the arguments, then doing a retrieve.
1916 static char *lflags[5] = { "active", "public", "hidden", "maillist", "group" };
1918 int qualified_get_lists(q, argv, cl, action, actarg)
1925 return(qualified_get(q, argv, action, actarg, "l.list_id != 0",
1926 "l", "name", lflags));
1930 /** get_members_of_list - optimized query for retrieval of list members
1933 ** argv[0] - list_id
1936 ** - retrieve USER members, then LIST members, then STRING members
1939 get_members_of_list(q, argv, cl, action, actarg)
1947 ## char member_name[129];
1950 list_id = *(int *)argv[0];
1952 targv[1] = member_name;
1954 ## range of m is members
1955 ## repeat retrieve (member_name = users.login)
1956 ## where m.#list_id = @list_id and m.member_type = "USER"
1957 ## and m.member_id = users.users_id
1958 ## sort by #member_name
1960 (*action)(2, targv, actarg);
1964 ## repeat retrieve (member_name = list.name)
1965 ## where m.#list_id = @list_id and m.member_type = "LIST"
1966 ## and m.member_id = list.#list_id
1967 ## sort by #member_name
1969 (*action)(2, targv, actarg);
1972 targv[0] = "STRING";
1973 ## repeat retrieve (member_name = strings.string)
1974 ## where m.#list_id = @list_id and m.member_type = "STRING"
1975 ## and m.member_id = strings.string_id
1976 ## sort by #member_name
1978 (*action)(2, targv, actarg);
1981 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
1982 ## where tblstats.#table = "members"
1983 return(SMS_SUCCESS);
1987 /* count_members_of_list: this is a simple query, but it cannot be done
1988 * through the dispatch table.
1991 int count_members_of_list(q, argv, cl, action, actarg)
1998 ## int list, ct = 0;
1999 char *rargv[1], countbuf[5];
2001 list = *(int *)argv[0];
2002 rargv[0] = countbuf;
2003 ## repeat retrieve (ct = count(members.list_id where members.list_id = @list))
2004 sprintf(countbuf, "%d", ct);
2005 (*action)(1, rargv, actarg);
2006 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
2007 ## where tblstats.#table = "members"
2008 return(SMS_SUCCESS);
2012 /* qualified_get_server: passed "TRUE", "FALSE", or "DONTCARE" for each of
2013 * the three flags associated with each service. It will return the name of
2014 * each service that meets the quailifications. It does this by building a
2015 * where clause based on the arguments, then doing a retrieve.
2018 static char *sflags[3] = { "enable", "inprogress", "harderror" };
2020 int qualified_get_server(q, argv, cl, action, actarg)
2027 return(qualified_get(q, argv, action, actarg, "s.name != \"\"",
2028 "s", "name", sflags));
2032 /* generic qualified get routine, used by qualified_get_lists,
2033 * qualified_get_server, and qualified_get_serverhost.
2035 * start - a simple where clause, must not be empty
2036 * range - the name of the range variable
2037 * field - the field to return
2038 * flags - an array of strings, names of the flag variables
2041 int qualified_get(q, argv, action, actarg, start, range, field, flags)
2051 ## char name[33], qual[256], *rvar, *rtbl, *rfield;
2052 char *rargv[1], buf[32];
2055 strcpy(qual, start);
2056 for (i = 0; i < q->argc; i++) {
2057 if (!strcmp(argv[i], "TRUE")) {
2058 sprintf(buf, " and %s.%s != 0", range, flags[i]);
2059 (void) strcat(qual, buf);
2060 } else if (!strcmp(argv[i], "FALSE")) {
2061 sprintf(buf, " and %s.%s = 0", range, flags[i]);
2062 (void) strcat(qual, buf);
2070 ## range of rvar is rtbl
2071 ## retrieve (name = rvar.rfield) where qual {
2072 (*action)(1, rargv, actarg);
2074 ## inquire_equel(rowcount = "rowcount")
2075 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
2076 ## where tblstats.#table = @rtbl
2078 return(SMS_NO_MATCH);
2079 return(SMS_SUCCESS);
2083 /* qualified_get_serverhost: passed "TRUE", "FALSE", or "DONTCARE" for each of
2084 * the five flags associated with each serverhost. It will return the name of
2085 * each service and host that meets the quailifications. It does this by
2086 * building a where clause based on the arguments, then doing a retrieve.
2089 static char *shflags[6] = { "service", "enable", "override", "success",
2090 "inprogress", "hosterror" };
2092 int qualified_get_serverhost(q, argv, cl, action, actarg)
2099 ## char sname[33], mname[33], qual[256];
2100 char *rargv[2], buf[32];
2103 sprintf(qual, "machine.mach_id = sh.mach_id and sh.service = \"%s\"",
2105 for (i = 1; i < q->argc; i++) {
2106 if (!strcmp(argv[i], "TRUE")) {
2107 sprintf(buf, " and sh.%s != 0", shflags[i]);
2109 } else if (!strcmp(argv[i], "FALSE")) {
2110 sprintf(buf, " and sh.%s = 0", shflags[i]);
2117 ## range of sh is serverhosts
2118 ## retrieve (sname = sh.service, mname = machine.name) where qual {
2119 (*action)(2, rargv, actarg);
2121 ## inquire_equel(rowcount = "rowcount")
2122 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
2123 ## where tblstats.#table = "serverhosts"
2125 return(SMS_NO_MATCH);
2126 return(SMS_SUCCESS);
2130 /* register_user - change user's login name and allocate a pobox, group,
2131 * filesystem, and quota for them. The user's status must start out as 0,
2132 * and is left as 2. Arguments are: user's UID, new login name, and user's
2133 * type for filesystem allocation (SMS_FS_STUDENT, SMS_FS_FACULTY,
2134 * SMS_FS_STAFF, SMS_FS_MISC).
2137 register_user(q, argv, cl)
2142 ## char *login, dir[65], *entity, *directory, machname[33];
2143 ## int who, rowcount, mid, uid, users_id, flag, utype, nid, list_id, quota;
2144 ## int size, alloc, pid, m_id;
2147 entity = cl->entity;
2150 uid = atoi(argv[0]);
2152 utype = atoi(argv[2]);
2154 ## range of u is users
2155 ## range of l is list
2156 ## range of sh is serverhosts
2157 ## range of n is nfsphys
2158 ## range of m is machine
2161 ## repeat retrieve (users_id = u.#users_id)
2162 ## where u.#uid = @uid and u.status = 0
2163 ## inquire_equel(rowcount = "rowcount");
2165 return(SMS_NO_MATCH);
2167 return(SMS_NOT_UNIQUE);
2169 /* check new login name */
2170 ## repeat retrieve (flag = any(u.#login where u.#login = @login))
2173 ## repeat retrieve (flag = any(l.name where l.name = @login))
2176 ## repeat retrieve (flag = any(filesys.#name where filesys.#name = @login))
2179 com_err(whoami, 0, "new login name OK");
2181 /* choose place for pobox, put in mid */
2182 ## repeat retrieve (mid = sh.mach_id, machname = m.name)
2183 ## where sh.service = "pop" and m.mach_id = sh.mach_id and
2184 ## sh.value2 - sh.value1 = max(sh.value2-sh.value1 where sh.service="pop")
2185 ## inquire_equel(rowcount = "rowcount");
2187 return(SMS_INTERNAL);
2189 /* change login name, set pobox */
2190 ## repeat replace u (#login = @login, status = 2, modtime = "now",
2191 ## modby = @who, modwith = @entity, potype="POP",
2192 ## pop_id = @mid, pmodtime="now", pmodby=@who,
2193 ## pmodwith=@entity)
2194 ## where u.#users_id = @users_id
2195 ## inquire_equel(rowcount = "rowcount");
2197 return(SMS_INTERNAL);
2198 set_pop_usage(mid, 1);
2199 com_err(whoami, 0, "set login name to %s and pobox to %s", login,
2202 /* create group list */
2203 if (set_next_object_id("gid", "list"))
2204 return(SMS_INTERNAL);
2205 if (set_next_object_id("list_id", "list"))
2206 return(SMS_INTERNAL);
2207 ## repeat retrieve (list_id = values.value) where values.name = "list_id"
2208 ## inquire_equel(rowcount = "rowcount");
2210 return(SMS_INTERNAL);
2211 ## repeat append list (name = @login, #list_id = @list_id, active = 1,
2212 ## public = 0, hidden = 0, maillist = 0, group = 1,
2213 ## #gid = values.value, desc = "User Group",
2214 ## acl_type = "USER", acl_id = @users_id, modtime = "now",
2215 ## modby = @who, modwith = @entity)
2216 ## where values.name = "gid"
2217 ## inquire_equel(rowcount = "rowcount");
2219 return(SMS_INTERNAL);
2220 com_err(whoami, 0, "group list created");
2222 /* decide where to put filesystem */
2225 ## repeat retrieve (mid = n.mach_id, dir = trim(n.#dir), nid = n.nfsphys_id,
2226 ## flag = n.status, size = n.#size, alloc = n.allocated) {
2227 if ((flag & utype) && (size != 0) && (size - alloc > maxsize)) {
2228 maxsize = size - alloc;
2231 directory = strsave(dir);
2237 return(SMS_INTERNAL);
2239 /* create filesystem */
2240 if (set_next_object_id("filsys_id", "filesys"))
2241 return(SMS_INTERNAL);
2242 ## repeat append filesys (filsys_id = values.value, phys_id = @pid,
2243 ## label = @login, type = "NFS", mach_id = @m_id,
2244 ## name = @directory + @login, mount = "/mit/" + @login,
2245 ## access = "w", comments = "User Locker",
2246 ## owner = @users_id, owners = @list_id, createflg = 1,
2247 ## lockertype = "HOMEDIR", modtime = "now",
2248 ## modby = @who, modwith = @entity)
2249 ## where values.name = "filsys_id"
2250 ## inquire_equel(rowcount = "rowcount");
2252 return(SMS_INTERNAL);
2253 com_err(whoami, 0, "filesys created on mach %d in %s/%s", m_id,
2254 trim(directory), login);
2257 ## repeat retrieve (quota = values.value) where values.name = "def_quota"
2258 ## inquire_equel(rowcount = "rowcount");
2260 return(SMS_INTERNAL);
2261 ## repeat append nfsquota (#users_id = @users_id, filsys_id = values.value,
2262 ## #quota = @quota, modtime = "now", modby = @who,
2263 ## modwith = @entity)
2264 ## where values.name = "filsys_id"
2265 ## inquire_equel(rowcount = "rowcount");
2267 return(SMS_INTERNAL);
2268 ## repeat replace nfsphys (allocated = nfsphys.allocated + @quota)
2269 ## where nfsphys.nfsphys_id = filesys.#phys_id and
2270 ## filesys.filsys_id = values.value and values.name = "filsys_id"
2271 ## inquire_equel(rowcount = "rowcount");
2273 return(SMS_INTERNAL);
2274 com_err(whoami, 0, "quota of %d assigned", quota);
2276 return(SMS_SUCCESS);
2281 /** set_pop_usage - incr/decr usage count for pop server in serverhosts talbe
2285 ** delta (will be +/- 1)
2288 ** - incr/decr value field in serverhosts table for pop/mach_id
2292 static int set_pop_usage(id, count)
2296 ## int mach_id = id;
2299 ## range of sh is serverhosts
2300 ## repeat replace sh (value1 = sh.value1 + @n)
2301 ## where sh.service = "pop" and sh.#mach_id = @mach_id
2303 return(SMS_SUCCESS);
2308 /* Validation Routines */
2310 validate_row(q, argv, v)
2311 register struct query *q;
2313 register struct validate *v;
2321 /* build where clause */
2322 build_qual(v->qual, v->argc, argv, qual);
2324 /* setup ingres variables */
2329 if (log_flags & LOG_RES)
2330 /* tell the logfile what we're doing */
2331 com_err(whoami, 0, "validating row: %s", qual);
2333 /* look for the record */
2334 ## range of rvar is table
2335 ## retrieve (rowcount = count(rvar.name where qual))
2336 if (rowcount == 0) return(SMS_NO_MATCH);
2337 if (rowcount > 1) return(SMS_NOT_UNIQUE);
2341 validate_fields(q, argv, vo, n)
2343 register char *argv[];
2344 register struct valobj *vo;
2347 register int status;
2352 if (log_flags & LOG_RES)
2353 com_err(whoami, 0, "validating %s in %s: %s",
2354 vo->namefield, vo->table, argv[vo->index]);
2355 status = validate_name(argv, vo);
2359 if (log_flags & LOG_RES)
2360 com_err(whoami, 0, "validating %s in %s: %s",
2361 vo->idfield, vo->table, argv[vo->index]);
2362 status = validate_id(argv, vo);
2366 if (log_flags & LOG_RES)
2367 com_err(whoami, 0, "validating date: %s", argv[vo->index]);
2368 status = validate_date(argv, vo);
2372 if (log_flags & LOG_RES)
2373 com_err(whoami, 0, "validating %s type: %s",
2374 vo->table, argv[vo->index]);
2375 status = validate_type(argv, vo);
2379 if (log_flags & LOG_RES)
2380 com_err(whoami, 0, "validating typed data (%s): %s",
2381 argv[vo->index - 1], argv[vo->index]);
2382 status = validate_typedata(q, argv, vo);
2386 if (log_flags & LOG_RES)
2387 com_err(whoami, 0, "validating rename %s in %s",
2388 argv[vo->index], vo->table);
2389 status = validate_rename(argv, vo);
2393 if (log_flags & LOG_RES)
2394 com_err(whoami, 0, "validating chars: %s", argv[vo->index]);
2395 status = validate_chars(argv[vo->index]);
2399 status = SMS_EXISTS;
2404 if (status != SMS_EXISTS) return(status);
2408 return(SMS_SUCCESS);
2412 /* validate_chars: verify that there are no illegal characters in
2413 * the string. Legal characters are printing chars other than
2416 static int illegalchars[] = {
2417 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
2418 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
2419 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
2420 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
2421 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ - O */
2422 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, /* P - _ */
2423 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
2424 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
2425 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2426 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2427 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2428 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2429 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2430 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2431 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2432 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2439 if (illegalchars[*s++])
2440 return(SMS_BAD_CHAR);
2445 validate_id(argv, vo)
2447 register struct valobj *vo;
2457 name = argv[vo->index];
2459 /* minor kludge to upcasify machine names */
2460 if (!strcmp(table, "machine"))
2461 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
2462 namefield = vo->namefield;
2463 idfield = vo->idfield;
2464 if (!strcmp(namefield, "uid")) {
2465 ## retrieve (id = table.idfield) where table.namefield = int4(name)
2466 ## inquire_equel (rowcount = "rowcount")
2468 ## retrieve (id = table.idfield) where table.namefield = name
2469 ## inquire_equel (rowcount = "rowcount")
2471 if (rowcount != 1) return(vo->error);
2472 *(int *)argv[vo->index] = id;
2476 validate_name(argv, vo)
2478 register struct valobj *vo;
2485 name = argv[vo->index];
2487 namefield = vo->namefield;
2488 ## retrieve (rowcount = countu(table.namefield
2489 ## where table.namefield = name))
2490 return ((rowcount == 1) ? SMS_EXISTS : vo->error);
2493 validate_date(argv, vo)
2501 idate = argv[vo->index];
2503 ## retrieve (dd = interval("years", date(idate) - date("today")))
2504 ## inquire_equel (errorno = "errorno")
2505 if (errorno != 0 || dd > 5.0) return(SMS_DATE);
2506 return(SMS_SUCCESS);
2510 validate_rename(argv, vo)
2514 ## char *name, *table, *namefield, *idfield;
2518 c = name = argv[vo->index];
2520 if (illegalchars[*c++])
2521 return(SMS_BAD_CHAR);
2523 /* minor kludge to upcasify machine names */
2524 if (!strcmp(table, "machine"))
2525 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
2526 namefield = vo->namefield;
2527 idfield = vo->idfield;
2530 if (!strcmp(argv[vo->index], argv[vo->index - 1]))
2532 ## retrieve (id = any(table.namefield where table.namefield = name))
2538 ## retrieve (id = table.idfield) where table.namefield = name
2539 if (id == -1 || id == *(int *)argv[vo->index - 1])
2546 validate_type(argv, vo)
2548 register struct valobj *vo;
2555 typename = vo->table;
2556 c = value = argv[vo->index];
2558 if (illegalchars[*c++])
2559 return(SMS_BAD_CHAR);
2561 /* uppercase type fields */
2562 for (c = value; *c; c++) if (islower(*c)) *c = toupper(*c);
2564 ## range of a is alias
2565 ## repeat retrieve (exists = any(a.trans where a.name = @typename and
2566 ## a.type = "TYPE" and
2567 ## a.trans = @value))
2568 return (exists ? SMS_EXISTS : vo->error);
2571 /* validate member or type-specific data field */
2573 validate_typedata(q, argv, vo)
2574 register struct query *q;
2575 register char *argv[];
2576 register struct valobj *vo;
2579 ## char *field_type;
2580 ## char data_type[129];
2586 /* get named object */
2587 name = argv[vo->index];
2589 /* get field type string (known to be at index-1) */
2590 field_type = argv[vo->index-1];
2592 /* get corresponding data type associated with field type name */
2593 ## repeat retrieve (data_type = alias.trans)
2594 ## where alias.#name = @field_type and alias.type = "TYPEDATA"
2595 ## inquire_equel (rowcount = "rowcount")
2596 if (rowcount != 1) return(SMS_TYPE);
2598 /* now retrieve the record id corresponding to the named object */
2599 if (index(data_type, ' '))
2600 *index(data_type, ' ') = 0;
2601 if (!strcmp(data_type, "user")) {
2603 ## repeat retrieve (id = users.users_id) where users.login = @name
2604 ## inquire_equel (rowcount = "rowcount")
2605 if (rowcount != 1) return(SMS_USER);
2607 } else if (!strcmp(data_type, "list")) {
2609 ## repeat retrieve (id = list.list_id) where list.#name = @name
2610 ## inquire_equel (rowcount = "rowcount")
2611 if (rowcount != 1) {
2612 /* if idfield is non-zero, then if argv[0] matches the string
2613 * that we're trying to resolve, we should get the value of
2614 * values.[idfield] for the id.
2616 if (vo->idfield && !strcmp(argv[0], argv[vo->index])) {
2618 ## repeat retrieve (id = values.value+1) where values.#name = @name
2619 ## inquire_equel(rowcount = "rowcount")
2620 if (rowcount != 1) return(SMS_LIST);
2624 } else if (!strcmp(data_type, "machine")) {
2626 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
2627 ## repeat retrieve (id = machine.mach_id) where machine.#name = @name
2628 ## inquire_equel (rowcount = "rowcount")
2629 if (rowcount != 1) return(SMS_MACHINE);
2631 } else if (!strcmp(data_type, "string")) {
2633 ## range of s is strings
2634 ## repeat retrieve (id = s.string_id) where s.string = @name
2635 ## inquire_equel (rowcount = "rowcount")
2636 if (rowcount == 0) {
2637 if (q->type != APPEND) return(SMS_STRING);
2638 ## range of v is values
2639 ## retrieve (id = v.value) where v.#name = "strings_id"
2641 ## replace v (value = id) where v.#name = "strings_id"
2642 ## append to strings (string_id = id, string = name)
2644 } else if (!strcmp(data_type, "none")) {
2650 /* now set value in argv */
2651 *(int *)argv[vo->index] = id;
2653 return (SMS_EXISTS);
2657 /* This looks up a login name and returns the SMS internal ID. It is used
2658 * by authenticate to put the users_id in the client structure.
2661 int get_users_id(name)
2664 ## int id, rowcount;
2669 ## range of u is users
2670 ## repeat retrieve (id = u.#users_id) where u.#login = @login
2671 ## inquire_equel (rowcount = "rowcount")
2680 /* Check the database at startup time. For now this just resets the
2681 * inprogress flags that the DCM uses.
2684 sanity_check_database()
2686 ## replace servers (inprogress = 0)
2687 ## replace serverhosts (inprogress = 0)