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();
20 extern int ingres_errno;
23 /* Specialized Access Routines */
25 /* access_user - verify that client name equals specified login name
27 * - since field validation routines are called first, a users_id is
28 * now in argv[0] instead of the login name.
31 access_user(q, argv, cl)
36 if (cl->users_id != *(int *)argv[0])
44 /* access_login - verify that client name equals specified login name
46 * argv[0...n] contain search info. q->
49 access_login(q, argv, cl)
57 build_qual(q->qual, q->argc, argv, qual);
58 ## retrieve (id = u.users_id) where qual
59 if (ingres_errno != 0) return(ingres_errno);
60 ## inquire_equel(rowcount = "rowcount")
61 if (rowcount != 1 || id != cl->users_id)
69 /* access_list - check access for most list operations
71 * Inputs: argv[0] - list_id
73 * argv[2] - member ID (only for queries "amtl" and "dmfl")
74 * argv[7] - group IID (only for query "ulis")
77 * - check that client is a member of the access control list
78 * - OR, if the query is add_member_to_list or delete_member_from_list
79 * and the list is public, allow access if client = member
82 access_list(q, argv, cl)
87 ## int list_id, acl_id, flags, rowcount, gid;
90 int client_id, status;
92 list_id = *(int *)argv[0];
93 ## repeat retrieve (acl_id = list.#acl_id, acl_type = list.#acl_type,
94 ## gid = list.#gid, flags = list.#public)
95 ## where list.#list_id = @list_id
96 if (ingres_errno != 0) return(ingres_errno);
97 ## inquire_equel(rowcount = "rowcount")
101 /* parse client structure */
102 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
105 /* if amtl or dmfl and list is public allow client to add or delete self */
106 if ((!strcmp("amtl", q->shortname) || !strcmp("dmfl", q->shortname)) &&
107 (flags && !strcmp("USER", argv[1]))) {
108 if (*(int *)argv[2] == client_id) return(SMS_SUCCESS);
109 /* if update_list, don't allow them to change the GID */
110 } else if (!strcmp("ulis", q->shortname)) {
111 if ((!strcmp(argv[7], UNIQUE_GID) && (gid != -1)) ||
112 (strcmp(argv[7], UNIQUE_GID) && (gid != atoi(argv[7]))))
116 /* check for client in access control list */
117 status = find_member(acl_type, acl_id, client_type, client_id, 0);
118 if (!status) return(SMS_PERM);
124 /* access_visible_list - allow access to list only if it is not hidden,
125 * or if the client is on the ACL
127 * Inputs: argv[0] - list_id
128 * cl - client identifier
131 access_visible_list(q, argv, cl)
136 ## int list_id, acl_id, flags, rowcount;
139 int client_id, status;
141 list_id = *(int *)argv[0];
142 ## repeat retrieve (flags = list.hidden, acl_id = list.#acl_id,
143 ## acl_type = list.#acl_type) where list.#list_id = @list_id
144 if (ingres_errno != 0) return(ingres_errno);
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 if (ingres_errno != 0) return(ingres_errno);
185 ## inquire_equel(rowcount = "rowcount");
187 return(SMS_WILDCARD);
189 return(SMS_NO_MATCH);
193 /* parse client structure */
194 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
197 /* check for client in access control list */
198 status = find_member(acl_type, acl_id, client_type, client_id, 0);
206 /* access_member - allow user to access member of type "USER" and name matches
207 * username, or to access member of type "LIST" and list is one that user is
208 * on the acl of, or the list is visible.
211 access_member(q, argv, cl)
216 if (!strcmp(argv[0], "LIST") || !strcmp(argv[0], "RLIST"))
217 return(access_visible_list(q, &argv[1], cl));
219 if (!strcmp(argv[0], "USER") || !strcmp(argv[0], "RUSER")) {
220 if (cl->users_id == *(int *)argv[1])
228 /* access_qgli - special access routine for Qualified_get_lists. Allows
229 * access iff argv[0] == "TRUE" and argv[2] == "FALSE".
232 access_qgli(q, argv, cl)
237 if (!strcmp(argv[0], "TRUE") && !strcmp(argv[2], "FALSE"))
243 /* access_service - allow access if user is on ACL of service. Don't
244 * allow access if a wildcard is used.
247 access_service(q, argv, cl)
252 ## int acl_id, rowcount;
253 ## char *name, acl_type[9];
254 int client_id, status;
258 ## repeat retrieve (acl_id = servers.#acl_id, acl_type = servers.#acl_type)
259 ## where servers.#name = uppercase(@name)
260 if (ingres_errno != 0) return(ingres_errno);
261 ## inquire_equel(rowcount = "rowcount")
265 /* parse client structure */
266 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
269 /* check for client in access control list */
270 status = find_member(acl_type, acl_id, client_type, client_id, 0);
271 if (!status) return(SMS_PERM);
278 /* access_filesys - verify that client is owner or on owners list of filesystem
282 access_filesys(q, argv, cl)
287 ## int rowcount, users_id, list_id;
289 int status, client_id;
293 ## repeat retrieve (users_id = filesys.owner, list_id = filesys.owners)
294 ## where filesys.label = @name
295 if (ingres_errno != 0) return(ingres_errno);
296 ## inquire_equel(rowcount = "rowcount")
300 if (users_id == cl->users_id)
302 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
304 status = find_member("LIST", list_id, client_type, client_id, 0);
314 /* Setup routine for add_user
316 * Inputs: argv[0] - login
321 * - if argv[1] == UNIQUE_UID then set argv[1] = next(uid)
322 * - if argv[0] == UNIQUE_LOGIN then set argv[0] = "#<uid>"
325 setup_ausr(q, argv, cl)
327 register char *argv[];
330 ## int nuid, rowcount;
332 if (!strcmp(argv[1], UNIQUE_UID) || atoi(argv[1]) == -1) {
333 if (set_next_object_id("uid", "users"))
334 return(SMS_INGRES_ERR);
335 ## repeat retrieve (nuid = values.value) where values.name = "uid"
336 if (ingres_errno != 0) return(ingres_errno);
337 ## inquire_equel(rowcount = "rowcount")
339 return(SMS_INTERNAL);
340 sprintf(argv[1], "%d", nuid);
343 if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[1]) == -1) {
344 sprintf(argv[0], "#%s", argv[1]);
351 /* setup_dusr - verify that the user is no longer being referenced
352 * and may safely be deleted.
355 int setup_dusr(q, argv)
361 id = *(int *)argv[0];
363 /* For now, only allow users to be deleted if their status is 0 */
364 ## repeat retrieve (flag = u.status) where u.users_id = @id
368 ## repeat delete nfsquota where nfsquota.users_id = @id
369 if (ingres_errno != 0) return(ingres_errno);
370 ## repeat retrieve (flag = any(members.member_id where members.member_id=@id
371 ## and members.member_type = "USER"))
372 if (ingres_errno != 0) return(ingres_errno);
375 ## repeat retrieve (flag = any(filesys.label where filesys.owner=@id))
376 if (ingres_errno != 0) return(ingres_errno);
379 ## repeat retrieve (flag = any(list.name where list.acl_id=@id and
380 ## list.acl_type = "USER"))
381 if (ingres_errno != 0) return(ingres_errno);
384 ## repeat retrieve (flag = any(servers.name where servers.acl_id=@id and
385 ## servers.acl_type = "USER"))
386 if (ingres_errno != 0) return(ingres_errno);
389 ## repeat retrieve (flag=any(hostaccess.acl_id where hostaccess.acl_id=@id and
390 ## hostaccess.acl_type = "USER"))
391 if (ingres_errno != 0) return(ingres_errno);
399 /* setup_spop: verify that there is already a valid POP machine_id in the
400 * pop_id field. Also take care of keeping track of the post office usage.
402 int setup_spop(q, argv)
406 ## int id, mid, flag;
409 id = *(int *)argv[0];
410 ## repeat retrieve (type = u.potype, mid = u.pop_id,
411 ## flag = any(machine.name where machine.mach_id = u.pop_id
412 ## and u.pop_id != 0 and u.users_id = @id))
413 ## where u.users_id = @id
414 if (ingres_errno != 0) return(ingres_errno);
417 if (strcmp(strtrim(type), "POP"))
418 set_pop_usage(mid, 1);
423 /* setup_dpob: Take care of keeping track of the post office usage.
425 int setup_dpob(q, argv)
432 user = *(int *)argv[0];
433 ## repeat retrieve (type = u.potype, id = u.pop_id)
434 ## where u.users_id = @user
435 if (ingres_errno != 0) return(ingres_errno);
437 if (!strcmp(strtrim(type), "POP"))
438 set_pop_usage(id, -1);
443 /* setup_dmac - verify that the machine is no longer being referenced
444 * and may safely be deleted.
447 int setup_dmac(q, argv)
453 id = *(int *)argv[0];
454 ## repeat retrieve (flag = any(users.login where users.potype = "POP"
455 ## and users.pop_id=@id))
456 if (ingres_errno != 0) return(ingres_errno);
459 ## repeat retrieve (flag = any(serverhosts.mach_id
460 ## where serverhosts.mach_id=@id))
461 if (ingres_errno != 0) return(ingres_errno);
464 ## repeat retrieve (flag = any(nfsphys.mach_id where nfsphys.mach_id=@id))
465 if (ingres_errno != 0) return(ingres_errno);
468 ## repeat retrieve (flag = any(hostaccess.mach_id where hostaccess.mach_id=@id))
469 if (ingres_errno != 0) return(ingres_errno);
472 ## repeat retrieve (flag = any(printcap.mach_id where printcap.mach_id=@id))
473 if (ingres_errno != 0) return(ingres_errno);
477 ## repeat delete mcmap where mcmap.mach_id = @id
478 if (ingres_errno != 0) return(ingres_errno);
483 /* setup_dclu - verify that the cluster is no longer being referenced
484 * and may safely be deleted.
487 int setup_dclu(q, argv)
493 id = *(int *)argv[0];
494 ## repeat retrieve (flag = any(mcmap.mach_id where mcmap.clu_id=@id))
495 if (ingres_errno != 0) return(ingres_errno);
498 ## repeat retrieve (flag = any(svc.clu_id where svc.clu_id=@id))
499 if (ingres_errno != 0) return(ingres_errno);
507 /* setup_alis - if argv[5] is non-zero and argv[6] is UNIQUE_ID, then allocate
508 * a new gid and put it in argv[6]. Otherwise if argv[6] is UNIQUE_ID but
509 * argv[5] is not, then remember that UNIQUE_ID is being stored by putting
510 * a -1 there. Remember that this is also used for ulis, with the indexes
514 int setup_alis(q, argv)
522 if (!strcmp(q->shortname, "alis"))
524 else if (!strcmp(q->shortname, "ulis"))
527 if (!strcmp(argv[idx], UNIQUE_GID) || atoi(argv[idx]) == -1) {
528 if (atoi(argv[idx - 1])) {
529 if (set_next_object_id("gid", "list"))
530 return(SMS_INGRES_ERR);
531 ## repeat retrieve (ngid = values.value) where values.name = "gid"
532 if (ingres_errno != 0) return(ingres_errno);
533 sprintf(argv[idx], "%d", ngid);
535 strcpy(argv[idx], "-1");
543 /* setup_dlist - verify that the list is no longer being referenced
544 * and may safely be deleted.
547 int setup_dlis(q, argv)
553 id = *(int *)argv[0];
554 ## repeat retrieve (flag = any(members.member_id where members.member_id=@id
555 ## and members.member_type = "LIST"))
556 if (ingres_errno != 0) return(ingres_errno);
559 ## repeat retrieve (flag = any(members.member_id where members.list_id=@id))
560 if (ingres_errno != 0) return(ingres_errno);
563 ## repeat retrieve (flag = any(filesys.label where filesys.owners=@id))
564 if (ingres_errno != 0) return(ingres_errno);
567 ## repeat retrieve (flag = any(capacls.tag where capacls.list_id=@id))
568 if (ingres_errno != 0) return(ingres_errno);
571 ## repeat retrieve (flag = any(list.name where list.acl_id=@id and
572 ## list.acl_type = "LIST" and list.list_id != @id))
573 if (ingres_errno != 0) return(ingres_errno);
576 ## repeat retrieve (flag = any(servers.name where servers.acl_id=@id and
577 ## servers.acl_type = "LIST"))
578 if (ingres_errno != 0) return(ingres_errno);
581 ## repeat retrieve (flag=any(hostaccess.acl_id where hostaccess.acl_id=@id and
582 ## hostaccess.acl_type = "LIST"))
583 if (ingres_errno != 0) return(ingres_errno);
586 ## repeat retrieve (flag = any(zephyr.class
587 ## where zephyr.xmt_type = "LIST" and zephyr.xmt_id = @id or
588 ## zephyr.sub_type = "LIST" and zephyr.sub_id = @id or
589 ## zephyr.iws_type = "LIST" and zephyr.iws_id = @id or
590 ## zephyr.iui_type = "LIST" and zephyr.iui_id = @id))
591 if (ingres_errno != 0) return(ingres_errno);
599 /* setup_dsin - verify that the service is no longer being referenced
600 * and may safely be deleted.
603 int setup_dsin(q, argv)
611 ## repeat retrieve (flag = any(serverhosts.service
612 ## where serverhosts.service=uppercase(@name)))
613 if (ingres_errno != 0) return(ingres_errno);
616 ## repeat retrieve (flag = servers.inprogress) where servers.#name = @name
617 if (ingres_errno != 0) return(ingres_errno);
625 /* setup_dshi - verify that the service-host is no longer being referenced
626 * and may safely be deleted.
629 int setup_dshi(q, argv)
637 id = *(int *)argv[1];
638 ## repeat retrieve (flag=serverhosts.inprogress)
639 ## where serverhosts.service=uppercase(@name) and serverhosts.mach_id=@id
640 if (ingres_errno != 0) return(ingres_errno);
649 ** setup_add_filesys - verify existance of referenced file systems
661 ** * extract directory prefix from name
662 ** * verify mach_id/dir in nfsphys
663 ** * verify access in {r, w, R, W}
665 ** Side effect: sets variable var_phys_id to the ID of the physical
666 ** filesystem (nfsphys_id for NFS, 0 for RVD)
669 ** SMS_NFS - specified directory not exported
670 ** SMS_FILESYS_ACCESS - invalid filesys access
674 ##static int var_phys_id;
686 mach_id = *(int *)argv[2];
691 if (!strcmp(type, "NFS"))
692 return (check_nfs(mach_id, name, access));
698 /* Verify the arguments, depending on the FStype. Also, if this is an
699 * NFS filesystem, then update any quotas for that filesystem to reflect
708 char *type, *name, *access;
712 mach_id = *(int *)argv[3];
717 if (!strcmp(type, "NFS")) {
718 status = check_nfs(mach_id, name, access);
719 fid = *(int *)argv[0];
720 ## replace nfsquota (phys_id = var_phys_id) where nfsquota.filsys_id = fid
721 if (ingres_errno != 0) return(ingres_errno);
728 /* Find the NFS physical partition that the named directory is on.
729 * This is done by comparing the dir against the mount point of the
730 * partition. To make sure we get the correct match when there is
731 * more than one, we sort the query in reverse order by dir name.
734 ##check_nfs(mach_id, name, access)
745 caccess = (isupper(*access)) ? tolower(*access) : *access;
746 if (caccess != 'r' && caccess != 'w') return(SMS_FILESYS_ACCESS);
749 ## range of np is nfsphys
750 ## repeat retrieve (var_phys_id = np.#nfsphys_id, dir = trim(np.#dir))
751 ## where np.#mach_id = @mach_id sort by #dir:d {
755 if (*cp1++ != *cp2) break;
759 status = SMS_SUCCESS;
763 if (ingres_errno != 0) return(ingres_errno);
769 /* setup_dfil: free any quota records associated with a filesystem
770 * when it is deleted.
773 setup_dfil(q, argv, cl)
780 id = *(int *)argv[0];
781 ## range of q is nfsquota
782 ## range of fs is filesys
783 ## range of n is nfsphys
784 ## repeat replace n (allocated=n.allocated-sum(q.quota where q.filsys_id=@id))
785 ## where n.nfsphys_id = fs.phys_id and fs.filsys_id = @id
786 if (ingres_errno != 0) return(ingres_errno);
788 ## repeat delete q where q.filsys_id = @id
789 if (ingres_errno != 0) return(ingres_errno);
794 /* setup_dnfp: check to see that the nfs physical partition does not have
795 * any filesystems assigned to it before allowing it to be deleted.
798 setup_dnfp(q, argv, cl)
805 id = *(int *)argv[0];
806 ## repeat retrieve (exists = any(filesys.label where filesys.phys_id = @id))
807 if (ingres_errno != 0) return(ingres_errno);
814 /* setup_dnfq: Remove allocation from nfsphys before deleting quota.
815 * argv[0] = filsys_id
819 setup_dnfq(q, argv, cl)
824 ## int quota, fs, user;
826 fs = *(int *)argv[0];
827 user = *(int *)argv[1];
829 ## range of q is nfsquota
830 ## repeat retrieve (quota = q.#quota) where q.users_id = @user and
832 if (ingres_errno != 0) return(ingres_errno);
833 ## repeat replace nfsphys (allocated = nfsphys.allocated - @quota)
834 ## where nfsphys.nfsphys_id = filesys.#phys_id and filesys.filsys_id = @fs
835 if (ingres_errno != 0) return(ingres_errno);
841 /* FOLLOWUP ROUTINES */
843 /* generic set_modtime routine. This takes the table name from the query,
844 * and will update the modtime, modby, and modwho fields in the entry in
845 * the table whose name field matches argv[0].
848 set_modtime(q, argv, cl)
853 ## char *name, *entity, *table;
861 ## replace table (modtime = "now", modby = who, modwith = entity)
862 ## where table.#name = name
863 if (ingres_errno != 0) return(ingres_errno);
867 /* generic set_modtime_by_id routine. This takes the table name from
868 * the query, and the id name from the validate record,
869 * and will update the modtime, modby, and modwho fields in the entry in
870 * the table whose id matches argv[0].
873 set_modtime_by_id(q, argv, cl)
878 ## char *entity, *table, *id_name;
884 id_name = q->validate->object_id;
886 id = *(int *)argv[0];
887 ## replace table (modtime = "now", modby = who, modwith = entity)
888 ## where table.id_name = id
889 if (ingres_errno != 0) return(ingres_errno);
894 /* Sets the finger modtime on a user record. The users_id will be in argv[0].
897 set_finger_modtime(q, argv, cl)
902 ## int users_id, who;
907 users_id = *(int *)argv[0];
909 ## repeat replace u (fmodtime = "now", fmodby = @who, fmodwith = @entity)
910 ## where u.#users_id = @users_id
911 if (ingres_errno != 0) return(ingres_errno);
916 /* Sets the pobox modtime on a user record. The users_id will be in argv[0].
919 set_pobox_modtime(q, argv, cl)
924 ## int users_id, who;
929 users_id = *(int *)argv[0];
931 ## repeat replace users (pmodtime = "now", pmodby = @who, pmodwith = @entity)
932 ## where users.#users_id = @users_id
933 if (ingres_errno != 0) return(ingres_errno);
938 /* Sets the modtime on a machine record. The machine name is in argv[0].
939 * This routine is different from the generic set_modtime in that the
940 * name is uppercased first.
943 set_mach_modtime(q, argv, cl)
948 ## char *host, *entity;
955 ## repeat replace m (modtime = "now", modby = @who, modwith = @entity)
956 ## where m.name = uppercase(@host)
957 if (ingres_errno != 0) return(ingres_errno);
962 /* Sets the modtime on the machine whose mach_id is in argv[0]. This routine
963 * is necessary for add_machine_to_cluster becuase the table that query
964 * operates on is "mcm", not "machine".
967 set_mach_modtime_by_id(q, argv, cl)
978 id = *(int *)argv[0];
979 ## range of m is machine
980 ## repeat replace m (modtime = "now", modby = @who, modwith = @entity)
981 ## where m.mach_id = @id
982 if (ingres_errno != 0) return(ingres_errno);
987 /* Sets the modtime on the cluster whose mach_id is in argv[0]. This routine
988 * is necessary for add_cluster_data and delete_cluster_data becuase the
989 * table that query operates on is "svc", not "cluster".
992 set_cluster_modtime_by_id(q, argv, cl)
1000 entity = cl->entity;
1003 id = *(int *)argv[0];
1004 ## range of c is cluster
1005 ## repeat replace c (modtime = "now", modby = @who, modwith = @entity)
1006 ## where c.clu_id = @id
1007 if (ingres_errno != 0) return(ingres_errno);
1008 return(SMS_SUCCESS);
1012 /* sets the modtime on the serverhost where the service name is in argv[0]
1013 * and the mach_id is in argv[1].
1016 set_serverhost_modtime(q, argv, cl)
1021 ## char *entity, *serv;
1024 entity = cl->entity;
1028 id = *(int *)argv[1];
1029 ## repeat replace sh (modtime = "now", modby = @who, modwith = @entity)
1030 ## where sh.service = uppercase(@serv) and sh.mach_id = @id
1031 if (ingres_errno != 0) return(ingres_errno);
1032 return(SMS_SUCCESS);
1036 /* sets the modtime on the nfsphys where the mach_id is in argv[0] and the
1037 * directory name is in argv[1].
1040 set_nfsphys_modtime(q, argv, cl)
1045 ## char *entity, *dir;
1048 entity = cl->entity;
1051 id = *(int *)argv[0];
1053 ## repeat replace np (modtime = "now", modby = @who, modwith = @entity)
1054 ## where np.#dir = @dir and np.mach_id = @id
1055 if (ingres_errno != 0) return(ingres_errno);
1056 return(SMS_SUCCESS);
1060 /* sets the modtime on a filesystem, where argv[0] contains the filesys
1064 set_filesys_modtime(q, argv, cl)
1069 ## char *label, *entity;
1072 entity = cl->entity;
1076 if (!strcmp(q->shortname, "ufil"))
1079 ## repeat replace fs (modtime = "now", modby = @who, modwith = @entity,
1080 ## #phys_id = @var_phys_id) where fs.#label = @label
1081 if (ingres_errno != 0) return(ingres_errno);
1082 return(SMS_SUCCESS);
1086 /* sets the modtime on a zephyr class, where argv[0] contains the class
1090 set_zephyr_modtime(q, argv, cl)
1095 ## char *class, *entity;
1098 entity = cl->entity;
1103 ## repeat replace z (modtime = "now", modby = @who, modwith = @entity)
1104 ## where z.#class = @class
1105 if (ingres_errno != 0) return(ingres_errno);
1106 return(SMS_SUCCESS);
1110 /* fixes the modby field. This will be the second to last thing in the
1111 * argv, the argv length is determined from the query structure. It is
1112 * passed as a pointer to an integer. This will either turn it into a
1113 * username, or # + the users_id.
1115 followup_fix_modby(q, sq, v, action, actarg, cl)
1117 register struct save_queue *sq;
1119 register int (*action)();
1120 register int actarg;
1124 char **argv, *malloc();
1125 ## int id, rowcount;
1129 while (sq_get_data(sq, &argv)) {
1132 argv[i] = malloc(9);
1134 ## repeat retrieve (name = users.login) where users.users_id = @id
1135 ## inquire_equel(rowcount = "rowcount")
1136 if (rowcount != 1) {
1137 sprintf(argv[i], "#%d", id);
1139 (*action)(q->vcnt, argv, actarg);
1140 for (j = 0; j < q->vcnt; j++)
1145 return(SMS_SUCCESS);
1150 ** followup_ausr - add finger and pobox entries, set_user_modtime
1153 ** argv[0] - login (add_user)
1154 ** argv[3] - last name
1155 ** argv[4] - first name
1156 ** argv[5] - middle name
1160 followup_ausr(q, argv, cl)
1166 ## char *login, *entity;
1167 ## char fullname[129];
1171 entity = cl->entity;
1173 /* build fullname */
1174 if (strlen(argv[4]) && strlen(argv[5]))
1175 sprintf(fullname, "%s %s %s", argv[4], argv[5], argv[3]);
1176 else if (strlen(argv[4]))
1177 sprintf(fullname, "%s %s", argv[4], argv[3]);
1179 sprintf(fullname, "%s", argv[3]);
1181 /* create finger entry, pobox & set modtime on user */
1182 ## repeat replace u (modtime = "now", modby=@who, modwith=@entity,
1183 ## #fullname=@fullname, mit_affil = u.mit_year,
1184 ## fmodtime="now", fmodby=@who, fmodwith=@entity,
1185 ## potype="NONE", pmodtime="now", pmodby=@who, pmodwith=@entity)
1186 ## where u.#login = @login
1187 if (ingres_errno != 0) return(ingres_errno);
1189 return(SMS_SUCCESS);
1193 /* followup_gpob: fixes argv[2] based on the IDs currently there and the
1194 * type in argv[1]. Then completes the upcall to the user.
1196 * argv[2] is of the form "123:234" where the first integer is the machine
1197 * ID if it is a pop box, and the second is the string ID if it is an SMTP
1198 * box. argv[1] should be "POP", "SMTP", or "NONE". Boxes of type NONE
1202 followup_gpob(q, sq, v, action, actarg, cl)
1203 register struct query *q;
1204 register struct save_queue *sq;
1205 register struct validate *v;
1206 register int (*action)();
1210 char **argv, *index();
1212 ## char box[129], *name;
1213 ## int mid, sid, rowcount;
1216 while (sq_get_data(sq, &argv)) {
1217 sms_trim_args(2, argv);
1219 p = index(argv[2], ':');
1221 mid = atoi(argv[2]);
1225 if (!strcmp(ptype, "POP")) {
1226 ## repeat retrieve (box=machine.#name) where machine.mach_id=@mid
1227 ## inquire_equel(rowcount = "rowcount")
1229 return(SMS_MACHINE);
1230 } else if (!strcmp(ptype, "SMTP")) {
1231 ## repeat retrieve (box=strings.string) where strings.string_id=@sid
1232 ## inquire_equel(rowcount = "rowcount")
1235 } else /* ptype == "NONE" */ {
1239 if (!strcmp(q->shortname, "gpob")) {
1240 sid = atoi(argv[4]);
1242 argv[4] = malloc(9);
1244 ## repeat retrieve (name = users.login) where users.users_id = @sid
1245 ## inquire_equel(rowcount = "rowcount")
1247 sprintf(name, "#%d", sid);
1251 (*action)(q->vcnt, argv, actarg);
1253 /* free saved data */
1260 return (SMS_SUCCESS);
1264 /* followup_glin: fix the ace_name in argv[8]. argv[7] will contain the
1265 * ace_type: "LIST", "USER", or "NONE". Decode the id in argv[8] into the
1266 * proper name based on the type, and repace that string in the argv.
1267 * Also fixes the modby field by called followup_fix_modby.
1270 followup_glin(q, sq, v, action, actarg, cl)
1271 register struct query *q;
1272 register struct save_queue *sq;
1273 register struct validate *v;
1274 register int (*action)();
1278 char **argv, *malloc(), *realloc(), *type;
1280 ## int id, rowcount;
1284 if (!strcmp(q->shortname, "gsin"))
1287 while (sq_get_data(sq, &argv)) {
1288 sms_trim_args(q->vcnt, argv);
1290 id = atoi(argv[i = q->vcnt - 2]);
1292 name = argv[i] = malloc(9);
1293 ## repeat retrieve (name = users.login) where users.users_id = @id
1294 ## inquire_equel(rowcount = "rowcount")
1296 sprintf(argv[i], "#%d", id);
1298 id = atoi(argv[idx]);
1299 type = argv[idx - 1];
1300 if ((name = malloc(33)) == NULL)
1303 if (!strcmp(type, "LIST")) {
1304 ## repeat retrieve (name = list.#name) where list.list_id = @id
1305 ## inquire_equel(rowcount = "rowcount")
1307 strcpy(name, "???");
1308 } else if (!strcmp(type, "USER")) {
1309 ## repeat retrieve (name = users.login) where users.users_id = @id
1310 ## inquire_equel(rowcount = "rowcount")
1312 strcpy(name, "???");
1313 } else if (!strcmp(type, "NONE")) {
1314 strcpy(name, "NONE");
1316 strcpy(name, "???");
1320 if (!strcmp(q->shortname, "glin") && atoi(argv[6]) == -1) {
1321 argv[6] = realloc(argv[6], strlen(UNIQUE_GID) + 1);
1322 strcpy(argv[6], UNIQUE_GID);
1326 (*action)(q->vcnt, argv, actarg);
1328 /* free saved data */
1329 for (i = 0; i < q->vcnt; i++)
1335 return (SMS_SUCCESS);
1339 /** followup_amtl - followup for amtl and dmfl; when adding a list
1340 ** member to a maillist, make member list a maillist also
1341 ** unless list is a user-group.
1342 ** Then set_list_modtime_by_id.
1345 ** argv[0] - list_id
1346 ** argv[1] - member_type
1347 ** argv[2] - member_id
1351 followup_amtl(q, argv, cl)
1361 list_id = *(int *)argv[0];
1362 entity = cl->entity;
1365 ## range of l is list
1366 ## repeat replace l (modtime = "now", modby = @who, modwith = @entity)
1367 ## where l.#list_id = @list_id
1368 if (ingres_errno != 0) return(ingres_errno);
1370 /* if query is not amtl or if member_type is not LIST then return */
1371 if (bcmp(q->shortname, "amtl", 4) || bcmp(argv[1], "LIST", 4))
1372 return(SMS_SUCCESS);
1374 member_id = *(int *)argv[2];
1376 /* is parent list a mailing list? */
1377 ## repeat retrieve (exists = l.maillist) where l.#list_id=@list_id
1378 if (ingres_errno != 0) return(ingres_errno);
1380 return(SMS_SUCCESS);
1382 /* list is not a user-group; add list to maillist table */
1383 ## repeat replace l (maillist = 1) where l.#list_id = @member_id
1384 if (ingres_errno != 0) return(ingres_errno);
1385 return(SMS_SUCCESS);
1389 /* followup_anfq: Add allocation to nfsphys after creating quota.
1390 * argv[0] = filsys_id
1391 * argv[2] = ascii(quota)
1394 followup_anfq(q, argv, cl)
1399 ## int quota, user, fs, who;
1402 fs = *(int *)argv[0];
1403 user = *(int *)argv[1];
1404 quota = atoi(argv[2]);
1406 entity = cl->entity;
1408 ## repeat replace nq (modtime = "now", modby = @who, modwith = @entity)
1409 ## where nq.filsys_id = @fs and nq.users_id = @user
1410 if (ingres_errno != 0) return(ingres_errno);
1411 ## repeat replace nfsphys (allocated = nfsphys.allocated + @quota)
1412 ## where nfsphys.nfsphys_id = filesys.#phys_id and filesys.filsys_id = @fs
1413 if (ingres_errno != 0) return(ingres_errno);
1414 return(SMS_SUCCESS);
1421 followup_gzcl(q, sq, v, action, actarg, cl)
1422 register struct query *q;
1423 register struct save_queue *sq;
1424 register struct validate *v;
1425 register int (*action)();
1430 ## int rowcount, id;
1434 while (sq_get_data(sq, &argv)) {
1435 sms_trim_args(q->vcnt, argv);
1437 id = atoi(argv[i = q->vcnt - 2]);
1439 name = argv[i] = malloc(9);
1440 ## repeat retrieve (name = users.login) where users.users_id = @id
1441 ## inquire_equel(rowcount = "rowcount")
1443 sprintf(argv[i], "#%d", id);
1445 for (i = 1; i < 8; i+=2) {
1446 id = atoi(argv[i+1]);
1448 if ((name = argv[i+1] = malloc(33)) == NULL)
1450 if (!strcmp(argv[i], "LIST")) {
1451 ## repeat retrieve (name = list.#name) where list.list_id = @id
1452 ## inquire_equel(rowcount = "rowcount")
1454 strcpy(name, "???");
1455 } else if (!strcmp(argv[i], "USER")) {
1456 ## repeat retrieve (name = users.login) where users.users_id = @id
1457 ## inquire_equel(rowcount = "rowcount")
1459 strcpy(name, "???");
1460 } else if (!strcmp(argv[i], "NONE")) {
1461 strcpy(name, "NONE");
1463 strcpy(name, "???");
1468 (*action)(q->vcnt, argv, actarg);
1470 /* free saved data */
1471 for (i = 0; i < q->vcnt; i++)
1476 return(SMS_SUCCESS);
1483 followup_gsha(q, sq, v, action, actarg, cl)
1484 register struct query *q;
1485 register struct save_queue *sq;
1486 register struct validate *v;
1487 register int (*action)();
1492 ## int rowcount, id;
1496 while (sq_get_data(sq, &argv)) {
1497 sms_trim_args(q->vcnt, argv);
1501 name = argv[4] = malloc(9);
1502 ## repeat retrieve (name = users.login) where users.users_id = @id
1503 ## inquire_equel(rowcount = "rowcount")
1505 sprintf(argv[4], "#%d", id);
1509 if ((name = argv[2] = malloc(33)) == NULL)
1511 if (!strcmp(argv[1], "LIST")) {
1512 ## repeat retrieve (name = list.#name) where list.list_id = @id
1513 ## inquire_equel(rowcount = "rowcount")
1515 strcpy(name, "???");
1516 } else if (!strcmp(argv[1], "USER")) {
1517 ## repeat retrieve (name = users.login) where users.users_id = @id
1518 ## inquire_equel(rowcount = "rowcount")
1520 strcpy(name, "???");
1521 } else if (!strcmp(argv[1], "NONE")) {
1522 strcpy(name, "NONE");
1524 strcpy(name, "???");
1528 (*action)(q->vcnt, argv, actarg);
1530 /* free saved data */
1531 for (i = 0; i < q->vcnt; i++)
1536 return(SMS_SUCCESS);
1541 /* Special query routines */
1543 /* set_pobox - this does all of the real work.
1544 * argv = user_id, type, box
1545 * if type is POP, then box should be a machine, and its ID should be put in
1546 * pop_id. If type is SMTP, then box should be a string and its ID should
1547 * be put in box_id. If type is NONE, then box doesn't matter.
1550 int set_pobox(q, argv, cl)
1555 ## int user, id, rowcount;
1556 ## char *box, potype[9];
1559 user = *(int *)argv[0];
1561 ## repeat retrieve (id = users.pop_id, potype = users.#potype)
1562 ## where users.users_id = @user
1563 if (ingres_errno != 0) return(ingres_errno);
1564 if (!strcmp(strtrim(potype), "POP"))
1565 set_pop_usage(id, -1);
1567 if (!strcmp(argv[1], "POP")) {
1568 ## repeat retrieve (id=machine.mach_id) where machine.name=uppercase(@box)
1569 if (ingres_errno != 0) return(ingres_errno);
1570 ## inquire_equel(rowcount = "rowcount")
1572 return(SMS_MACHINE);
1573 ## repeat replace users (#potype = "POP", pop_id = @id)
1574 ## where users.users_id = @user
1575 if (ingres_errno != 0) return(ingres_errno);
1576 set_pop_usage(id, 1);
1577 } else if (!strcmp(argv[1], "SMTP")) {
1578 ## range of s is strings
1579 ## repeat retrieve (id = s.string_id) where s.string = @box
1580 if (ingres_errno != 0) return(ingres_errno);
1581 ## inquire_equel (rowcount = "rowcount")
1582 if (rowcount == 0) {
1583 ## range of v is values
1584 ## repeat retrieve (id = v.value) where v.name = "strings_id"
1585 if (ingres_errno != 0) return(ingres_errno);
1587 ## repeat replace v (value = @id) where v.name = "strings_id"
1588 if (ingres_errno != 0) return(ingres_errno);
1589 ## append to strings (string_id = id, string = box)
1590 if (ingres_errno != 0) return(ingres_errno);
1592 ## repeat replace users (#potype = "SMTP", box_id = @id)
1593 ## where users.users_id = @user
1594 if (ingres_errno != 0) return(ingres_errno);
1595 } else /* argv[1] == "NONE" */ {
1596 ## repeat replace users (#potype = "NONE") where users.users_id = @user
1597 if (ingres_errno != 0) return(ingres_errno);
1600 set_pobox_modtime(q, argv, cl);
1601 ## repeat replace tblstats (updates = tblstats.updates + 1, modtime = "now")
1602 ## where tblstats.#table = "users"
1603 if (ingres_errno != 0) return(ingres_errno);
1604 return(SMS_SUCCESS);
1608 /* get_list_info: passed a wildcard list name, returns lots of stuff about
1609 * each list. This is tricky: first build a queue of all requested
1610 * data. Rest of processing consists of fixing gid, ace_name, and modby.
1613 get_list_info(q, aargv, cl, action, actarg)
1614 register struct query *q;
1617 register int (*action)();
1620 char *argv[13], *malloc(), *realloc();
1621 ## char *name, acl_type[9], listname[33], active[5], public[5], hidden[5];
1622 ## char maillist[5], group[5], gid[6], acl_name[33], desc[256], modtime[27];
1623 ## char modby[9], modwith[9];
1624 ## int id, rowcount, acl_id, hid, modby_id;
1626 struct save_queue *sq, *sq_create();
1628 returned = rowcount = 0;
1632 ## range of l is list
1633 ## repeat retrieve (id = l.list_id) where l.#name = @name {
1634 sq_save_data(sq, id);
1638 return(SMS_NO_MATCH);
1640 argv[0] = listname; argv[1] = active; argv[2] = public; argv[3] = hidden;
1641 argv[4] = maillist; argv[5] = group; argv[6] = gid; argv[7] = acl_type;
1642 argv[8] = acl_name; argv[9] = desc; argv[10] = modtime; argv[11] = modby;
1645 while (sq_get_data(sq, &id)) {
1649 ## repeat retrieve (listname = l.#name, active = text(l.#active),
1650 ## public = text(l.#public), hidden = text(l.#hidden),
1651 ## hid = l.#hidden, maillist = text(l.#maillist),
1652 ## group = text(l.#group), gid = text(l.#gid),
1653 ## acl_type = trim(l.#acl_type), acl_id = l.#acl_id,
1654 ## desc = l.#desc, modtime = l.#modtime, modby_id = l.#modby,
1655 ## modwith =l.#modwith)
1656 ## where l.list_id = @id
1658 if (atoi(gid) == -1)
1659 argv[6] = UNIQUE_GID;
1661 if (!strcmp(acl_type, "LIST")) {
1662 ## repeat retrieve (acl_name = l.#name) where l.list_id = @acl_id
1663 ## inquire_equel(rowcount = "rowcount")
1665 strcpy(acl_name, "???");
1666 } else if (!strcmp(acl_type, "USER")) {
1667 ## repeat retrieve (acl_name = users.#login)
1668 ## where users.users_id = @acl_id
1669 ## inquire_equel(rowcount = "rowcount")
1671 strcpy(acl_name, "???");
1672 } else if (!strcmp(acl_type, "NONE")) {
1673 strcpy(acl_name, "NONE");
1675 strcpy(acl_name, "???");
1677 ## repeat retrieve (modby = users.login) where users.users_id = @modby_id
1678 ## inquire_equel(rowcount = "rowcount")
1680 sprintf(modby, "#%d", id);
1682 sms_trim_args(q->vcnt, argv);
1684 (*action)(q->vcnt, argv, actarg);
1689 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
1690 ## where tblstats.#table = "list"
1692 return (SMS_SUCCESS);
1696 /* get_ace_use - given a type and a name, return a type and a name.
1697 * The ace_type is one of "LIST", "USER", "RLIST", or "RUSER" in argv[0],
1698 * and argv[1] will contain the ID of the entity in question. The R*
1699 * types mean to recursively look at every containing list, not just
1700 * when the object in question is a direct member. On return, the
1701 * usage type will be one of LIST, SERVICE, FILESYS, QUOTA, QUERY, or ZEPHYR.
1704 int get_ace_use(q, argv, cl, action, actarg)
1713 ## int aid, listid, id;
1714 struct save_queue *sq, *sq_create();
1717 aid = *(int *)argv[1];
1718 if (!strcmp(atype, "LIST") || !strcmp(atype, "USER")) {
1719 return(get_ace_internal(atype, aid, action, actarg));
1723 if (!strcmp(atype, "RLIST")) {
1724 sq_save_data(sq, aid);
1725 /* get all the list_id's of containing lists */
1726 ## range of m is members
1727 while (sq_get_data(sq, &id)) {
1728 ## repeat retrieve (listid = m.list_id)
1729 ## where m.member_type = "LIST" and m.member_id = @id {
1730 sq_save_unique_data(sq, listid);
1733 /* now process each one */
1734 while (sq_get_data(sq, &id)) {
1735 if (get_ace_internal("LIST", id, action, actarg) == SMS_SUCCESS)
1740 if (!strcmp(atype, "RUSER")) {
1741 ## range of m is members
1742 ## repeat retrieve (listid = m.list_id)
1743 ## where m.member_type = "USER" and m.member_id = @aid {
1744 sq_save_data(sq, listid);
1746 /* get all the list_id's of containing lists */
1747 while (sq_get_data(sq, &id)) {
1748 ## repeat retrieve (listid = m.list_id)
1749 ## where m.member_type = "LIST" and m.member_id = @id {
1750 sq_save_unique_data(sq, listid);
1753 /* now process each one */
1754 while (sq_get_data(sq, &id)) {
1755 if (get_ace_internal("LIST", id, action, actarg) == SMS_SUCCESS)
1758 if (get_ace_internal("USER", aid, action, actarg) == SMS_SUCCESS)
1763 if (!found) return(SMS_NO_MATCH);
1764 return(SMS_SUCCESS);
1768 /* This looks up a single list or user for ace use. atype must be "USER"
1769 * or "LIST", and aid is the ID of the corresponding object. This is used
1770 * by get_ace_use above.
1773 ##get_ace_internal(atype, aid, action, actarg)
1784 if (!strcmp(atype, "LIST")) {
1785 rargv[0] = "FILESYS";
1786 ## repeat retrieve (name = filesys.label)
1787 ## where filesys.owners = @aid {
1788 (*action)(2, rargv, actarg);
1793 ## repeat retrieve (name = capacls.capability)
1794 ## where capacls.list_id = @aid {
1795 (*action)(2, rargv, actarg);
1798 } else if (!strcmp(atype, "USER")) {
1799 rargv[0] = "FILESYS";
1800 ## repeat retrieve (name = filesys.label)
1801 ## where filesys.owner = @aid {
1802 (*action)(2, rargv, actarg);
1808 ## repeat retrieve (name = list.#name)
1809 ## where list.acl_type = @atype and list.acl_id = @aid {
1810 (*action)(2, rargv, actarg);
1814 rargv[0] = "SERVICE";
1815 ## repeat retrieve (name = servers.#name)
1816 ## where servers.acl_type = @atype and servers.acl_id = @aid {
1817 (*action)(2, rargv, actarg);
1821 rargv[0] = "HOSTACCESS";
1822 ## repeat retrieve (name = machine.#name)
1823 ## where machine.mach_id = hostaccess.mach_id and
1824 ## hostaccess.acl_type = @atype and hostaccess.acl_id = @aid {
1825 (*action)(2, rargv, actarg);
1828 rargv[0] = "ZEPHYR";
1829 ## repeat retrieve (name = zephyr.class)
1830 ## where zephyr.xmt_type = @atype and zephyr.xmt_id = @aid or
1831 ## zephyr.sub_type = @atype and zephyr.sub_id = @aid or
1832 ## zephyr.iws_type = @atype and zephyr.iws_id = @aid or
1833 ## zephyr.iui_type = @atype and zephyr.iui_id = @aid {
1834 (*action)(2, rargv, actarg);
1838 if (!found) return(SMS_NO_MATCH);
1839 return(SMS_SUCCESS);
1843 /* get_lists_of_member - given a type and a name, return the name and flags
1844 * of all of the lists of the given member. The member_type is one of
1845 * "LIST", "USER", "STRING", "RLIST", "RUSER", or "RSTRING" in argv[0],
1846 * and argv[1] will contain the ID of the entity in question. The R*
1847 * types mean to recursively look at every containing list, not just
1848 * when the object in question is a direct member.
1851 int get_lists_of_member(q, argv, cl, action, actarg)
1860 ## int aid, listid, id;
1861 struct save_queue *sq, *sq_create();
1864 aid = *(int *)argv[1];
1865 if (!strcmp(atype, "LIST") ||
1866 !strcmp(atype, "USER") ||
1867 !strcmp(atype, "STRING")) {
1868 return(glom_internal(atype, aid, action, actarg));
1872 if (!strcmp(atype, "RLIST")) {
1873 sq_save_data(sq, aid);
1874 /* get all the list_id's of containing lists */
1875 ## range of m is members
1876 while (sq_get_data(sq, &id)) {
1877 ## repeat retrieve (listid = m.list_id)
1878 ## where m.member_type = "LIST" and m.member_id = @id {
1879 sq_save_unique_data(sq, listid);
1882 /* now process each one */
1883 while (sq_get_data(sq, &id)) {
1884 if (glom_internal("LIST", id, action, actarg) == SMS_SUCCESS)
1889 if (!strcmp(atype, "RUSER")) {
1890 ## range of m is members
1891 ## repeat retrieve (listid = m.list_id)
1892 ## where m.member_type = "USER" and m.member_id = @aid {
1893 sq_save_data(sq, listid);
1895 /* get all the list_id's of containing lists */
1896 while (sq_get_data(sq, &id)) {
1897 ## repeat retrieve (listid = m.list_id)
1898 ## where m.member_type = "LIST" and m.member_id = @id {
1899 sq_save_unique_data(sq, listid);
1902 /* now process each one */
1903 while (sq_get_data(sq, &id)) {
1904 if (glom_internal("LIST", id, action, actarg) == SMS_SUCCESS)
1907 if (glom_internal("USER", aid, action, actarg) == SMS_SUCCESS)
1911 if (!strcmp(atype, "RSTRING")) {
1912 ## range of m is members
1913 ## repeat retrieve (listid = m.list_id)
1914 ## where m.member_type = "STRING" and m.member_id = @aid {
1915 sq_save_data(sq, listid);
1917 /* get all the list_id's of containing lists */
1918 while (sq_get_data(sq, &id)) {
1919 ## repeat retrieve (listid = m.list_id)
1920 ## where m.member_type = "LIST" and m.member_id = @id {
1921 sq_save_unique_data(sq, listid);
1924 /* now process each one */
1925 while (sq_get_data(sq, &id)) {
1926 if (glom_internal("LIST", id, action, actarg) == SMS_SUCCESS)
1929 if (glom_internal("STRING", aid, action, actarg) == SMS_SUCCESS)
1933 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
1934 ## where tblstats.#table = "members"
1936 if (!found) return(SMS_NO_MATCH);
1937 return(SMS_SUCCESS);
1941 /* This looks up a single list, user, or string as a member. atype must be
1942 * "USER", "LIST", or "STRING" and aid is the ID of the corresponding object.
1943 * This is used by get_lists_of_members above.
1946 ##glom_internal(atype, aid, action, actarg)
1954 ## char name[33], active[5], public[5], hidden[5], maillist[5], group[5];
1960 rargv[4] = maillist;
1962 ## repeat retrieve (name = list.#name, active = text(list.#active),
1963 ## public = text(list.#public), hidden = text(list.#hidden),
1964 ## maillist = text(list.#maillist), group = text(list.#group))
1965 ## where list.list_id = m.list_id and
1966 ## m.member_type = @atype and m.member_id = @aid {
1967 (*action)(6, rargv, actarg);
1971 if (!found) return(SMS_NO_MATCH);
1972 return(SMS_SUCCESS);
1976 /* qualified_get_lists: passed "TRUE", "FALSE", or "DONTCARE" for each of
1977 * the five flags associated with each list. It will return the name of
1978 * each list that meets the quailifications. It does this by building a
1979 * where clause based on the arguments, then doing a retrieve.
1982 static char *lflags[5] = { "active", "public", "hidden", "maillist", "group" };
1984 int qualified_get_lists(q, argv, cl, action, actarg)
1991 return(qualified_get(q, argv, action, actarg, "l.list_id != 0",
1992 "l", "name", lflags));
1996 /** get_members_of_list - optimized query for retrieval of list members
1999 ** argv[0] - list_id
2002 ** - retrieve USER members, then LIST members, then STRING members
2005 get_members_of_list(q, argv, cl, action, actarg)
2013 ## char member_name[129];
2016 list_id = *(int *)argv[0];
2018 targv[1] = member_name;
2020 ## range of m is members
2021 ## repeat retrieve (member_name = users.login)
2022 ## where m.#list_id = @list_id and m.member_type = "USER"
2023 ## and m.member_id = users.users_id
2024 ## sort by #member_name
2026 (*action)(2, targv, actarg);
2030 ## repeat retrieve (member_name = list.name)
2031 ## where m.#list_id = @list_id and m.member_type = "LIST"
2032 ## and m.member_id = list.#list_id
2033 ## sort by #member_name
2035 (*action)(2, targv, actarg);
2038 targv[0] = "STRING";
2039 ## repeat retrieve (member_name = strings.string)
2040 ## where m.#list_id = @list_id and m.member_type = "STRING"
2041 ## and m.member_id = strings.string_id
2042 ## sort by #member_name
2044 (*action)(2, targv, actarg);
2047 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
2048 ## where tblstats.#table = "members"
2049 return(SMS_SUCCESS);
2053 /* count_members_of_list: this is a simple query, but it cannot be done
2054 * through the dispatch table.
2057 int count_members_of_list(q, argv, cl, action, actarg)
2064 ## int list, ct = 0;
2065 char *rargv[1], countbuf[5];
2067 list = *(int *)argv[0];
2068 rargv[0] = countbuf;
2069 ## repeat retrieve (ct = count(members.list_id where members.list_id = @list))
2070 sprintf(countbuf, "%d", ct);
2071 (*action)(1, rargv, actarg);
2072 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
2073 ## where tblstats.#table = "members"
2074 return(SMS_SUCCESS);
2078 /* qualified_get_server: passed "TRUE", "FALSE", or "DONTCARE" for each of
2079 * the three flags associated with each service. It will return the name of
2080 * each service that meets the quailifications. It does this by building a
2081 * where clause based on the arguments, then doing a retrieve.
2084 static char *sflags[3] = { "enable", "inprogress", "harderror" };
2086 int qualified_get_server(q, argv, cl, action, actarg)
2093 return(qualified_get(q, argv, action, actarg, "s.name != \"\"",
2094 "s", "name", sflags));
2098 /* generic qualified get routine, used by qualified_get_lists,
2099 * qualified_get_server, and qualified_get_serverhost.
2101 * start - a simple where clause, must not be empty
2102 * range - the name of the range variable
2103 * field - the field to return
2104 * flags - an array of strings, names of the flag variables
2107 int qualified_get(q, argv, action, actarg, start, range, field, flags)
2117 ## char name[33], qual[256], *rvar, *rtbl, *rfield;
2118 char *rargv[1], buf[32];
2121 strcpy(qual, start);
2122 for (i = 0; i < q->argc; i++) {
2123 if (!strcmp(argv[i], "TRUE")) {
2124 sprintf(buf, " and %s.%s != 0", range, flags[i]);
2125 (void) strcat(qual, buf);
2126 } else if (!strcmp(argv[i], "FALSE")) {
2127 sprintf(buf, " and %s.%s = 0", range, flags[i]);
2128 (void) strcat(qual, buf);
2136 ## range of rvar is rtbl
2137 ## retrieve (name = rvar.rfield) where qual {
2138 (*action)(1, rargv, actarg);
2140 ## inquire_equel(rowcount = "rowcount")
2141 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
2142 ## where tblstats.#table = @rtbl
2144 return(SMS_NO_MATCH);
2145 return(SMS_SUCCESS);
2149 /* qualified_get_serverhost: passed "TRUE", "FALSE", or "DONTCARE" for each of
2150 * the five flags associated with each serverhost. It will return the name of
2151 * each service and host that meets the quailifications. It does this by
2152 * building a where clause based on the arguments, then doing a retrieve.
2155 static char *shflags[6] = { "service", "enable", "override", "success",
2156 "inprogress", "hosterror" };
2158 int qualified_get_serverhost(q, argv, cl, action, actarg)
2165 ## char sname[33], mname[33], qual[256];
2166 char *rargv[2], buf[32];
2169 sprintf(qual, "machine.mach_id = sh.mach_id and sh.service = uppercase(\"%s\")",
2171 for (i = 1; i < q->argc; i++) {
2172 if (!strcmp(argv[i], "TRUE")) {
2173 sprintf(buf, " and sh.%s != 0", shflags[i]);
2175 } else if (!strcmp(argv[i], "FALSE")) {
2176 sprintf(buf, " and sh.%s = 0", shflags[i]);
2183 ## range of sh is serverhosts
2184 ## retrieve (sname = sh.service, mname = machine.name) where qual {
2185 (*action)(2, rargv, actarg);
2187 ## inquire_equel(rowcount = "rowcount")
2188 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
2189 ## where tblstats.#table = "serverhosts"
2191 return(SMS_NO_MATCH);
2192 return(SMS_SUCCESS);
2196 /* register_user - change user's login name and allocate a pobox, group,
2197 * filesystem, and quota for them. The user's status must start out as 0,
2198 * and is left as 2. Arguments are: user's UID, new login name, and user's
2199 * type for filesystem allocation (SMS_FS_STUDENT, SMS_FS_FACULTY,
2200 * SMS_FS_STAFF, SMS_FS_MISC).
2203 register_user(q, argv, cl)
2208 ## char *login, dir[65], *entity, *directory, machname[33];
2209 ## int who, rowcount, mid, uid, users_id, flag, utype, nid, list_id, quota;
2210 ## int size, alloc, pid, m_id;
2213 entity = cl->entity;
2216 uid = atoi(argv[0]);
2218 utype = atoi(argv[2]);
2220 ## range of u is users
2221 ## range of l is list
2222 ## range of sh is serverhosts
2223 ## range of n is nfsphys
2224 ## range of m is machine
2227 ## repeat retrieve (users_id = u.#users_id)
2228 ## where u.#uid = @uid and u.status = 0
2229 if (ingres_errno != 0) return(ingres_errno);
2230 ## inquire_equel(rowcount = "rowcount");
2232 return(SMS_NO_MATCH);
2234 return(SMS_NOT_UNIQUE);
2236 /* check new login name */
2237 ## repeat retrieve (flag = any(u.#login where u.#login = @login))
2240 ## repeat retrieve (flag = any(l.#name where l.#name = @login))
2243 ## repeat retrieve (flag = any(filesys.#name where filesys.#name = @login))
2246 if (ingres_errno != 0) return(ingres_errno);
2247 com_err(whoami, 0, "new login name OK");
2249 /* choose place for pobox, put in mid */
2250 ## repeat retrieve (mid = sh.mach_id, machname = m.name)
2251 ## where sh.service = "POP" and m.mach_id = sh.mach_id and
2252 ## sh.value2 - sh.value1 = max(sh.value2-sh.value1 where sh.service="POP")
2253 if (ingres_errno != 0) return(ingres_errno);
2254 ## inquire_equel(rowcount = "rowcount");
2256 return(SMS_NO_POBOX);
2258 /* change login name, set pobox */
2259 ## repeat replace u (#login = @login, status = 2, modtime = "now",
2260 ## modby = @who, modwith = @entity, potype="POP",
2261 ## pop_id = @mid, pmodtime="now", pmodby=@who,
2262 ## pmodwith=@entity)
2263 ## where u.#users_id = @users_id
2264 if (ingres_errno != 0) return(ingres_errno);
2265 ## inquire_equel(rowcount = "rowcount");
2267 return(SMS_INTERNAL);
2268 set_pop_usage(mid, 1);
2269 com_err(whoami, 0, "set login name to %s and pobox to %s", login,
2272 /* create group list */
2273 if (set_next_object_id("gid", "list"))
2275 if (set_next_object_id("list_id", "list"))
2277 ## repeat retrieve (list_id = values.value) where values.name = "list_id"
2278 if (ingres_errno != 0) return(ingres_errno);
2279 ## inquire_equel(rowcount = "rowcount");
2281 return(SMS_INTERNAL);
2282 ## repeat append list (name = @login, #list_id = @list_id, active = 1,
2283 ## public = 0, hidden = 0, maillist = 0, group = 1,
2284 ## #gid = values.value, desc = "User Group",
2285 ## acl_type = "USER", acl_id = @users_id, modtime = "now",
2286 ## modby = @who, modwith = @entity)
2287 ## where values.name = "gid"
2288 if (ingres_errno != 0) return(ingres_errno);
2289 ## inquire_equel(rowcount = "rowcount");
2291 return(SMS_INTERNAL);
2292 ## repeat append members (#list_id = @list_id, member_type = "USER",
2293 ## member_id = @users_id)
2294 if (ingres_errno != 0) return(ingres_errno);
2295 ## inquire_equel(rowcount = "rowcount");
2297 return(SMS_INTERNAL);
2298 com_err(whoami, 0, "group list created");
2300 /* decide where to put filesystem */
2303 ## repeat retrieve (mid = n.mach_id, dir = trim(n.#dir), nid = n.nfsphys_id,
2304 ## flag = n.status, size = n.#size, alloc = n.allocated) {
2305 if ((flag & utype) && (size != 0) && (size - alloc > maxsize)) {
2306 maxsize = size - alloc;
2309 directory = strsave(dir);
2314 if (ingres_errno != 0) return(ingres_errno);
2316 return(SMS_NO_FILESYS);
2318 /* create filesystem */
2319 if (set_next_object_id("filsys_id", "filesys"))
2321 ## repeat append filesys (filsys_id = values.value, phys_id = @pid,
2322 ## label = @login, type = "NFS", mach_id = @m_id,
2323 ## name = @directory + "/" + @login,
2324 ## mount = "/mit/" + @login,
2325 ## access = "w", comments = "User Locker",
2326 ## owner = @users_id, owners = @list_id, createflg = 1,
2327 ## lockertype = "HOMEDIR", modtime = "now",
2328 ## modby = @who, modwith = @entity)
2329 ## where values.name = "filsys_id"
2330 if (ingres_errno != 0) return(ingres_errno);
2331 ## inquire_equel(rowcount = "rowcount");
2333 return(SMS_INTERNAL);
2334 com_err(whoami, 0, "filesys created on mach %d in %s/%s", m_id,
2338 ## repeat retrieve (quota = values.value) where values.name = "def_quota"
2339 if (ingres_errno != 0) return(ingres_errno);
2340 ## inquire_equel(rowcount = "rowcount");
2342 return(SMS_NO_QUOTA);
2343 ## repeat append nfsquota (#users_id = @users_id, filsys_id = values.value,
2344 ## #quota = @quota, phys_id = @pid, modtime = "now",
2345 ## modby = @who, modwith = @entity)
2346 ## where values.name = "filsys_id"
2347 if (ingres_errno != 0) return(ingres_errno);
2348 ## inquire_equel(rowcount = "rowcount");
2350 return(SMS_INTERNAL);
2351 ## repeat replace nfsphys (allocated = nfsphys.allocated + @quota)
2352 ## where nfsphys.nfsphys_id = filesys.#phys_id and
2353 ## filesys.filsys_id = values.value and values.name = "filsys_id"
2354 if (ingres_errno != 0) return(ingres_errno);
2355 ## inquire_equel(rowcount = "rowcount");
2357 return(SMS_INTERNAL);
2358 com_err(whoami, 0, "quota of %d assigned", quota);
2360 ## repeat replace tblstats (updates = tblstats.updates + 1, modtime = "now")
2361 ## where tblstats.table = "users"
2362 if (ingres_errno != 0) return(ingres_errno);
2363 ## repeat replace tblstats (appends = tblstats.appends + 1, modtime = "now")
2364 ## where tblstats.table = "list" or tblstats.table = "filesys" or
2365 ## tblstats.table = "nfsquota"
2366 if (ingres_errno != 0) return(ingres_errno);
2367 return(SMS_SUCCESS);
2372 /** set_pop_usage - incr/decr usage count for pop server in serverhosts talbe
2376 ** delta (will be +/- 1)
2379 ** - incr/decr value field in serverhosts table for pop/mach_id
2383 static int set_pop_usage(id, count)
2387 ## int mach_id = id;
2390 ## range of sh is serverhosts
2391 ## repeat replace sh (value1 = sh.value1 + @n)
2392 ## where sh.service = "POP" and sh.#mach_id = @mach_id
2393 if (ingres_errno != 0) return(ingres_errno);
2395 return(SMS_SUCCESS);
2400 /* Validation Routines */
2402 validate_row(q, argv, v)
2403 register struct query *q;
2405 register struct validate *v;
2413 /* build where clause */
2414 build_qual(v->qual, v->argc, argv, qual);
2416 /* setup ingres variables */
2421 if (log_flags & LOG_VALID)
2422 /* tell the logfile what we're doing */
2423 com_err(whoami, 0, "validating row: %s", qual);
2425 /* look for the record */
2426 ## range of rvar is table
2427 ## retrieve (rowcount = count(rvar.name where qual))
2428 if (rowcount == 0) return(SMS_NO_MATCH);
2429 if (rowcount > 1) return(SMS_NOT_UNIQUE);
2433 validate_fields(q, argv, vo, n)
2435 register char *argv[];
2436 register struct valobj *vo;
2439 register int status;
2444 if (log_flags & LOG_VALID)
2445 com_err(whoami, 0, "validating %s in %s: %s",
2446 vo->namefield, vo->table, argv[vo->index]);
2447 status = validate_name(argv, vo);
2451 if (log_flags & LOG_VALID)
2452 com_err(whoami, 0, "validating %s in %s: %s",
2453 vo->idfield, vo->table, argv[vo->index]);
2454 status = validate_id(argv, vo);
2458 if (log_flags & LOG_VALID)
2459 com_err(whoami, 0, "validating date: %s", argv[vo->index]);
2460 status = validate_date(argv, vo);
2464 if (log_flags & LOG_VALID)
2465 com_err(whoami, 0, "validating %s type: %s",
2466 vo->table, argv[vo->index]);
2467 status = validate_type(argv, vo);
2471 if (log_flags & LOG_VALID)
2472 com_err(whoami, 0, "validating typed data (%s): %s",
2473 argv[vo->index - 1], argv[vo->index]);
2474 status = validate_typedata(q, argv, vo);
2478 if (log_flags & LOG_VALID)
2479 com_err(whoami, 0, "validating rename %s in %s",
2480 argv[vo->index], vo->table);
2481 status = validate_rename(argv, vo);
2485 if (log_flags & LOG_VALID)
2486 com_err(whoami, 0, "validating chars: %s", argv[vo->index]);
2487 status = validate_chars(argv[vo->index]);
2491 status = SMS_EXISTS;
2496 if (status != SMS_EXISTS) return(status);
2500 return(SMS_SUCCESS);
2504 /* validate_chars: verify that there are no illegal characters in
2505 * the string. Legal characters are printing chars other than
2506 * ", *, ?, \, [ and ].
2508 static int illegalchars[] = {
2509 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
2510 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
2511 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
2512 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
2513 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ - O */
2514 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* P - _ */
2515 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
2516 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
2517 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2518 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2519 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2520 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2521 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2522 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2523 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2524 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2531 if (illegalchars[*s++])
2532 return(SMS_BAD_CHAR);
2537 validate_id(argv, vo)
2539 register struct valobj *vo;
2549 name = argv[vo->index];
2551 /* minor kludge to upcasify machine names */
2552 if (!strcmp(table, "machine"))
2553 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
2554 namefield = vo->namefield;
2555 idfield = vo->idfield;
2556 if (!strcmp(namefield, "uid")) {
2557 ## retrieve (id = table.idfield) where table.namefield = int4(name)
2558 ## inquire_equel (rowcount = "rowcount")
2560 ## retrieve (id = table.idfield) where table.namefield = name
2561 ## inquire_equel (rowcount = "rowcount")
2563 if (rowcount != 1) return(vo->error);
2564 *(int *)argv[vo->index] = id;
2568 validate_name(argv, vo)
2570 register struct valobj *vo;
2578 name = argv[vo->index];
2580 namefield = vo->namefield;
2581 if (!strcmp(table, "servers") && !strcmp(namefield, "name")) {
2582 for (c = name; *c; c++)
2586 ## retrieve (rowcount = countu(table.namefield
2587 ## where table.namefield = name))
2588 return ((rowcount == 1) ? SMS_EXISTS : vo->error);
2591 validate_date(argv, vo)
2599 idate = argv[vo->index];
2601 ## retrieve (dd = interval("years", date(idate) - date("today")))
2602 ## inquire_equel (errorno = "errorno")
2603 if (errorno != 0 || dd > 5.0) return(SMS_DATE);
2608 validate_rename(argv, vo)
2612 ## char *name, *table, *namefield, *idfield;
2616 c = name = argv[vo->index];
2618 if (illegalchars[*c++])
2619 return(SMS_BAD_CHAR);
2621 /* minor kludge to upcasify machine names */
2622 if (!strcmp(table, "machine"))
2623 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
2624 namefield = vo->namefield;
2625 idfield = vo->idfield;
2628 if (!strcmp(argv[vo->index], argv[vo->index - 1]))
2630 ## retrieve (id = any(table.namefield where table.namefield = name))
2636 ## retrieve (id = table.idfield) where table.namefield = name
2637 if (id == -1 || id == *(int *)argv[vo->index - 1])
2644 validate_type(argv, vo)
2646 register struct valobj *vo;
2653 typename = vo->table;
2654 c = value = argv[vo->index];
2656 if (illegalchars[*c++])
2657 return(SMS_BAD_CHAR);
2659 /* uppercase type fields */
2660 for (c = value; *c; c++) if (islower(*c)) *c = toupper(*c);
2662 ## range of a is alias
2663 ## repeat retrieve (exists = any(a.trans where a.name = @typename and
2664 ## a.type = "TYPE" and
2665 ## a.trans = @value))
2666 return (exists ? SMS_EXISTS : vo->error);
2669 /* validate member or type-specific data field */
2671 validate_typedata(q, argv, vo)
2672 register struct query *q;
2673 register char *argv[];
2674 register struct valobj *vo;
2677 ## char *field_type;
2678 ## char data_type[129];
2684 /* get named object */
2685 name = argv[vo->index];
2687 /* get field type string (known to be at index-1) */
2688 field_type = argv[vo->index-1];
2690 /* get corresponding data type associated with field type name */
2691 ## repeat retrieve (data_type = alias.trans)
2692 ## where alias.#name = @field_type and alias.type = "TYPEDATA"
2693 ## inquire_equel (rowcount = "rowcount")
2694 if (rowcount != 1) return(SMS_TYPE);
2696 /* now retrieve the record id corresponding to the named object */
2697 if (index(data_type, ' '))
2698 *index(data_type, ' ') = 0;
2699 if (!strcmp(data_type, "user")) {
2701 ## repeat retrieve (id = users.users_id) where users.login = @name
2702 ## inquire_equel (rowcount = "rowcount")
2703 if (rowcount != 1) return(SMS_USER);
2705 } else if (!strcmp(data_type, "list")) {
2707 ## repeat retrieve (id = list.list_id) where list.#name = @name
2708 ## inquire_equel (rowcount = "rowcount")
2709 if (rowcount != 1) {
2710 /* if idfield is non-zero, then if argv[0] matches the string
2711 * that we're trying to resolve, we should get the value of
2712 * values.[idfield] for the id.
2714 if (vo->idfield && !strcmp(argv[0], argv[vo->index])) {
2715 set_next_object_id(q->validate->object_id, q->rtable);
2717 ## repeat retrieve (id = values.value) where values.#name = @name
2718 ## inquire_equel(rowcount = "rowcount")
2719 if (rowcount != 1) return(SMS_LIST);
2723 } else if (!strcmp(data_type, "machine")) {
2725 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
2726 ## repeat retrieve (id = machine.mach_id) where machine.#name = @name
2727 ## inquire_equel (rowcount = "rowcount")
2728 if (rowcount != 1) return(SMS_MACHINE);
2730 } else if (!strcmp(data_type, "string")) {
2732 ## range of s is strings
2733 ## repeat retrieve (id = s.string_id) where s.string = @name
2734 ## inquire_equel (rowcount = "rowcount")
2735 if (rowcount == 0) {
2736 if (q->type != APPEND) return(SMS_STRING);
2737 ## range of v is values
2738 ## retrieve (id = v.value) where v.#name = "strings_id"
2740 ## replace v (value = id) where v.#name = "strings_id"
2741 ## append to strings (string_id = id, string = name)
2743 } else if (!strcmp(data_type, "none")) {
2749 /* now set value in argv */
2750 *(int *)argv[vo->index] = id;
2752 return (SMS_EXISTS);
2756 /* This looks up a login name and returns the SMS internal ID. It is used
2757 * by authenticate to put the users_id in the client structure.
2760 int get_users_id(name)
2763 ## int id, rowcount;
2768 ## range of u is users
2769 ## repeat retrieve (id = u.#users_id) where u.#login = @login
2770 ## inquire_equel (rowcount = "rowcount")
2779 /* Check the database at startup time. For now this just resets the
2780 * inprogress flags that the DCM uses.
2783 sanity_check_database()