6 * Copyright (C) 1987 by the Massachusetts Institute of Technology
7 * For copying and distribution information, please see the file
13 static char *rcsid_qsupport_qc = "$Header$";
16 #include <mit-copyright.h>
18 #include "sms_server.h"
22 extern char *whoami, *strsave();
23 extern int ingres_errno, sms_errcode;
26 /* Specialized Access Routines */
28 /* access_user - verify that client name equals specified login name
30 * - since field validation routines are called first, a users_id is
31 * now in argv[0] instead of the login name.
34 access_user(q, argv, cl)
39 if (cl->users_id != *(int *)argv[0])
47 /* access_login - verify that client name equals specified login name
49 * argv[0...n] contain search info. q->
52 access_login(q, argv, cl)
60 build_qual(q->qual, q->argc, argv, qual);
61 ## retrieve (id = u.users_id) where qual
62 ## inquire_equel(rowcount = "rowcount")
63 if (rowcount != 1 || id != cl->users_id)
71 /* access_list - check access for most list operations
73 * Inputs: argv[0] - list_id
75 * argv[2] - member ID (only for queries "amtl" and "dmfl")
76 * argv[7] - group IID (only for query "ulis")
79 * - check that client is a member of the access control list
80 * - OR, if the query is add_member_to_list or delete_member_from_list
81 * and the list is public, allow access if client = member
84 access_list(q, argv, cl)
89 ## int list_id, acl_id, flags, rowcount, gid;
92 int client_id, status;
94 list_id = *(int *)argv[0];
95 ## repeat retrieve (acl_id = list.#acl_id, acl_type = list.#acl_type,
96 ## gid = list.#gid, flags = list.#public)
97 ## where list.#list_id = @list_id
98 ## inquire_equel(rowcount = "rowcount")
100 return(SMS_INTERNAL);
102 /* parse client structure */
103 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
106 /* if amtl or dmfl and list is public allow client to add or delete self */
107 if ((!strcmp("amtl", q->shortname) || !strcmp("dmfl", q->shortname)) &&
108 (flags && !strcmp("USER", argv[1]))) {
109 if (*(int *)argv[2] == client_id) return(SMS_SUCCESS);
110 /* if update_list, don't allow them to change the GID */
111 } else if (!strcmp("ulis", q->shortname)) {
112 if ((!strcmp(argv[7], UNIQUE_GID) && (gid != -1)) ||
113 (strcmp(argv[7], UNIQUE_GID) && (gid != atoi(argv[7]))))
117 /* check for client in access control list */
118 status = find_member(acl_type, acl_id, client_type, client_id, 0);
119 if (!status) return(SMS_PERM);
125 /* access_visible_list - allow access to list only if it is not hidden,
126 * or if the client is on the ACL
128 * Inputs: argv[0] - list_id
129 * cl - client identifier
132 access_visible_list(q, argv, cl)
137 ## int list_id, acl_id, flags, rowcount;
140 int client_id, status;
142 list_id = *(int *)argv[0];
143 ## repeat retrieve (flags = list.hidden, acl_id = list.#acl_id,
144 ## acl_type = list.#acl_type) where list.#list_id = @list_id
145 ## inquire_equel(rowcount = "rowcount")
147 return(SMS_INTERNAL);
151 /* parse client structure */
152 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
155 /* check for client in access control list */
156 status = find_member(acl_type, acl_id, client_type, client_id, 0);
164 /* access_vis_list_by_name - allow access to list only if it is not hidden,
165 * or if the client is on the ACL
167 * Inputs: argv[0] - list name
168 * cl - client identifier
171 access_vis_list_by_name(q, argv, cl)
176 ## int acl_id, flags, rowcount;
177 ## char acl_type[9], *listname;
179 int client_id, status;
182 ## repeat retrieve (flags = list.hidden, acl_id = list.#acl_id,
183 ## acl_type = list.#acl_type) where list.#name = @listname
184 ## inquire_equel(rowcount = "rowcount");
186 return(SMS_WILDCARD);
188 return(SMS_NO_MATCH);
192 /* parse client structure */
193 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
196 /* check for client in access control list */
197 status = find_member(acl_type, acl_id, client_type, client_id, 0);
205 /* access_member - allow user to access member of type "USER" and name matches
206 * username, or to access member of type "LIST" and list is one that user is
207 * on the acl of, or the list is visible.
210 access_member(q, argv, cl)
215 if (!strcmp(argv[0], "LIST") || !strcmp(argv[0], "RLIST"))
216 return(access_visible_list(q, &argv[1], cl));
218 if (!strcmp(argv[0], "USER") || !strcmp(argv[0], "RUSER")) {
219 if (cl->users_id == *(int *)argv[1])
227 /* access_qgli - special access routine for Qualified_get_lists. Allows
228 * access iff argv[0] == "TRUE" and argv[2] == "FALSE".
231 access_qgli(q, argv, cl)
236 if (!strcmp(argv[0], "TRUE") && !strcmp(argv[2], "FALSE"))
242 /* access_service - allow access if user is on ACL of service. Don't
243 * allow access if a wildcard is used.
246 access_service(q, argv, cl)
251 ## int acl_id, rowcount;
252 ## char *name, acl_type[9];
253 int client_id, status;
257 ## repeat retrieve (acl_id = servers.#acl_id, acl_type = servers.#acl_type)
258 ## where servers.#name = uppercase(@name)
259 ## inquire_equel(rowcount = "rowcount")
263 /* parse client structure */
264 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
267 /* check for client in access control list */
268 status = find_member(acl_type, acl_id, client_type, client_id, 0);
269 if (!status) return(SMS_PERM);
276 /* access_filesys - verify that client is owner or on owners list of filesystem
280 access_filesys(q, argv, cl)
285 ## int rowcount, users_id, list_id;
287 int status, client_id;
291 ## repeat retrieve (users_id = filesys.owner, list_id = filesys.owners)
292 ## where filesys.label = @name
293 ## inquire_equel(rowcount = "rowcount")
297 if (users_id == cl->users_id)
299 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
301 status = find_member("LIST", list_id, client_type, client_id, 0);
311 /* Setup routine for add_user
313 * Inputs: argv[0] - login
318 * - if argv[1] == UNIQUE_UID then set argv[1] = next(uid)
319 * - if argv[0] == UNIQUE_LOGIN then set argv[0] = "#<uid>"
322 setup_ausr(q, argv, cl)
324 register char *argv[];
327 ## int nuid, rowcount;
329 if (!strcmp(argv[1], UNIQUE_UID) || atoi(argv[1]) == -1) {
330 if (set_next_object_id("uid", "users"))
331 return(SMS_INGRES_ERR);
332 ## repeat retrieve (nuid = values.value) where values.name = "uid"
333 ## inquire_equel(rowcount = "rowcount")
335 return(SMS_INTERNAL);
336 sprintf(argv[1], "%d", nuid);
339 if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[1]) == -1) {
340 sprintf(argv[0], "#%s", argv[1]);
347 /* setup_dusr - verify that the user is no longer being referenced
348 * and may safely be deleted.
351 int setup_dusr(q, argv)
357 id = *(int *)argv[0];
359 /* For now, only allow users to be deleted if their status is 0 */
360 ## repeat retrieve (flag = u.status) where u.users_id = @id
364 ## repeat delete nfsquota where nfsquota.users_id = @id
365 ## repeat retrieve (flag = any(members.member_id where members.member_id=@id
366 ## and members.member_type = "USER"))
369 ## repeat retrieve (flag = any(filesys.label where filesys.owner=@id))
372 ## repeat retrieve (flag = any(list.name where list.acl_id=@id and
373 ## list.acl_type = "USER"))
376 ## repeat retrieve (flag = any(servers.name where servers.acl_id=@id and
377 ## servers.acl_type = "USER"))
380 ## repeat retrieve (flag=any(hostaccess.acl_id where hostaccess.acl_id=@id and
381 ## hostaccess.acl_type = "USER"))
389 /* setup_spop: verify that there is already a valid POP machine_id in the
390 * pop_id field. Also take care of keeping track of the post office usage.
392 int setup_spop(q, argv)
396 ## int id, mid, flag;
399 id = *(int *)argv[0];
400 ## repeat retrieve (type = u.potype, mid = u.pop_id,
401 ## flag = any(machine.name where machine.mach_id = u.pop_id
402 ## and u.pop_id != 0 and u.users_id = @id))
403 ## where u.users_id = @id
406 if (strcmp(strtrim(type), "POP"))
407 set_pop_usage(mid, 1);
412 /* setup_dpob: Take care of keeping track of the post office usage.
414 int setup_dpob(q, argv)
421 user = *(int *)argv[0];
422 ## repeat retrieve (type = u.potype, id = u.pop_id)
423 ## where u.users_id = @user
425 if (!strcmp(strtrim(type), "POP"))
426 set_pop_usage(id, -1);
431 /* setup_dmac - verify that the machine is no longer being referenced
432 * and may safely be deleted.
435 int setup_dmac(q, argv)
441 id = *(int *)argv[0];
442 ## repeat retrieve (flag = any(users.login where users.potype = "POP"
443 ## and users.pop_id=@id))
446 ## repeat retrieve (flag = any(serverhosts.mach_id
447 ## where serverhosts.mach_id=@id))
450 ## repeat retrieve (flag = any(nfsphys.mach_id where nfsphys.mach_id=@id))
453 ## repeat retrieve (flag = any(hostaccess.mach_id where hostaccess.mach_id=@id))
456 ## repeat retrieve (flag = any(printcap.mach_id where printcap.mach_id=@id))
460 ## repeat delete mcmap where mcmap.mach_id = @id
465 /* setup_dclu - verify that the cluster is no longer being referenced
466 * and may safely be deleted.
469 int setup_dclu(q, argv)
475 id = *(int *)argv[0];
476 ## repeat retrieve (flag = any(mcmap.mach_id where mcmap.clu_id=@id))
479 ## repeat retrieve (flag = any(svc.clu_id where svc.clu_id=@id))
487 /* setup_alis - if argv[5] is non-zero and argv[6] is UNIQUE_ID, then allocate
488 * a new gid and put it in argv[6]. Otherwise if argv[6] is UNIQUE_ID but
489 * argv[5] is not, then remember that UNIQUE_ID is being stored by putting
490 * a -1 there. Remember that this is also used for ulis, with the indexes
494 int setup_alis(q, argv)
502 if (!strcmp(q->shortname, "alis"))
504 else if (!strcmp(q->shortname, "ulis"))
507 if (!strcmp(argv[idx], UNIQUE_GID) || atoi(argv[idx]) == -1) {
508 if (atoi(argv[idx - 1])) {
509 if (set_next_object_id("gid", "list"))
510 return(SMS_INGRES_ERR);
511 ## repeat retrieve (ngid = values.value) where values.name = "gid"
512 sprintf(argv[idx], "%d", ngid);
514 strcpy(argv[idx], "-1");
522 /* setup_dlist - verify that the list is no longer being referenced
523 * and may safely be deleted.
526 int setup_dlis(q, argv)
532 id = *(int *)argv[0];
533 ## repeat retrieve (flag = any(members.member_id where members.member_id=@id
534 ## and members.member_type = "LIST"))
537 ## repeat retrieve (flag = any(members.member_id where members.list_id=@id))
540 ## repeat retrieve (flag = any(filesys.label where filesys.owners=@id))
543 ## repeat retrieve (flag = any(capacls.tag where capacls.list_id=@id))
546 ## repeat retrieve (flag = any(list.name where list.acl_id=@id and
547 ## list.acl_type = "LIST" and list.list_id != @id))
550 ## repeat retrieve (flag = any(servers.name where servers.acl_id=@id and
551 ## servers.acl_type = "LIST"))
554 ## repeat retrieve (flag=any(hostaccess.acl_id where hostaccess.acl_id=@id and
555 ## hostaccess.acl_type = "LIST"))
558 ## repeat retrieve (flag = any(zephyr.class
559 ## where zephyr.xmt_type = "LIST" and zephyr.xmt_id = @id or
560 ## zephyr.sub_type = "LIST" and zephyr.sub_id = @id or
561 ## zephyr.iws_type = "LIST" and zephyr.iws_id = @id or
562 ## zephyr.iui_type = "LIST" and zephyr.iui_id = @id))
570 /* setup_dsin - verify that the service is no longer being referenced
571 * and may safely be deleted.
574 int setup_dsin(q, argv)
582 ## repeat retrieve (flag = any(serverhosts.service
583 ## where serverhosts.service=uppercase(@name)))
586 ## repeat retrieve (flag = servers.inprogress) where servers.#name = @name
594 /* setup_dshi - verify that the service-host is no longer being referenced
595 * and may safely be deleted.
598 int setup_dshi(q, argv)
606 id = *(int *)argv[1];
607 ## repeat retrieve (flag=serverhosts.inprogress)
608 ## where serverhosts.service=uppercase(@name) and serverhosts.mach_id=@id
617 ** setup_add_filesys - verify existance of referenced file systems
629 ** * extract directory prefix from name
630 ** * verify mach_id/dir in nfsphys
631 ** * verify access in {r, w, R, W}
633 ** Side effect: sets variable var_phys_id to the ID of the physical
634 ** filesystem (nfsphys_id for NFS, 0 for RVD)
637 ** SMS_NFS - specified directory not exported
638 ** SMS_FILESYS_ACCESS - invalid filesys access
642 ##static int var_phys_id;
654 mach_id = *(int *)argv[2];
659 if (!strcmp(type, "NFS"))
660 return (check_nfs(mach_id, name, access));
666 /* Verify the arguments, depending on the FStype. Also, if this is an
667 * NFS filesystem, then update any quotas for that filesystem to reflect
676 char *type, *name, *access;
680 mach_id = *(int *)argv[3];
685 if (!strcmp(type, "NFS")) {
686 status = check_nfs(mach_id, name, access);
687 fid = *(int *)argv[0];
688 ## replace nfsquota (phys_id = var_phys_id) where nfsquota.filsys_id = fid
695 /* Find the NFS physical partition that the named directory is on.
696 * This is done by comparing the dir against the mount point of the
697 * partition. To make sure we get the correct match when there is
698 * more than one, we sort the query in reverse order by dir name.
701 ##check_nfs(mach_id, name, access)
712 caccess = (isupper(*access)) ? tolower(*access) : *access;
713 if (caccess != 'r' && caccess != 'w') return(SMS_FILESYS_ACCESS);
716 ## range of np is nfsphys
717 ## repeat retrieve (var_phys_id = np.#nfsphys_id, dir = trim(np.#dir))
718 ## where np.#mach_id = @mach_id sort by #dir:d {
722 if (*cp1++ != *cp2) break;
726 status = SMS_SUCCESS;
735 /* setup_dfil: free any quota records and fsgroup info associated with
736 * a filesystem when it is deleted. Also adjust the allocation numbers.
739 setup_dfil(q, argv, cl)
746 id = *(int *)argv[0];
747 ## range of q is nfsquota
748 ## range of fs is filesys
749 ## range of n is nfsphys
750 ## repeat replace n (allocated=n.allocated-sum(q.quota where q.filsys_id=@id))
751 ## where n.nfsphys_id = fs.phys_id and fs.filsys_id = @id
753 ## repeat delete q where q.filsys_id = @id
754 ## repeat delete fsgroup where fsgroup.filsys_id = @id
755 ## repeat delete fsgroup where fsgroup.group_id = @id
760 /* setup_dnfp: check to see that the nfs physical partition does not have
761 * any filesystems assigned to it before allowing it to be deleted.
764 setup_dnfp(q, argv, cl)
771 id = *(int *)argv[0];
772 ## repeat retrieve (exists = any(filesys.label where filesys.phys_id = @id))
779 /* setup_dnfq: Remove allocation from nfsphys before deleting quota.
780 * argv[0] = filsys_id
784 setup_dnfq(q, argv, cl)
789 ## int quota, fs, user;
791 fs = *(int *)argv[0];
792 user = *(int *)argv[1];
794 ## range of q is nfsquota
795 ## repeat retrieve (quota = q.#quota) where q.users_id = @user and
797 ## repeat replace nfsphys (allocated = nfsphys.allocated - @quota)
798 ## where nfsphys.nfsphys_id = filesys.#phys_id and filesys.filsys_id = @fs
803 /* setup_sshi: don't exclusive lock the machine table during
804 * set_server_host_internal.
807 setup_sshi(q, argv, cl)
812 ## set lockmode session where readlock = system
817 /* FOLLOWUP ROUTINES */
819 /* generic set_modtime routine. This takes the table name from the query,
820 * and will update the modtime, modby, and modwho fields in the entry in
821 * the table whose name field matches argv[0].
824 set_modtime(q, argv, cl)
829 ## char *name, *entity, *table;
837 ## replace table (modtime = "now", modby = who, modwith = entity)
838 ## where table.#name = name
842 /* generic set_modtime_by_id routine. This takes the table name from
843 * the query, and the id name from the validate record,
844 * and will update the modtime, modby, and modwho fields in the entry in
845 * the table whose id matches argv[0].
848 set_modtime_by_id(q, argv, cl)
853 ## char *entity, *table, *id_name;
859 id_name = q->validate->object_id;
861 id = *(int *)argv[0];
862 ## replace table (modtime = "now", modby = who, modwith = entity)
863 ## where table.id_name = id
868 /* Sets the finger modtime on a user record. The users_id will be in argv[0].
871 set_finger_modtime(q, argv, cl)
876 ## int users_id, who;
881 users_id = *(int *)argv[0];
883 ## repeat replace u (fmodtime = "now", fmodby = @who, fmodwith = @entity)
884 ## where u.#users_id = @users_id
889 /* Sets the pobox modtime on a user record. The users_id will be in argv[0].
892 set_pobox_modtime(q, argv, cl)
897 ## int users_id, who;
902 users_id = *(int *)argv[0];
904 ## repeat replace users (pmodtime = "now", pmodby = @who, pmodwith = @entity)
905 ## where users.#users_id = @users_id
910 /* Like set_modtime, but uppercases the name first.
913 set_uppercase_modtime(q, argv, cl)
918 ## char *name, *entity, *table;
926 ## replace table (modtime = "now", modby = who, modwith = entity)
927 ## where table.#name = uppercase(name)
932 /* Sets the modtime on the machine whose mach_id is in argv[0]. This routine
933 * is necessary for add_machine_to_cluster becuase the table that query
934 * operates on is "mcm", not "machine".
937 set_mach_modtime_by_id(q, argv, cl)
948 id = *(int *)argv[0];
949 ## range of m is machine
950 ## repeat replace m (modtime = "now", modby = @who, modwith = @entity)
951 ## where m.mach_id = @id
956 /* Sets the modtime on the cluster whose mach_id is in argv[0]. This routine
957 * is necessary for add_cluster_data and delete_cluster_data becuase the
958 * table that query operates on is "svc", not "cluster".
961 set_cluster_modtime_by_id(q, argv, cl)
972 id = *(int *)argv[0];
973 ## range of c is cluster
974 ## repeat replace c (modtime = "now", modby = @who, modwith = @entity)
975 ## where c.clu_id = @id
980 /* sets the modtime on the serverhost where the service name is in argv[0]
981 * and the mach_id is in argv[1].
984 set_serverhost_modtime(q, argv, cl)
989 ## char *entity, *serv;
996 id = *(int *)argv[1];
997 ## repeat replace sh (modtime = "now", modby = @who, modwith = @entity)
998 ## where sh.service = uppercase(@serv) and sh.mach_id = @id
1003 /* sets the modtime on the nfsphys where the mach_id is in argv[0] and the
1004 * directory name is in argv[1].
1007 set_nfsphys_modtime(q, argv, cl)
1012 ## char *entity, *dir;
1015 entity = cl->entity;
1018 id = *(int *)argv[0];
1020 ## repeat replace np (modtime = "now", modby = @who, modwith = @entity)
1021 ## where np.#dir = @dir and np.mach_id = @id
1022 return(SMS_SUCCESS);
1026 /* sets the modtime on a filesystem, where argv[0] contains the filesys
1030 set_filesys_modtime(q, argv, cl)
1035 ## char *label, *entity;
1038 entity = cl->entity;
1042 if (!strcmp(q->shortname, "ufil"))
1045 ## repeat replace fs (modtime = "now", modby = @who, modwith = @entity,
1046 ## #phys_id = @var_phys_id) where fs.#label = @label
1047 return(SMS_SUCCESS);
1051 /* sets the modtime on a zephyr class, where argv[0] contains the class
1055 set_zephyr_modtime(q, argv, cl)
1060 ## char *class, *entity;
1063 entity = cl->entity;
1068 ## repeat replace z (modtime = "now", modby = @who, modwith = @entity)
1069 ## where z.#class = @class
1070 return(SMS_SUCCESS);
1074 /* fixes the modby field. This will be the second to last thing in the
1075 * argv, the argv length is determined from the query structure. It is
1076 * passed as a pointer to an integer. This will either turn it into a
1077 * username, or # + the users_id.
1079 followup_fix_modby(q, sq, v, action, actarg, cl)
1081 register struct save_queue *sq;
1083 register int (*action)();
1084 register int actarg;
1088 char **argv, *malloc();
1089 ## int id, rowcount;
1093 while (sq_get_data(sq, &argv)) {
1096 argv[i] = malloc(9);
1098 ## repeat retrieve (name = users.login) where users.users_id = @id
1099 ## inquire_equel(rowcount = "rowcount")
1100 if (rowcount != 1) {
1101 sprintf(argv[i], "#%d", id);
1103 (*action)(q->vcnt, argv, actarg);
1104 for (j = 0; j < q->vcnt; j++)
1109 return(SMS_SUCCESS);
1114 ** followup_ausr - add finger and pobox entries, set_user_modtime
1117 ** argv[0] - login (add_user)
1118 ** argv[3] - last name
1119 ** argv[4] - first name
1120 ** argv[5] - middle name
1124 followup_ausr(q, argv, cl)
1130 ## char *login, *entity;
1131 ## char fullname[129];
1135 entity = cl->entity;
1137 /* build fullname */
1138 if (strlen(argv[4]) && strlen(argv[5]))
1139 sprintf(fullname, "%s %s %s", argv[4], argv[5], argv[3]);
1140 else if (strlen(argv[4]))
1141 sprintf(fullname, "%s %s", argv[4], argv[3]);
1143 sprintf(fullname, "%s", argv[3]);
1145 /* create finger entry, pobox & set modtime on user */
1146 ## repeat replace u (modtime = "now", modby=@who, modwith=@entity,
1147 ## #fullname=@fullname, mit_affil = u.mit_year,
1148 ## fmodtime="now", fmodby=@who, fmodwith=@entity,
1149 ## potype="NONE", pmodtime="now", pmodby=@who, pmodwith=@entity)
1150 ## where u.#login = @login
1152 return(SMS_SUCCESS);
1156 /* followup_gpob: fixes argv[2] based on the IDs currently there and the
1157 * type in argv[1]. Then completes the upcall to the user.
1159 * argv[2] is of the form "123:234" where the first integer is the machine
1160 * ID if it is a pop box, and the second is the string ID if it is an SMTP
1161 * box. argv[1] should be "POP", "SMTP", or "NONE". Boxes of type NONE
1165 followup_gpob(q, sq, v, action, actarg, cl)
1166 register struct query *q;
1167 register struct save_queue *sq;
1168 register struct validate *v;
1169 register int (*action)();
1173 char **argv, *index();
1175 ## char box[129], *name;
1176 ## int mid, sid, rowcount;
1179 while (sq_get_data(sq, &argv)) {
1180 sms_trim_args(2, argv);
1182 p = index(argv[2], ':');
1184 mid = atoi(argv[2]);
1188 if (!strcmp(ptype, "POP")) {
1189 ## repeat retrieve (box=machine.#name) where machine.mach_id=@mid
1190 ## inquire_equel(rowcount = "rowcount")
1192 return(SMS_MACHINE);
1193 } else if (!strcmp(ptype, "SMTP")) {
1194 ## repeat retrieve (box=strings.string) where strings.string_id=@sid
1195 ## inquire_equel(rowcount = "rowcount")
1198 } else /* ptype == "NONE" */ {
1202 if (!strcmp(q->shortname, "gpob")) {
1203 sid = atoi(argv[4]);
1205 argv[4] = malloc(9);
1207 ## repeat retrieve (name = users.login) where users.users_id = @sid
1208 ## inquire_equel(rowcount = "rowcount")
1210 sprintf(name, "#%d", sid);
1214 (*action)(q->vcnt, argv, actarg);
1216 /* free saved data */
1223 return (SMS_SUCCESS);
1227 /* followup_glin: fix the ace_name in argv[8]. argv[7] will contain the
1228 * ace_type: "LIST", "USER", or "NONE". Decode the id in argv[8] into the
1229 * proper name based on the type, and repace that string in the argv.
1230 * Also fixes the modby field by called followup_fix_modby.
1233 followup_glin(q, sq, v, action, actarg, cl)
1234 register struct query *q;
1235 register struct save_queue *sq;
1236 register struct validate *v;
1237 register int (*action)();
1241 char **argv, *malloc(), *realloc(), *type;
1243 ## int id, rowcount;
1247 if (!strcmp(q->shortname, "gsin"))
1250 while (sq_get_data(sq, &argv)) {
1251 sms_trim_args(q->vcnt, argv);
1253 id = atoi(argv[i = q->vcnt - 2]);
1255 name = argv[i] = malloc(9);
1256 ## repeat retrieve (name = users.login) where users.users_id = @id
1257 ## inquire_equel(rowcount = "rowcount")
1259 sprintf(argv[i], "#%d", id);
1261 id = atoi(argv[idx]);
1262 type = argv[idx - 1];
1263 if ((name = malloc(33)) == NULL)
1266 if (!strcmp(type, "LIST")) {
1267 ## repeat retrieve (name = list.#name) where list.list_id = @id
1268 ## inquire_equel(rowcount = "rowcount")
1270 strcpy(name, "???");
1271 } else if (!strcmp(type, "USER")) {
1272 ## repeat retrieve (name = users.login) where users.users_id = @id
1273 ## inquire_equel(rowcount = "rowcount")
1275 strcpy(name, "???");
1276 } else if (!strcmp(type, "KERBEROS")) {
1277 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1278 ## inquire_equel(rowcount = "rowcount")
1280 strcpy(name, "???");
1281 } else if (!strcmp(type, "NONE")) {
1282 strcpy(name, "NONE");
1284 strcpy(name, "???");
1288 if (!strcmp(q->shortname, "glin") && atoi(argv[6]) == -1) {
1289 argv[6] = realloc(argv[6], strlen(UNIQUE_GID) + 1);
1290 strcpy(argv[6], UNIQUE_GID);
1294 (*action)(q->vcnt, argv, actarg);
1296 /* free saved data */
1297 for (i = 0; i < q->vcnt; i++)
1303 return (SMS_SUCCESS);
1307 /** followup_amtl - followup for amtl and dmfl; when adding a list
1308 ** member to a maillist, make member list a maillist also
1309 ** unless list is a user-group.
1310 ** Then set_list_modtime_by_id.
1313 ** argv[0] - list_id
1314 ** argv[1] - member_type
1315 ** argv[2] - member_id
1319 followup_amtl(q, argv, cl)
1329 list_id = *(int *)argv[0];
1330 entity = cl->entity;
1333 ## range of l is list
1334 ## repeat replace l (modtime = "now", modby = @who, modwith = @entity)
1335 ## where l.#list_id = @list_id
1337 /* if query is not amtl or if member_type is not LIST then return */
1338 if (bcmp(q->shortname, "amtl", 4) || bcmp(argv[1], "LIST", 4))
1339 return(SMS_SUCCESS);
1341 member_id = *(int *)argv[2];
1343 /* is parent list a mailing list? */
1344 ## repeat retrieve (exists = l.maillist) where l.#list_id=@list_id
1346 return(SMS_SUCCESS);
1348 /* list is not a user-group; add list to maillist table */
1349 ## repeat replace l (maillist = 1) where l.#list_id = @member_id
1350 return(SMS_SUCCESS);
1354 /* followup_anfq: Add allocation to nfsphys after creating quota.
1355 * argv[0] = filsys_id
1356 * argv[2] = ascii(quota)
1359 followup_anfq(q, argv, cl)
1364 ## int quota, user, fs, who;
1367 fs = *(int *)argv[0];
1368 user = *(int *)argv[1];
1369 quota = atoi(argv[2]);
1371 entity = cl->entity;
1373 ## repeat replace nq (modtime = "now", modby = @who, modwith = @entity)
1374 ## where nq.filsys_id = @fs and nq.users_id = @user
1375 ## repeat replace nfsphys (allocated = nfsphys.allocated + @quota)
1376 ## where nfsphys.nfsphys_id = filesys.#phys_id and filesys.filsys_id = @fs
1377 return(SMS_SUCCESS);
1384 followup_gzcl(q, sq, v, action, actarg, cl)
1385 register struct query *q;
1386 register struct save_queue *sq;
1387 register struct validate *v;
1388 register int (*action)();
1393 ## int rowcount, id;
1397 while (sq_get_data(sq, &argv)) {
1398 sms_trim_args(q->vcnt, argv);
1400 id = atoi(argv[i = q->vcnt - 2]);
1402 name = argv[i] = malloc(9);
1403 ## repeat retrieve (name = users.login) where users.users_id = @id
1404 ## inquire_equel(rowcount = "rowcount")
1406 sprintf(argv[i], "#%d", id);
1408 for (i = 1; i < 8; i+=2) {
1409 id = atoi(argv[i+1]);
1411 if ((name = argv[i+1] = malloc(33)) == NULL)
1413 if (!strcmp(argv[i], "LIST")) {
1414 ## repeat retrieve (name = list.#name) where list.list_id = @id
1415 ## inquire_equel(rowcount = "rowcount")
1417 strcpy(name, "???");
1418 } else if (!strcmp(argv[i], "USER")) {
1419 ## repeat retrieve (name = users.login) where users.users_id = @id
1420 ## inquire_equel(rowcount = "rowcount")
1422 strcpy(name, "???");
1423 } else if (!strcmp(argv[i], "KERBEROS")) {
1424 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1425 ## inquire_equel(rowcount = "rowcount")
1427 strcpy(name, "???");
1428 } else if (!strcmp(argv[i], "NONE")) {
1429 strcpy(name, "NONE");
1431 strcpy(name, "???");
1436 (*action)(q->vcnt, argv, actarg);
1438 /* free saved data */
1439 for (i = 0; i < q->vcnt; i++)
1444 return(SMS_SUCCESS);
1451 followup_gsha(q, sq, v, action, actarg, cl)
1452 register struct query *q;
1453 register struct save_queue *sq;
1454 register struct validate *v;
1455 register int (*action)();
1460 ## int rowcount, id;
1464 while (sq_get_data(sq, &argv)) {
1465 sms_trim_args(q->vcnt, argv);
1469 name = argv[4] = malloc(9);
1470 ## repeat retrieve (name = users.login) where users.users_id = @id
1471 ## inquire_equel(rowcount = "rowcount")
1473 sprintf(argv[4], "#%d", id);
1477 if ((name = argv[2] = malloc(33)) == NULL)
1479 if (!strcmp(argv[1], "LIST")) {
1480 ## repeat retrieve (name = list.#name) where list.list_id = @id
1481 ## inquire_equel(rowcount = "rowcount")
1483 strcpy(name, "???");
1484 } else if (!strcmp(argv[1], "USER")) {
1485 ## repeat retrieve (name = users.login) where users.users_id = @id
1486 ## inquire_equel(rowcount = "rowcount")
1488 strcpy(name, "???");
1489 } else if (!strcmp(argv[1], "KERBEROS")) {
1490 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1491 ## inquire_equel(rowcount = "rowcount")
1493 strcpy(name, "???");
1494 } else if (!strcmp(argv[1], "NONE")) {
1495 strcpy(name, "NONE");
1497 strcpy(name, "???");
1501 (*action)(q->vcnt, argv, actarg);
1503 /* free saved data */
1504 for (i = 0; i < q->vcnt; i++)
1509 return(SMS_SUCCESS);
1514 /* Special query routines */
1516 /* set_pobox - this does all of the real work.
1517 * argv = user_id, type, box
1518 * if type is POP, then box should be a machine, and its ID should be put in
1519 * pop_id. If type is SMTP, then box should be a string and its ID should
1520 * be put in box_id. If type is NONE, then box doesn't matter.
1523 int set_pobox(q, argv, cl)
1528 ## int user, id, rowcount;
1529 ## char *box, potype[9];
1532 user = *(int *)argv[0];
1534 ## repeat retrieve (id = users.pop_id, potype = users.#potype)
1535 ## where users.users_id = @user
1536 if (!strcmp(strtrim(potype), "POP"))
1537 set_pop_usage(id, -1);
1539 if (!strcmp(argv[1], "POP")) {
1540 ## repeat retrieve (id=machine.mach_id) where machine.name=uppercase(@box)
1541 ## inquire_equel(rowcount = "rowcount")
1543 return(SMS_MACHINE);
1544 ## repeat replace users (#potype = "POP", pop_id = @id)
1545 ## where users.users_id = @user
1546 set_pop_usage(id, 1);
1547 } else if (!strcmp(argv[1], "SMTP")) {
1548 ## range of s is strings
1549 ## repeat retrieve (id = s.string_id) where s.string = @box
1550 ## inquire_equel (rowcount = "rowcount")
1551 if (rowcount == 0) {
1552 ## range of v is values
1553 ## repeat retrieve (id = v.value) where v.name = "strings_id"
1555 ## repeat replace v (value = @id) where v.name = "strings_id"
1556 ## append to strings (string_id = id, string = box)
1558 ## repeat replace users (#potype = "SMTP", box_id = @id)
1559 ## where users.users_id = @user
1560 } else /* argv[1] == "NONE" */ {
1561 ## repeat replace users (#potype = "NONE") where users.users_id = @user
1564 set_pobox_modtime(q, argv, cl);
1565 ## repeat replace tblstats (updates = tblstats.updates + 1, modtime = "now")
1566 ## where tblstats.#table = "users"
1567 return(SMS_SUCCESS);
1571 /* get_list_info: passed a wildcard list name, returns lots of stuff about
1572 * each list. This is tricky: first build a queue of all requested
1573 * data. Rest of processing consists of fixing gid, ace_name, and modby.
1576 get_list_info(q, aargv, cl, action, actarg)
1577 register struct query *q;
1580 register int (*action)();
1583 char *argv[13], *malloc(), *realloc();
1584 ## char *name, acl_type[9], listname[33], active[5], public[5], hidden[5];
1585 ## char maillist[5], group[5], gid[6], acl_name[33], desc[256], modtime[27];
1586 ## char modby[9], modwith[9];
1587 ## int id, rowcount, acl_id, hid, modby_id;
1589 struct save_queue *sq, *sq_create();
1591 returned = rowcount = 0;
1595 ## range of l is list
1596 ## repeat retrieve (id = l.list_id) where l.#name = @name {
1597 sq_save_data(sq, id);
1601 return(SMS_NO_MATCH);
1603 argv[0] = listname; argv[1] = active; argv[2] = public; argv[3] = hidden;
1604 argv[4] = maillist; argv[5] = group; argv[6] = gid; argv[7] = acl_type;
1605 argv[8] = acl_name; argv[9] = desc; argv[10] = modtime; argv[11] = modby;
1608 while (sq_get_data(sq, &id)) {
1612 ## repeat retrieve (listname = l.#name, active = text(l.#active),
1613 ## public = text(l.#public), hidden = text(l.#hidden),
1614 ## hid = l.#hidden, maillist = text(l.#maillist),
1615 ## group = text(l.#group), gid = text(l.#gid),
1616 ## acl_type = trim(l.#acl_type), acl_id = l.#acl_id,
1617 ## desc = l.#desc, modtime = l.#modtime, modby_id = l.#modby,
1618 ## modwith =l.#modwith)
1619 ## where l.list_id = @id
1621 if (atoi(gid) == -1)
1622 argv[6] = UNIQUE_GID;
1624 if (!strcmp(acl_type, "LIST")) {
1625 ## repeat retrieve (acl_name = l.#name) where l.list_id = @acl_id
1626 ## inquire_equel(rowcount = "rowcount")
1628 strcpy(acl_name, "???");
1629 } else if (!strcmp(acl_type, "USER")) {
1630 ## repeat retrieve (acl_name = users.#login)
1631 ## where users.users_id = @acl_id
1632 ## inquire_equel(rowcount = "rowcount")
1634 strcpy(acl_name, "???");
1635 } else if (!strcmp(acl_type, "KERBEROS")) {
1636 ## repeat retrieve (acl_name = strings.string)
1637 ## where strings.string_id = @acl_id
1638 ## inquire_equel(rowcount = "rowcount")
1640 strcpy(acl_name, "???");
1641 } else if (!strcmp(acl_type, "NONE")) {
1642 strcpy(acl_name, "NONE");
1644 strcpy(acl_name, "???");
1646 ## repeat retrieve (modby = users.login) where users.users_id = @modby_id
1647 ## inquire_equel(rowcount = "rowcount")
1649 sprintf(modby, "#%d", id);
1651 sms_trim_args(q->vcnt, argv);
1653 (*action)(q->vcnt, argv, actarg);
1657 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
1658 ## where tblstats.#table = "list"
1660 return (SMS_SUCCESS);
1664 /* get_ace_use - given a type and a name, return a type and a name.
1665 * The ace_type is one of "LIST", "USER", "RLIST", or "RUSER" in argv[0],
1666 * and argv[1] will contain the ID of the entity in question. The R*
1667 * types mean to recursively look at every containing list, not just
1668 * when the object in question is a direct member. On return, the
1669 * usage type will be one of LIST, SERVICE, FILESYS, QUOTA, QUERY, or ZEPHYR.
1672 int get_ace_use(q, argv, cl, action, actarg)
1681 ## int aid, listid, id;
1682 struct save_queue *sq, *sq_create();
1685 aid = *(int *)argv[1];
1686 if (!strcmp(atype, "LIST") || !strcmp(atype, "USER") ||
1687 !strcmp(atype, "KERBEROS")) {
1688 return(get_ace_internal(atype, aid, action, actarg));
1692 if (!strcmp(atype, "RLIST")) {
1693 sq_save_data(sq, aid);
1694 /* get all the list_id's of containing lists */
1695 ## range of m is members
1696 while (sq_get_data(sq, &id)) {
1697 ## repeat retrieve (listid = m.list_id)
1698 ## where m.member_type = "LIST" and m.member_id = @id {
1699 sq_save_unique_data(sq, listid);
1702 /* now process each one */
1703 while (sq_get_data(sq, &id)) {
1704 if (get_ace_internal("LIST", id, action, actarg) == SMS_SUCCESS)
1709 if (!strcmp(atype, "RUSER")) {
1710 ## range of m is members
1711 ## repeat retrieve (listid = m.list_id)
1712 ## where m.member_type = "USER" and m.member_id = @aid {
1713 sq_save_data(sq, listid);
1715 /* get all the list_id's of containing lists */
1716 while (sq_get_data(sq, &id)) {
1717 ## repeat retrieve (listid = m.list_id)
1718 ## where m.member_type = "LIST" and m.member_id = @id {
1719 sq_save_unique_data(sq, listid);
1722 /* now process each one */
1723 while (sq_get_data(sq, &id)) {
1724 if (get_ace_internal("LIST", id, action, actarg) == SMS_SUCCESS)
1727 if (get_ace_internal("USER", aid, action, actarg) == SMS_SUCCESS)
1731 if (!strcmp(atype, "RKERBERO")) {
1732 ## range of m is members
1733 ## repeat retrieve (listid = m.list_id)
1734 ## where m.member_type = "KERBEROS" and m.member_id = @aid {
1735 sq_save_data(sq, listid);
1737 /* get all the list_id's of containing lists */
1738 while (sq_get_data(sq, &id)) {
1739 ## repeat retrieve (listid = m.list_id)
1740 ## where m.member_type = "LIST" and m.member_id = @id {
1741 sq_save_unique_data(sq, listid);
1744 /* now process each one */
1745 while (sq_get_data(sq, &id)) {
1746 if (get_ace_internal("LIST", id, action, actarg) == SMS_SUCCESS)
1749 if (get_ace_internal("KERBEROS", aid, action, actarg) == SMS_SUCCESS)
1754 if (!found) return(SMS_NO_MATCH);
1755 return(SMS_SUCCESS);
1759 /* This looks up a single list or user for ace use. atype must be "USER"
1760 * or "LIST", and aid is the ID of the corresponding object. This is used
1761 * by get_ace_use above.
1764 ##get_ace_internal(atype, aid, action, actarg)
1775 if (!strcmp(atype, "LIST")) {
1776 rargv[0] = "FILESYS";
1777 ## repeat retrieve (name = filesys.label)
1778 ## where filesys.owners = @aid {
1779 (*action)(2, rargv, actarg);
1784 ## repeat retrieve (name = capacls.capability)
1785 ## where capacls.list_id = @aid {
1786 (*action)(2, rargv, actarg);
1789 } else if (!strcmp(atype, "USER")) {
1790 rargv[0] = "FILESYS";
1791 ## repeat retrieve (name = filesys.label)
1792 ## where filesys.owner = @aid {
1793 (*action)(2, rargv, actarg);
1799 ## repeat retrieve (name = list.#name)
1800 ## where list.acl_type = @atype and list.acl_id = @aid {
1801 (*action)(2, rargv, actarg);
1805 rargv[0] = "SERVICE";
1806 ## repeat retrieve (name = servers.#name)
1807 ## where servers.acl_type = @atype and servers.acl_id = @aid {
1808 (*action)(2, rargv, actarg);
1812 rargv[0] = "HOSTACCESS";
1813 ## repeat retrieve (name = machine.#name)
1814 ## where machine.mach_id = hostaccess.mach_id and
1815 ## hostaccess.acl_type = @atype and hostaccess.acl_id = @aid {
1816 (*action)(2, rargv, actarg);
1819 rargv[0] = "ZEPHYR";
1820 ## repeat retrieve (name = zephyr.class)
1821 ## where zephyr.xmt_type = @atype and zephyr.xmt_id = @aid or
1822 ## zephyr.sub_type = @atype and zephyr.sub_id = @aid or
1823 ## zephyr.iws_type = @atype and zephyr.iws_id = @aid or
1824 ## zephyr.iui_type = @atype and zephyr.iui_id = @aid {
1825 (*action)(2, rargv, actarg);
1829 if (!found) return(SMS_NO_MATCH);
1830 return(SMS_SUCCESS);
1834 /* get_lists_of_member - given a type and a name, return the name and flags
1835 * of all of the lists of the given member. The member_type is one of
1836 * "LIST", "USER", "STRING", "RLIST", "RUSER", or "RSTRING" in argv[0],
1837 * and argv[1] will contain the ID of the entity in question. The R*
1838 * types mean to recursively look at every containing list, not just
1839 * when the object in question is a direct member.
1842 int get_lists_of_member(q, argv, cl, action, actarg)
1851 ## int aid, listid, id;
1852 struct save_queue *sq, *sq_create();
1855 aid = *(int *)argv[1];
1856 if (!strcmp(atype, "LIST") ||
1857 !strcmp(atype, "USER") ||
1858 !strcmp(atype, "STRING") ||
1859 !strcmp(atype, "KERBEROS")) {
1860 return(glom_internal(atype, aid, action, actarg));
1864 if (!strcmp(atype, "RLIST")) {
1865 sq_save_data(sq, aid);
1866 /* get all the list_id's of containing lists */
1867 ## range of m is members
1868 while (sq_get_data(sq, &id)) {
1869 ## repeat retrieve (listid = m.list_id)
1870 ## where m.member_type = "LIST" and m.member_id = @id {
1871 sq_save_unique_data(sq, listid);
1874 /* now process each one */
1875 while (sq_get_data(sq, &id)) {
1876 if (glom_internal("LIST", id, action, actarg) == SMS_SUCCESS)
1881 if (!strcmp(atype, "RUSER")) {
1882 ## range of m is members
1883 ## repeat retrieve (listid = m.list_id)
1884 ## where m.member_type = "USER" and m.member_id = @aid {
1885 sq_save_data(sq, listid);
1887 /* get all the list_id's of containing lists */
1888 while (sq_get_data(sq, &id)) {
1889 ## repeat retrieve (listid = m.list_id)
1890 ## where m.member_type = "LIST" and m.member_id = @id {
1891 sq_save_unique_data(sq, listid);
1894 /* now process each one */
1895 while (sq_get_data(sq, &id)) {
1896 if (glom_internal("LIST", id, action, actarg) == SMS_SUCCESS)
1899 if (glom_internal("USER", aid, action, actarg) == SMS_SUCCESS)
1903 if (!strcmp(atype, "RSTRING")) {
1904 ## range of m is members
1905 ## repeat retrieve (listid = m.list_id)
1906 ## where m.member_type = "STRING" and m.member_id = @aid {
1907 sq_save_data(sq, listid);
1909 /* get all the list_id's of containing lists */
1910 while (sq_get_data(sq, &id)) {
1911 ## repeat retrieve (listid = m.list_id)
1912 ## where m.member_type = "LIST" and m.member_id = @id {
1913 sq_save_unique_data(sq, listid);
1916 /* now process each one */
1917 while (sq_get_data(sq, &id)) {
1918 if (glom_internal("LIST", id, action, actarg) == SMS_SUCCESS)
1921 if (glom_internal("STRING", aid, action, actarg) == SMS_SUCCESS)
1925 if (!strcmp(atype, "RKERBERO")) {
1926 ## range of m is members
1927 ## repeat retrieve (listid = m.list_id)
1928 ## where m.member_type = "KERBEROS" and m.member_id = @aid {
1929 sq_save_data(sq, listid);
1931 /* get all the list_id's of containing lists */
1932 while (sq_get_data(sq, &id)) {
1933 ## repeat retrieve (listid = m.list_id)
1934 ## where m.member_type = "LIST" and m.member_id = @id {
1935 sq_save_unique_data(sq, listid);
1938 /* now process each one */
1939 while (sq_get_data(sq, &id)) {
1940 if (glom_internal("LIST", id, action, actarg) == SMS_SUCCESS)
1943 if (glom_internal("KERBEROS", aid, action, actarg) == SMS_SUCCESS)
1947 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
1948 ## where tblstats.#table = "members"
1950 if (!found) return(SMS_NO_MATCH);
1951 return(SMS_SUCCESS);
1955 /* This looks up a single list, user, or string as a member. atype must be
1956 * "USER", "LIST", or "STRING" and aid is the ID of the corresponding object.
1957 * This is used by get_lists_of_members above.
1960 ##glom_internal(atype, aid, action, actarg)
1968 ## char name[33], active[5], public[5], hidden[5], maillist[5], group[5];
1974 rargv[4] = maillist;
1976 ## repeat retrieve (name = list.#name, active = text(list.#active),
1977 ## public = text(list.#public), hidden = text(list.#hidden),
1978 ## maillist = text(list.#maillist), group = text(list.#group))
1979 ## where list.list_id = m.list_id and
1980 ## m.member_type = @atype and m.member_id = @aid {
1981 (*action)(6, rargv, actarg);
1985 if (!found) return(SMS_NO_MATCH);
1986 return(SMS_SUCCESS);
1990 /* qualified_get_lists: passed "TRUE", "FALSE", or "DONTCARE" for each of
1991 * the five flags associated with each list. It will return the name of
1992 * each list that meets the quailifications. It does this by building a
1993 * where clause based on the arguments, then doing a retrieve.
1996 static char *lflags[5] = { "active", "public", "hidden", "maillist", "group" };
1998 int qualified_get_lists(q, argv, cl, action, actarg)
2005 return(qualified_get(q, argv, action, actarg, "l.list_id != 0",
2006 "l", "name", lflags));
2010 /** get_members_of_list - optimized query for retrieval of list members
2013 ** argv[0] - list_id
2016 ** - retrieve USER members, then LIST members, then STRING members
2019 get_members_of_list(q, argv, cl, action, actarg)
2027 ## char member_name[129];
2030 list_id = *(int *)argv[0];
2032 targv[1] = member_name;
2034 ## range of m is members
2035 ## repeat retrieve (member_name = users.login)
2036 ## where m.#list_id = @list_id and m.member_type = "USER"
2037 ## and m.member_id = users.users_id
2038 ## sort by #member_name
2040 (*action)(2, targv, actarg);
2044 ## repeat retrieve (member_name = list.name)
2045 ## where m.#list_id = @list_id and m.member_type = "LIST"
2046 ## and m.member_id = list.#list_id
2047 ## sort by #member_name
2049 (*action)(2, targv, actarg);
2052 targv[0] = "STRING";
2053 ## repeat retrieve (member_name = strings.string)
2054 ## where m.#list_id = @list_id and m.member_type = "STRING"
2055 ## and m.member_id = strings.string_id
2056 ## sort by #member_name
2058 (*action)(2, targv, actarg);
2061 targv[0] = "KERBEROS";
2062 ## repeat retrieve (member_name = strings.string)
2063 ## where m.#list_id = @list_id and m.member_type = "KERBEROS"
2064 ## and m.member_id = strings.string_id
2065 ## sort by #member_name
2067 (*action)(2, targv, actarg);
2070 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
2071 ## where tblstats.#table = "members"
2072 return(SMS_SUCCESS);
2076 /* count_members_of_list: this is a simple query, but it cannot be done
2077 * through the dispatch table.
2080 int count_members_of_list(q, argv, cl, action, actarg)
2087 ## int list, ct = 0;
2088 char *rargv[1], countbuf[5];
2090 list = *(int *)argv[0];
2091 rargv[0] = countbuf;
2092 ## repeat retrieve (ct = count(members.list_id where members.list_id = @list))
2093 sprintf(countbuf, "%d", ct);
2094 (*action)(1, rargv, actarg);
2095 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
2096 ## where tblstats.#table = "members"
2097 return(SMS_SUCCESS);
2101 /* qualified_get_server: passed "TRUE", "FALSE", or "DONTCARE" for each of
2102 * the three flags associated with each service. It will return the name of
2103 * each service that meets the quailifications. It does this by building a
2104 * where clause based on the arguments, then doing a retrieve.
2107 static char *sflags[3] = { "enable", "inprogress", "harderror" };
2109 int qualified_get_server(q, argv, cl, action, actarg)
2116 return(qualified_get(q, argv, action, actarg, "s.name != \"\"",
2117 "s", "name", sflags));
2121 /* generic qualified get routine, used by qualified_get_lists,
2122 * qualified_get_server, and qualified_get_serverhost.
2124 * start - a simple where clause, must not be empty
2125 * range - the name of the range variable
2126 * field - the field to return
2127 * flags - an array of strings, names of the flag variables
2130 int qualified_get(q, argv, action, actarg, start, range, field, flags)
2140 ## char name[33], qual[256], *rvar, *rtbl, *rfield;
2141 char *rargv[1], buf[32];
2144 strcpy(qual, start);
2145 for (i = 0; i < q->argc; i++) {
2146 if (!strcmp(argv[i], "TRUE")) {
2147 sprintf(buf, " and %s.%s != 0", range, flags[i]);
2148 (void) strcat(qual, buf);
2149 } else if (!strcmp(argv[i], "FALSE")) {
2150 sprintf(buf, " and %s.%s = 0", range, flags[i]);
2151 (void) strcat(qual, buf);
2159 ## range of rvar is rtbl
2160 ## retrieve (name = rvar.rfield) where qual {
2161 (*action)(1, rargv, actarg);
2163 ## inquire_equel(rowcount = "rowcount")
2164 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
2165 ## where tblstats.#table = @rtbl
2167 return(SMS_NO_MATCH);
2168 return(SMS_SUCCESS);
2172 /* qualified_get_serverhost: passed "TRUE", "FALSE", or "DONTCARE" for each of
2173 * the five flags associated with each serverhost. It will return the name of
2174 * each service and host that meets the quailifications. It does this by
2175 * building a where clause based on the arguments, then doing a retrieve.
2178 static char *shflags[6] = { "service", "enable", "override", "success",
2179 "inprogress", "hosterror" };
2181 int qualified_get_serverhost(q, argv, cl, action, actarg)
2188 ## char sname[33], mname[33], qual[256];
2189 char *rargv[2], buf[32];
2192 sprintf(qual, "machine.mach_id = sh.mach_id and sh.service = uppercase(\"%s\")",
2194 for (i = 1; i < q->argc; i++) {
2195 if (!strcmp(argv[i], "TRUE")) {
2196 sprintf(buf, " and sh.%s != 0", shflags[i]);
2198 } else if (!strcmp(argv[i], "FALSE")) {
2199 sprintf(buf, " and sh.%s = 0", shflags[i]);
2206 ## range of sh is serverhosts
2207 ## retrieve (sname = sh.service, mname = machine.name) where qual {
2208 (*action)(2, rargv, actarg);
2210 ## inquire_equel(rowcount = "rowcount")
2211 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
2212 ## where tblstats.#table = "serverhosts"
2214 return(SMS_NO_MATCH);
2215 return(SMS_SUCCESS);
2219 /* register_user - change user's login name and allocate a pobox, group,
2220 * filesystem, and quota for them. The user's status must start out as 0,
2221 * and is left as 2. Arguments are: user's UID, new login name, and user's
2222 * type for filesystem allocation (SMS_FS_STUDENT, SMS_FS_FACULTY,
2223 * SMS_FS_STAFF, SMS_FS_MISC).
2226 register_user(q, argv, cl)
2231 ## char *login, dir[65], *entity, *directory, machname[33];
2232 ## int who, rowcount, mid, uid, users_id, flag, utype, nid, list_id, quota;
2233 ## int size, alloc, pid, m_id;
2236 entity = cl->entity;
2239 uid = atoi(argv[0]);
2241 utype = atoi(argv[2]);
2243 ## range of u is users
2244 ## range of l is list
2245 ## range of sh is serverhosts
2246 ## range of n is nfsphys
2247 ## range of m is machine
2250 ## repeat retrieve (users_id = u.#users_id)
2251 ## where u.#uid = @uid and u.status = 0
2252 ## inquire_equel(rowcount = "rowcount");
2254 return(SMS_NO_MATCH);
2256 return(SMS_NOT_UNIQUE);
2258 /* check new login name */
2259 ## repeat retrieve (flag = any(u.#login where u.#login = @login))
2260 if (ingres_errno) return(sms_errcode);
2261 if (flag) return(SMS_IN_USE);
2262 ## repeat retrieve (flag = any(l.#name where l.#name = @login))
2263 if (ingres_errno) return(sms_errcode);
2264 if (flag) return(SMS_IN_USE);
2265 ## repeat retrieve (flag = any(filesys.#label where filesys.#label = @login))
2266 if (ingres_errno) return(sms_errcode);
2267 if (flag) return(SMS_IN_USE);
2268 com_err(whoami, 0, "new login name OK");
2270 /* choose place for pobox, put in mid */
2271 ## repeat retrieve (mid = sh.mach_id, machname = m.name)
2272 ## where sh.service = "POP" and m.mach_id = sh.mach_id and
2273 ## sh.value2 - sh.value1 = max(sh.value2-sh.value1 where sh.service="POP")
2274 ## inquire_equel(rowcount = "rowcount");
2276 return(SMS_NO_POBOX);
2278 /* change login name, set pobox */
2279 ## repeat replace u (#login = @login, status = 2, modtime = "now",
2280 ## modby = @who, modwith = @entity, potype="POP",
2281 ## pop_id = @mid, pmodtime="now", pmodby=@who,
2282 ## pmodwith=@entity)
2283 ## where u.#users_id = @users_id
2284 ## inquire_equel(rowcount = "rowcount");
2286 return(SMS_INTERNAL);
2287 set_pop_usage(mid, 1);
2288 com_err(whoami, 0, "set login name to %s and pobox to %s", login,
2291 /* create group list */
2292 if (set_next_object_id("gid", "list"))
2294 if (set_next_object_id("list_id", "list"))
2296 ## repeat retrieve (list_id = values.value) where values.name = "list_id"
2297 ## inquire_equel(rowcount = "rowcount");
2299 return(SMS_INTERNAL);
2300 ## repeat append list (name = @login, #list_id = @list_id, active = 1,
2301 ## public = 0, hidden = 0, maillist = 0, group = 1,
2302 ## #gid = values.value, desc = "User Group",
2303 ## acl_type = "USER", acl_id = @users_id, modtime = "now",
2304 ## modby = @who, modwith = @entity)
2305 ## where values.name = "gid"
2306 ## inquire_equel(rowcount = "rowcount");
2308 return(SMS_INTERNAL);
2309 ## repeat append members (#list_id = @list_id, member_type = "USER",
2310 ## member_id = @users_id)
2311 ## inquire_equel(rowcount = "rowcount");
2313 return(SMS_INTERNAL);
2314 com_err(whoami, 0, "group list created");
2316 /* decide where to put filesystem */
2319 ## repeat retrieve (mid = n.mach_id, dir = trim(n.#dir), nid = n.nfsphys_id,
2320 ## flag = n.status, size = n.#size, alloc = n.allocated) {
2321 if ((flag & utype) && (size != 0) && (size - alloc > maxsize)) {
2322 maxsize = size - alloc;
2325 directory = strsave(dir);
2331 return(SMS_NO_FILESYS);
2333 /* create filesystem */
2334 if (set_next_object_id("filsys_id", "filesys"))
2336 ## repeat append filesys (filsys_id = values.value, phys_id = @pid,
2337 ## label = @login, type = "NFS", mach_id = @m_id,
2338 ## name = @directory + "/" + @login,
2339 ## mount = "/mit/" + @login,
2340 ## access = "w", comments = "User Locker",
2341 ## owner = @users_id, owners = @list_id, createflg = 1,
2342 ## lockertype = "HOMEDIR", modtime = "now",
2343 ## modby = @who, modwith = @entity)
2344 ## where values.name = "filsys_id"
2345 ## inquire_equel(rowcount = "rowcount");
2347 return(SMS_INTERNAL);
2348 com_err(whoami, 0, "filesys created on mach %d in %s/%s", m_id,
2352 ## repeat retrieve (quota = values.value) where values.name = "def_quota"
2353 ## inquire_equel(rowcount = "rowcount");
2355 return(SMS_NO_QUOTA);
2356 ## repeat append nfsquota (#users_id = @users_id, filsys_id = values.value,
2357 ## #quota = @quota, phys_id = @pid, modtime = "now",
2358 ## modby = @who, modwith = @entity)
2359 ## where values.name = "filsys_id"
2360 ## inquire_equel(rowcount = "rowcount");
2362 return(SMS_INTERNAL);
2363 ## repeat replace nfsphys (allocated = nfsphys.allocated + @quota)
2364 ## where nfsphys.nfsphys_id = filesys.#phys_id and
2365 ## filesys.filsys_id = values.value and values.name = "filsys_id"
2366 ## inquire_equel(rowcount = "rowcount");
2368 return(SMS_INTERNAL);
2369 com_err(whoami, 0, "quota of %d assigned", quota);
2371 ## repeat replace tblstats (updates = tblstats.updates + 1, modtime = "now")
2372 ## where tblstats.table = "users"
2373 ## repeat replace tblstats (appends = tblstats.appends + 1, modtime = "now")
2374 ## where tblstats.table = "list" or tblstats.table = "filesys" or
2375 ## tblstats.table = "nfsquota"
2376 return(SMS_SUCCESS);
2381 /** set_pop_usage - incr/decr usage count for pop server in serverhosts talbe
2385 ** delta (will be +/- 1)
2388 ** - incr/decr value field in serverhosts table for pop/mach_id
2392 static int set_pop_usage(id, count)
2396 ## int mach_id = id;
2399 ## range of sh is serverhosts
2400 ## repeat replace sh (value1 = sh.value1 + @n)
2401 ## where sh.service = "POP" and sh.#mach_id = @mach_id
2403 return(SMS_SUCCESS);
2408 /* Validation Routines */
2410 validate_row(q, argv, v)
2411 register struct query *q;
2413 register struct validate *v;
2421 /* build where clause */
2422 build_qual(v->qual, v->argc, argv, qual);
2424 /* setup ingres variables */
2429 if (log_flags & LOG_VALID)
2430 /* tell the logfile what we're doing */
2431 com_err(whoami, 0, "validating row: %s", qual);
2433 /* look for the record */
2434 ## range of rvar is table
2435 ## retrieve (rowcount = count(rvar.name where qual))
2436 if (ingres_errno) return(sms_errcode);
2437 if (rowcount == 0) return(SMS_NO_MATCH);
2438 if (rowcount > 1) return(SMS_NOT_UNIQUE);
2442 validate_fields(q, argv, vo, n)
2444 register char *argv[];
2445 register struct valobj *vo;
2448 register int status;
2453 if (log_flags & LOG_VALID)
2454 com_err(whoami, 0, "validating %s in %s: %s",
2455 vo->namefield, vo->table, argv[vo->index]);
2456 status = validate_name(argv, vo);
2460 if (log_flags & LOG_VALID)
2461 com_err(whoami, 0, "validating %s in %s: %s",
2462 vo->idfield, vo->table, argv[vo->index]);
2463 status = validate_id(argv, vo);
2467 if (log_flags & LOG_VALID)
2468 com_err(whoami, 0, "validating date: %s", argv[vo->index]);
2469 status = validate_date(argv, vo);
2473 if (log_flags & LOG_VALID)
2474 com_err(whoami, 0, "validating %s type: %s",
2475 vo->table, argv[vo->index]);
2476 status = validate_type(argv, vo);
2480 if (log_flags & LOG_VALID)
2481 com_err(whoami, 0, "validating typed data (%s): %s",
2482 argv[vo->index - 1], argv[vo->index]);
2483 status = validate_typedata(q, argv, vo);
2487 if (log_flags & LOG_VALID)
2488 com_err(whoami, 0, "validating rename %s in %s",
2489 argv[vo->index], vo->table);
2490 status = validate_rename(argv, vo);
2494 if (log_flags & LOG_VALID)
2495 com_err(whoami, 0, "validating chars: %s", argv[vo->index]);
2496 status = validate_chars(argv[vo->index]);
2500 status = SMS_EXISTS;
2504 status = lock_table(vo);
2508 if (status != SMS_EXISTS) return(status);
2512 return(SMS_SUCCESS);
2516 /* validate_chars: verify that there are no illegal characters in
2517 * the string. Legal characters are printing chars other than
2518 * ", *, ?, \, [ and ].
2520 static int illegalchars[] = {
2521 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
2522 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
2523 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
2524 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
2525 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ - O */
2526 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* P - _ */
2527 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
2528 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
2529 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2530 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2531 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2532 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2533 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2534 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2535 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2536 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2543 if (illegalchars[*s++])
2544 return(SMS_BAD_CHAR);
2549 validate_id(argv, vo)
2551 register struct valobj *vo;
2561 name = argv[vo->index];
2563 /* minor kludge to upcasify machine names */
2564 if (!strcmp(table, "machine"))
2565 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
2566 namefield = vo->namefield;
2567 idfield = vo->idfield;
2568 if (!strcmp(namefield, "uid")) {
2569 ## retrieve (id = table.idfield) where table.namefield = int4(name)
2570 if (ingres_errno) return(sms_errcode);
2571 ## inquire_equel (rowcount = "rowcount")
2573 ## retrieve (id = table.idfield) where table.namefield = name
2574 if (ingres_errno) return(sms_errcode);
2575 ## inquire_equel (rowcount = "rowcount")
2577 if (rowcount != 1) return(vo->error);
2578 *(int *)argv[vo->index] = id;
2582 validate_name(argv, vo)
2584 register struct valobj *vo;
2592 name = argv[vo->index];
2594 namefield = vo->namefield;
2595 if (!strcmp(table, "servers") && !strcmp(namefield, "name")) {
2596 for (c = name; *c; c++)
2600 ## retrieve (rowcount = countu(table.namefield
2601 ## where table.namefield = name))
2602 if (ingres_errno) return(sms_errcode);
2603 return ((rowcount == 1) ? SMS_EXISTS : vo->error);
2606 validate_date(argv, vo)
2614 idate = argv[vo->index];
2616 ## retrieve (dd = interval("years", date(idate) - date("today")))
2617 ## inquire_equel (errorno = "errorno")
2618 if (errorno != 0 || dd > 5.0) return(SMS_DATE);
2623 validate_rename(argv, vo)
2627 ## char *name, *table, *namefield, *idfield;
2631 c = name = argv[vo->index];
2633 if (illegalchars[*c++])
2634 return(SMS_BAD_CHAR);
2636 /* minor kludge to upcasify machine names */
2637 if (!strcmp(table, "machine"))
2638 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
2639 namefield = vo->namefield;
2640 idfield = vo->idfield;
2643 if (!strcmp(argv[vo->index], argv[vo->index - 1]))
2645 ## retrieve (id = any(table.namefield where table.namefield = name))
2646 if (ingres_errno) return(sms_errcode);
2652 ## retrieve (id = table.idfield) where table.namefield = name
2653 if (ingres_errno) return(sms_errcode);
2654 if (id == -1 || id == *(int *)argv[vo->index - 1])
2661 validate_type(argv, vo)
2663 register struct valobj *vo;
2670 typename = vo->table;
2671 c = value = argv[vo->index];
2673 if (illegalchars[*c++])
2674 return(SMS_BAD_CHAR);
2676 /* uppercase type fields */
2677 for (c = value; *c; c++) if (islower(*c)) *c = toupper(*c);
2679 ## range of a is alias
2680 ## repeat retrieve (exists = any(a.trans where a.name = @typename and
2681 ## a.type = "TYPE" and
2682 ## a.trans = @value))
2683 if (ingres_errno) return(sms_errcode);
2684 return (exists ? SMS_EXISTS : vo->error);
2687 /* validate member or type-specific data field */
2689 validate_typedata(q, argv, vo)
2690 register struct query *q;
2691 register char *argv[];
2692 register struct valobj *vo;
2695 ## char *field_type;
2696 ## char data_type[129];
2702 /* get named object */
2703 name = argv[vo->index];
2705 /* get field type string (known to be at index-1) */
2706 field_type = argv[vo->index-1];
2708 /* get corresponding data type associated with field type name */
2709 ## repeat retrieve (data_type = alias.trans)
2710 ## where alias.#name = @field_type and alias.type = "TYPEDATA"
2711 if (ingres_errno) return(sms_errcode);
2712 ## inquire_equel (rowcount = "rowcount")
2713 if (rowcount != 1) return(SMS_TYPE);
2715 /* now retrieve the record id corresponding to the named object */
2716 if (index(data_type, ' '))
2717 *index(data_type, ' ') = 0;
2718 if (!strcmp(data_type, "user")) {
2720 ## repeat retrieve (id = users.users_id) where users.login = @name
2721 ## inquire_equel (rowcount = "rowcount")
2722 if (rowcount != 1) return(SMS_USER);
2724 } else if (!strcmp(data_type, "list")) {
2726 ## repeat retrieve (id = list.list_id) where list.#name = @name
2727 ## inquire_equel (rowcount = "rowcount")
2728 if (rowcount != 1) {
2729 /* if idfield is non-zero, then if argv[0] matches the string
2730 * that we're trying to resolve, we should get the value of
2731 * values.[idfield] for the id.
2733 if (vo->idfield && !strcmp(argv[0], argv[vo->index])) {
2734 set_next_object_id(q->validate->object_id, q->rtable);
2736 ## repeat retrieve (id = values.value) where values.#name = @name
2737 ## inquire_equel(rowcount = "rowcount")
2738 if (rowcount != 1) return(SMS_LIST);
2742 } else if (!strcmp(data_type, "machine")) {
2744 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
2745 ## repeat retrieve (id = machine.mach_id) where machine.#name = @name
2746 ## inquire_equel (rowcount = "rowcount")
2747 if (rowcount != 1) return(SMS_MACHINE);
2749 } else if (!strcmp(data_type, "string")) {
2751 ## range of s is strings
2752 ## repeat retrieve (id = s.string_id) where s.string = @name
2753 ## inquire_equel (rowcount = "rowcount")
2754 if (rowcount == 0) {
2755 if (q->type != APPEND) return(SMS_STRING);
2756 ## range of v is values
2757 ## retrieve (id = v.value) where v.#name = "strings_id"
2759 ## replace v (value = id) where v.#name = "strings_id"
2760 ## append to strings (string_id = id, string = name)
2762 } else if (!strcmp(data_type, "none")) {
2768 /* now set value in argv */
2769 *(int *)argv[vo->index] = id;
2771 return (SMS_EXISTS);
2775 /* Lock the table named by the validation object */
2780 ## char *table, *idfield;
2784 idfield = vo->idfield;
2785 ## replace table (modtime = "now") where table.idfield = 0
2786 if (ingres_errno) return(sms_errcode);
2787 ## inquire_equel (rowcount = "rowcount")
2795 /* This looks up a login name and returns the SMS internal ID. It is used
2796 * by authenticate to put the users_id in the client structure.
2799 int get_users_id(name)
2802 ## int id, rowcount;
2807 ## range of u is users
2808 ## repeat retrieve (id = u.#users_id) where u.#login = @login
2809 ## inquire_equel (rowcount = "rowcount")
2818 /* Check the database at startup time. For now this just resets the
2819 * inprogress flags that the DCM uses.
2822 sanity_check_database()