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 "mr_server.h"
20 EXEC SQL INCLUDE sqlca;
22 extern char *whoami, *strsave();
23 extern int ingres_errno, mr_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)
58 EXEC SQL BEGIN DECLARE SECTION;
61 EXEC SQL END DECLARE SECTION;
63 build_qual(q->qual, q->argc, argv, qual);
65 EXEC SQL SELECT users_id INTO :id FROM users WHERE qual;
67 if (sqlca.sqlcode < 0 || sqlca.sqlerrd[2] != 1 || id != cl->users_id)
76 /* access_list - check access for most list operations
78 * Inputs: argv[0] - list_id
80 * argv[2] - member ID (only for queries "amtl" and "dmfl")
81 * argv[7] - group IID (only for query "ulis")
84 * - check that client is a member of the access control list
85 * - OR, if the query is add_member_to_list or delete_member_from_list
86 * and the list is public, allow access if client = member
89 access_list(q, argv, cl)
94 EXEC SQL BEGIN DECLARE SECTION;
95 int list_id, acl_id, flags, rowcount, gid;
97 EXEC SQL END DECLARE SECTION;
99 int client_id, status;
101 list_id = *(int *)argv[0];
102 EXEC SQL SELECT acl_id, acl_type, gid, public
103 INTO :acl_id, :acl_type, :gid, :flags
105 WHERE list_id = :list_id;
106 if (sqlca.sqlcode < 0 || sqlca.sqlerrd[2] != 1)
109 /* parse client structure */
110 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
113 /* if amtl or dmfl and list is public allow client to add or delete self */
114 if (((!strcmp("amtl", q->shortname) && flags) ||
115 (!strcmp("dmfl", q->shortname))) &&
116 (!strcmp("USER", argv[1]))) {
117 if (*(int *)argv[2] == client_id) return(MR_SUCCESS);
118 /* if update_list, don't allow them to change the GID */
119 } else if (!strcmp("ulis", q->shortname)) {
120 if ((!strcmp(argv[7], UNIQUE_GID) && (gid != -1)) ||
121 (strcmp(argv[7], UNIQUE_GID) && (gid != atoi(argv[7]))))
125 /* check for client in access control list */
126 status = find_member(acl_type, acl_id, client_type, client_id, 0);
127 if (!status) return(MR_PERM);
133 /* access_visible_list - allow access to list only if it is not hidden,
134 * or if the client is on the ACL
136 * Inputs: argv[0] - list_id
137 * cl - client identifier
140 access_visible_list(q, argv, cl)
145 EXEC SQL BEGIN DECLARE SECTION;
146 int list_id, acl_id, flags, rowcount;
148 EXEC SQL END DECLARE SECTION;
150 int client_id, status;
152 list_id = *(int *)argv[0];
153 EXEC SQL SELECT hidden, acl_id, acl_type
154 INTO :flags, :acl_id, :acl_type
156 WHERE list_id = :list_id;
157 if (sqlca.sqlcode < 0 || sqlca.sqlerrd[2] != 1)
163 /* parse client structure */
164 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
167 /* check for client in access control list */
168 status = find_member(acl_type, acl_id, client_type, client_id, 0);
176 /* access_vis_list_by_name - allow access to list only if it is not hidden,
177 * or if the client is on the ACL
179 * Inputs: argv[0] - list name
180 * cl - client identifier
183 access_vis_list_by_name(q, argv, cl)
188 EXEC SQL BEGIN DECLARE SECTION;
189 int acl_id, flags, rowcount;
190 char acl_type[9], *listname;
191 EXEC SQL END DECLARE SECTION;
193 int client_id, status;
196 EXEC SQL SELECT hidden, acl_id, acl_type
197 INTO :flags, :acl_id, :acl_type
199 WHERE name = :listname;
200 if (sqlca.sqlerrd[2] > 1) return(MR_WILDCARD);
201 if (sqlca.sqlcode == 100) return(MR_NO_MATCH);
205 /* parse client structure */
206 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
209 /* check for client in access control list */
210 status = find_member(acl_type, acl_id, client_type, client_id, 0);
218 /* access_member - allow user to access member of type "USER" and name matches
219 * username, or to access member of type "LIST" and list is one that user is
220 * on the acl of, or the list is visible.
223 access_member(q, argv, cl)
228 if (!strcmp(argv[0], "LIST") || !strcmp(argv[0], "RLIST"))
229 return(access_visible_list(q, &argv[1], cl));
231 if (!strcmp(argv[0], "USER") || !strcmp(argv[0], "RUSER")) {
232 if (cl->users_id == *(int *)argv[1])
240 /* access_qgli - special access routine for Qualified_get_lists. Allows
241 * access iff argv[0] == "TRUE" and argv[2] == "FALSE".
244 access_qgli(q, argv, cl)
249 if (!strcmp(argv[0], "TRUE") && !strcmp(argv[2], "FALSE"))
255 /* access_service - allow access if user is on ACL of service. Don't
256 * allow access if a wildcard is used.
259 access_service(q, argv, cl)
264 EXEC SQL BEGIN DECLARE SECTION;
265 int acl_id, rowcount;
266 char *name, acl_type[9];
267 EXEC SQL END DECLARE SECTION;
268 int client_id, status;
273 EXEC SQL SELECT acl_id, acl_type
274 INTO :acl_id, :acl_type
277 if (sqlca.sqlerrd[2] > 1) return(MR_PERM);
278 /* parse client structure */
279 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
282 /* check for client in access control list */
283 status = find_member(acl_type, acl_id, client_type, client_id, 0);
284 if (!status) return(MR_PERM);
291 /* access_filesys - verify that client is owner or on owners list of filesystem
295 access_filesys(q, argv, cl)
300 EXEC SQL BEGIN DECLARE SECTION;
301 int users_id, list_id;
303 EXEC SQL END DECLARE SECTION;
304 int status, client_id;
308 EXEC SQL SELECT owner, owners
309 INTO :users_id, :list_id
312 if (sqlca.sqlcode < 0 || sqlca.sqlerrd[2] != 1)
315 if (users_id == cl->users_id)
317 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
319 status = find_member("LIST", list_id, client_type, client_id, 0);
330 /* Setup routine for add_user
332 * Inputs: argv[0] - login
337 * - if argv[1] == UNIQUE_UID then set argv[1] = next(uid)
338 * - if argv[0] == UNIQUE_LOGIN then set argv[0] = "#<uid>"
341 setup_ausr(q, argv, cl)
343 register char *argv[];
346 EXEC SQL BEGIN DECLARE SECTION;
349 EXEC SQL END DECLARE SECTION;
352 /* this is currently disabled because we need an index on ID's
353 * before it can run in finite time.
355 mit_id = argv[U_MITID];
356 ## retrieve (rowcount = any(u.#mit_id where u.#mit_id = mit_id))
357 if (ingres_errno) return(mr_errcode);
358 if (rowcount) return(MR_EXISTS);
361 if (!strcmp(argv[1], UNIQUE_UID) || atoi(argv[1]) == -1) {
362 if (set_next_object_id("uid", "users"))
363 return(MR_INGRES_ERR);
364 EXEC SQL SELECT value
368 if (sqlca.sqlcode < 0 || sqlca.sqlerrd[2] != 1)
370 sprintf(argv[1], "%d", nuid);
373 if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[1]) == -1) {
374 sprintf(argv[0], "#%s", argv[1]);
381 /* setup_dusr - verify that the user is no longer being referenced
382 * and may safely be deleted.
385 int setup_dusr(q, argv)
389 EXEC SQL BEGIN DECLARE SECTION;
391 EXEC SQL END DECLARE SECTION;
393 id = *(int *)argv[0];
395 /* For now, only allow users to be deleted if their status is 0 */
396 ## repeat retrieve (flag = u.status) where u.users_id = @id
397 if (flag != 0 && flag != 4)
400 ## repeat delete quota where quota.entity_id = @id and quota.type = "USER"
401 ## repeat delete krbmap where krbmap.users_id = @id
402 ## repeat retrieve (flag = any(imembers.member_id where imembers.member_id=@id
403 ## and imembers.member_type = "USER"))
406 ## repeat retrieve (flag = any(filesys.label where filesys.owner=@id))
409 ## repeat retrieve (flag = any(list.name where list.acl_id=@id and
410 ## list.acl_type = "USER"))
413 ## repeat retrieve (flag = any(servers.name where servers.acl_id=@id and
414 ## servers.acl_type = "USER"))
417 ## repeat retrieve (flag=any(hostaccess.acl_id where hostaccess.acl_id=@id and
418 ## hostaccess.acl_type = "USER"))
427 /* setup_spop: verify that there is already a valid POP machine_id in the
428 * pop_id field. Also take care of keeping track of the post office usage.
430 int setup_spop(q, argv)
434 EXEC SQL BEGIN DECLARE SECTION;
437 EXEC SQL END DECLARE SECTION;
439 id = *(int *)argv[0];
440 ## repeat retrieve (type = u.potype, mid = u.pop_id,
441 ## flag = any(machine.name where machine.mach_id = u.pop_id
442 ## and u.pop_id != 0 and u.users_id = @id))
443 ## where u.users_id = @id
446 if (strcmp(strtrim(type), "POP"))
447 set_pop_usage(mid, 1);
452 /* setup_dpob: Take care of keeping track of the post office usage.
454 int setup_dpob(q, argv)
458 EXEC SQL BEGIN DECLARE SECTION;
461 EXEC SQL END DECLARE SECTION;
463 user = *(int *)argv[0];
464 EXEC SQL SELECT potype, pop_id
467 WHERE users_id = :user;
468 if (ingres_errno) return(mr_errcode);
470 if (!strcmp(strtrim(type), "POP"))
471 set_pop_usage(id, -1);
476 /* setup_dmac - verify that the machine is no longer being referenced
477 * and may safely be deleted.
480 int setup_dmac(q, argv)
484 EXEC SQL BEGIN DECLARE SECTION;
486 EXEC SQL END DECLARE SECTION;
488 id = *(int *)argv[0];
489 ## repeat retrieve (flag = any(users.login where users.potype = "POP"
490 ## and users.pop_id=@id))
493 ## repeat retrieve (flag = any(serverhosts.mach_id
494 ## where serverhosts.mach_id=@id))
497 ## repeat retrieve (flag = any(nfsphys.mach_id where nfsphys.mach_id=@id))
500 ## repeat retrieve (flag = any(hostaccess.mach_id where hostaccess.mach_id=@id))
503 ## repeat retrieve (flag = any(printcap.mach_id where printcap.mach_id=@id))
506 ## repeat retrieve (flag = any(printcap.quotaserver where printcap.quotaserver=@id))
509 ## repeat retrieve (flag = any(palladium.mach_id where palladium.mach_id=@id))
513 ## repeat delete mcmap where mcmap.mach_id = @id
514 if (ingres_errno) return(mr_errcode);
519 /* setup_dclu - verify that the cluster is no longer being referenced
520 * and may safely be deleted.
523 int setup_dclu(q, argv)
527 EXEC SQL BEGIN DECLARE SECTION;
529 EXEC SQL END DECLARE SECTION;
531 id = *(int *)argv[0];
532 ## repeat retrieve (flag = any(mcmap.mach_id where mcmap.clu_id=@id))
535 ## repeat retrieve (flag = any(svc.clu_id where svc.clu_id=@id))
544 /* setup_alis - if argv[5] is non-zero and argv[6] is UNIQUE_ID, then allocate
545 * a new gid and put it in argv[6]. Otherwise if argv[6] is UNIQUE_ID but
546 * argv[5] is not, then remember that UNIQUE_ID is being stored by putting
547 * a -1 there. Remember that this is also used for ulis, with the indexes
551 int setup_alis(q, argv)
555 EXEC SQL BEGIN DECLARE SECTION;
557 EXEC SQL END DECLARE SECTION;
561 if (!strcmp(q->shortname, "alis"))
563 else if (!strcmp(q->shortname, "ulis"))
566 if (!strcmp(argv[idx], UNIQUE_GID) || atoi(argv[idx]) == -1) {
567 if (atoi(argv[idx - 1])) {
568 if (set_next_object_id("gid", "list"))
569 return(MR_INGRES_ERR);
570 EXEC SQL SELECT value
574 if (ingres_errno) return(mr_errcode);
575 sprintf(argv[idx], "%d", ngid);
577 strcpy(argv[idx], "-1");
585 /* setup_dlist - verify that the list is no longer being referenced
586 * and may safely be deleted.
589 int setup_dlis(q, argv)
593 EXEC SQL BEGIN DECLARE SECTION;
595 EXEC SQL END DECLARE SECTION;
597 id = *(int *)argv[0];
598 ## repeat retrieve (flag = any(imembers.member_id where imembers.member_id=@id
599 ## and imembers.member_type = "LIST"))
602 ## repeat retrieve (flag = any(imembers.member_id where imembers.list_id=@id))
605 ## repeat retrieve (flag = any(filesys.label where filesys.owners=@id))
608 ## repeat retrieve (flag = any(capacls.tag where capacls.list_id=@id))
611 ## repeat retrieve (flag = any(list.name where list.acl_id=@id and
612 ## list.acl_type = "LIST" and list.list_id != @id))
615 ## repeat retrieve (flag = any(servers.name where servers.acl_id=@id and
616 ## servers.acl_type = "LIST"))
619 ## repeat retrieve (flag = any(quota.entity_id where quota.entity_id=@id and
620 ## quota.type = "GROUP"))
623 ## repeat retrieve (flag=any(hostaccess.acl_id where hostaccess.acl_id=@id and
624 ## hostaccess.acl_type = "LIST"))
627 ## repeat retrieve (flag = any(zephyr.class
628 ## where zephyr.xmt_type = "LIST" and zephyr.xmt_id = @id or
629 ## zephyr.sub_type = "LIST" and zephyr.sub_id = @id or
630 ## zephyr.iws_type = "LIST" and zephyr.iws_id = @id or
631 ## zephyr.iui_type = "LIST" and zephyr.iui_id = @id))
640 /* setup_dsin - verify that the service is no longer being referenced
641 * and may safely be deleted.
644 int setup_dsin(q, argv)
648 EXEC SQL BEGIN DECLARE SECTION;
651 EXEC SQL END DECLARE SECTION;
654 ## repeat retrieve (flag = any(serverhosts.service
655 ## where serverhosts.service=uppercase(@name)))
658 EXEC SQL SELECT inprogress
670 /* setup_dshi - verify that the service-host is no longer being referenced
671 * and may safely be deleted.
674 int setup_dshi(q, argv)
678 EXEC SQL BEGIN DECLARE SECTION;
681 EXEC SQL END DECLARE SECTION;
684 id = *(int *)argv[1];
686 EXEC SQL SELECT inprogress
689 WHERE service = :name AND mach_id = :id;
699 ** setup_add_filesys - verify existance of referenced file systems
711 ** * extract directory prefix from name
712 ** * verify mach_id/dir in nfsphys
713 ** * verify access in {r, w, R, W}
715 ** Side effect: sets variable var_phys_id to the ID of the physical
716 ** filesystem (nfsphys_id for NFS, 0 for RVD)
719 ** MR_NFS - specified directory not exported
720 ** MR_FILESYS_ACCESS - invalid filesys access
724 ##static int var_phys_id;
732 EXEC SQL BEGIN DECLARE SECTION;
734 char ftype[32], *access;
735 EXEC SQL END DECLARE SECTION;
738 mach_id = *(int *)argv[2];
743 sprintf(ftype, "fs_access_%s", type);
744 ## retrieve (ok = any(alias.trans where alias.name = ftype and
745 ## alias.type = "TYPE" and alias.trans = access))
746 if (ingres_errno) return(mr_errcode);
747 if (ok == 0) return(MR_FILESYS_ACCESS);
749 if (!strcmp(type, "NFS"))
750 return (check_nfs(mach_id, name, access));
756 /* Verify the arguments, depending on the FStype. Also, if this is an
757 * NFS filesystem, then update any quotas for that filesystem to reflect
761 setup_ufil(q, argv, cl)
768 EXEC SQL BEGIN DECLARE SECTION;
770 char *entity, ftype[32], *access;
771 EXEC SQL END DECLARE SECTION;
774 mach_id = *(int *)argv[3];
778 fid = *(int *)argv[0];
782 sprintf(ftype, "fs_access_%s", type);
783 ## retrieve (total = any(alias.trans where alias.name = ftype and
784 ## alias.type = "TYPE" and alias.trans = access))
785 if (ingres_errno) return(mr_errcode);
786 if (total == 0) return(MR_FILESYS_ACCESS);
788 if (!strcmp(type, "NFS")) {
789 status = check_nfs(mach_id, name, access);
790 ## replace quota (phys_id = var_phys_id) where quota.filsys_id = fid
791 if (ingres_errno) return(mr_errcode);
793 } else if (!strcmp(type, "AFS")) {
795 ## retrieve (total = sum(quota.quota where quota.filsys_id = fid
796 ## and quota.phys_id != 0))
797 if (ingres_errno) return(mr_errcode);
799 ## append quota (quota = total, filsys_id = fid,
800 ## phys_id = 0, entity_id = 0, type = "ANY",
801 ## modtime = "now", modby = who, modwith = entity)
802 if (ingres_errno) return(mr_errcode);
805 ## replace quota (phys_id = 0) where quota.filsys_id = fid
806 if (ingres_errno) return(mr_errcode);
812 /* Find the NFS physical partition that the named directory is on.
813 * This is done by comparing the dir against the mount point of the
814 * partition. To make sure we get the correct match when there is
815 * more than one, we sort the query in reverse order by dir name.
818 ##check_nfs(mach_id, name, access)
819 EXEC SQL BEGIN DECLARE SECTION;
821 EXEC SQL END DECLARE SECTION;
825 EXEC SQL BEGIN DECLARE SECTION;
827 EXEC SQL END DECLARE SECTION;
834 ## range of np is nfsphys
835 ## repeat retrieve (var_phys_id = np.#nfsphys_id, dir = trim(np.#dir))
836 ## where np.#mach_id = @mach_id sort by #dir:d {
840 if (*cp1++ != *cp2) break;
854 /* setup_dfil: free any quota records and fsgroup info associated with
855 * a filesystem when it is deleted. Also adjust the allocation numbers.
858 setup_dfil(q, argv, cl)
863 EXEC SQL BEGIN DECLARE SECTION;
865 EXEC SQL END DECLARE SECTION;
867 id = *(int *)argv[0];
868 ## range of q is quota
869 ## range of n is nfsphys
870 ## repeat replace n (allocated=n.allocated-sum(q.quota where q.filsys_id=@id))
871 ## where n.nfsphys_id = filesys.phys_id and filesys.filsys_id = @id
873 ## repeat delete q where q.filsys_id = @id
874 ## repeat delete fsgroup where fsgroup.filsys_id = @id
875 ## repeat delete fsgroup where fsgroup.group_id = @id
876 if (ingres_errno) return(mr_errcode);
881 /* setup_dnfp: check to see that the nfs physical partition does not have
882 * any filesystems assigned to it before allowing it to be deleted.
885 setup_dnfp(q, argv, cl)
890 EXEC SQL BEGIN DECLARE SECTION;
893 EXEC SQL END DECLARE SECTION;
895 id = *(int *)argv[0];
897 ## repeat retrieve (exist = any(filesys.label where filesys.mach_id = @id
898 ## and filesys.phys_id = nfsphys.nfsphys_id and
899 ## nfsphys.mach_id = @id and nfsphys.#dir = @dir))
908 /* setup_dqot: Remove allocation from nfsphys before deleting quota.
909 * argv[0] = filsys_id
910 * argv[1] = type if "update_quota" or "delete_quota"
911 * argv[2 or 1] = users_id or list_id
914 setup_dqot(q, argv, cl)
919 EXEC SQL BEGIN DECLARE SECTION;
922 EXEC SQL END DECLARE SECTION;
924 fs = *(int *)argv[0];
925 if (!strcmp(q->name, "update_quota") || !strcmp(q->name, "delete_quota")) {
927 id = *(int *)argv[2];
930 id = *(int *)argv[1];
932 EXEC SQL SELECT quota_value
935 WHERE type = :qtype AND entity_id = :id AND filsys_id = :fs;
936 ## repeat replace nfsphys (allocated = nfsphys.allocated - @quota)
937 ## where nfsphys.nfsphys_id = filesys.#phys_id and filesys.filsys_id = @fs
938 if (ingres_errno) return(mr_errcode);
943 /* setup_sshi: don't exclusive lock the machine table during
944 * set_server_host_internal.
947 setup_sshi(q, argv, cl)
952 ## set lockmode session where readlock = system
956 /* setup add_kerberos_user_mapping: add the string to the string
957 * table if necessary.
960 setup_akum(q, argv, cl)
965 EXEC SQL BEGIN DECLARE SECTION;
968 EXEC SQL END DECLARE SECTION;
971 if (name_to_id(name, "STRING", &id) != MR_SUCCESS) {
972 if (q->type != APPEND) return(MR_STRING);
973 EXEC SQL SELECT value
976 WHERE name = "strings_id";
978 ## replace v (value = id) where v.#name = "strings_id"
979 ## append to strings (string_id = id, string = name)
980 cache_entry(name, "STRING", id);
982 if (ingres_errno) return(mr_errcode);
983 *(int *)argv[1] = id;
989 /* FOLLOWUP ROUTINES */
991 /* generic set_modtime routine. This takes the table name from the query,
992 * and will update the modtime, modby, and modwho fields in the entry in
993 * the table whose name field matches argv[0].
996 set_modtime(q, argv, cl)
1001 EXEC SQL BEGIN DECLARE SECTION;
1002 char *name, *entity, *tbl;
1004 EXEC SQL END DECLARE SECTION;
1006 entity = cl->entity;
1007 who = cl->client_id;
1011 ## replace tbl (modtime = "now", modby = who, modwith = entity)
1012 ## where tbl.#name = name
1016 /* generic set_modtime_by_id routine. This takes the table name from
1017 * the query, and the id name from the validate record,
1018 * and will update the modtime, modby, and modwho fields in the entry in
1019 * the table whose id matches argv[0].
1022 set_modtime_by_id(q, argv, cl)
1027 EXEC SQL BEGIN DECLARE SECTION;
1028 char *entity, *tbl, *id_name;
1030 EXEC SQL END DECLARE SECTION;
1032 entity = cl->entity;
1033 who = cl->client_id;
1035 id_name = q->validate->object_id;
1037 id = *(int *)argv[0];
1038 ## replace tbl (modtime = "now", modby = who, modwith = entity)
1039 ## where tbl.id_name = id
1044 /* Sets the finger modtime on a user record. The users_id will be in argv[0].
1047 set_finger_modtime(q, argv, cl)
1052 EXEC SQL BEGIN DECLARE SECTION;
1055 EXEC SQL END DECLARE SECTION;
1057 entity = cl->entity;
1058 who = cl->client_id;
1059 users_id = *(int *)argv[0];
1061 ## repeat replace u (fmodtime = "now", fmodby = @who, fmodwith = @entity)
1062 ## where u.#users_id = @users_id
1067 /* Sets the pobox modtime on a user record. The users_id will be in argv[0].
1070 set_pobox_modtime(q, argv, cl)
1075 EXEC SQL BEGIN DECLARE SECTION;
1078 EXEC SQL END DECLARE SECTION;
1080 entity = cl->entity;
1081 who = cl->client_id;
1082 users_id = *(int *)argv[0];
1084 ## repeat replace users (pmodtime = "now", pmodby = @who, pmodwith = @entity)
1085 ## where users.#users_id = @users_id
1090 /* Like set_modtime, but uppercases the name first.
1093 set_uppercase_modtime(q, argv, cl)
1098 EXEC SQL BEGIN DECLARE SECTION;
1099 char *name, *entity, *tbl;
1101 EXEC SQL END DECLARE SECTION;
1103 entity = cl->entity;
1104 who = cl->client_id;
1108 ## replace tbl (modtime = "now", modby = who, modwith = entity)
1109 ## where tbl.#name = uppercase(name)
1114 /* Sets the modtime on the machine whose mach_id is in argv[0]. This routine
1115 * is necessary for add_machine_to_cluster becuase the table that query
1116 * operates on is "mcm", not "machine".
1119 set_mach_modtime_by_id(q, argv, cl)
1124 EXEC SQL BEGIN DECLARE SECTION;
1127 EXEC SQL END DECLARE SECTION;
1129 entity = cl->entity;
1130 who = cl->client_id;
1132 id = *(int *)argv[0];
1133 ## repeat replace machine (modtime = "now", modby = @who, modwith = @entity)
1134 ## where machine.mach_id = @id
1139 /* Sets the modtime on the cluster whose mach_id is in argv[0]. This routine
1140 * is necessary for add_cluster_data and delete_cluster_data becuase the
1141 * table that query operates on is "svc", not "cluster".
1144 set_cluster_modtime_by_id(q, argv, cl)
1149 EXEC SQL BEGIN DECLARE SECTION;
1152 EXEC SQL END DECLARE SECTION;
1154 entity = cl->entity;
1155 who = cl->client_id;
1157 id = *(int *)argv[0];
1158 ## repeat replace cluster (modtime = "now", modby = @who, modwith = @entity)
1159 ## where cluster.clu_id = @id
1164 /* sets the modtime on the serverhost where the service name is in argv[0]
1165 * and the mach_id is in argv[1].
1168 set_serverhost_modtime(q, argv, cl)
1173 EXEC SQL BEGIN DECLARE SECTION;
1174 char *entity, *serv;
1176 EXEC SQL END DECLARE SECTION;
1178 entity = cl->entity;
1179 who = cl->client_id;
1182 id = *(int *)argv[1];
1183 ## repeat replace sh (modtime = "now", modby = @who, modwith = @entity)
1184 ## where sh.service = uppercase(@serv) and sh.mach_id = @id
1189 /* sets the modtime on the nfsphys where the mach_id is in argv[0] and the
1190 * directory name is in argv[1].
1193 set_nfsphys_modtime(q, argv, cl)
1198 EXEC SQL BEGIN DECLARE SECTION;
1201 EXEC SQL END DECLARE SECTION;
1203 entity = cl->entity;
1204 who = cl->client_id;
1206 id = *(int *)argv[0];
1208 ## repeat replace np (modtime = "now", modby = @who, modwith = @entity)
1209 ## where np.#dir = @dir and np.mach_id = @id
1214 /* sets the modtime on a filesystem, where argv[0] contains the filesys
1218 set_filesys_modtime(q, argv, cl)
1223 EXEC SQL BEGIN DECLARE SECTION;
1224 char *label, *entity;
1226 EXEC SQL END DECLARE SECTION;
1228 entity = cl->entity;
1229 who = cl->client_id;
1232 if (!strcmp(q->shortname, "ufil"))
1235 ## repeat replace fs (modtime = "now", modby = @who, modwith = @entity,
1236 ## #phys_id = @var_phys_id) where fs.#label = @label
1241 /* sets the modtime on a zephyr class, where argv[0] contains the class
1245 set_zephyr_modtime(q, argv, cl)
1250 EXEC SQL BEGIN DECLARE SECTION;
1251 char *class, *entity;
1253 EXEC SQL END DECLARE SECTION;
1255 entity = cl->entity;
1256 who = cl->client_id;
1260 ## repeat replace z (modtime = "now", modby = @who, modwith = @entity)
1261 ## where z.#class = @class
1266 /* fixes the modby field. This will be the second to last thing in the
1267 * argv, the argv length is determined from the query structure. It is
1268 * passed as a pointer to an integer. This will either turn it into a
1269 * username, or # + the users_id.
1271 followup_fix_modby(q, sq, v, action, actarg, cl)
1273 register struct save_queue *sq;
1275 register int (*action)();
1276 register int actarg;
1280 char **argv, *malloc();
1284 while (sq_get_data(sq, &argv)) {
1287 status = id_to_name(id, "USER", &argv[i]);
1289 status = id_to_name(-id, "STRING", &argv[i]);
1290 if (status && status != MR_NO_MATCH)
1292 (*action)(q->vcnt, argv, actarg);
1293 for (j = 0; j < q->vcnt; j++)
1303 ** followup_ausr - add finger and pobox entries, set_user_modtime
1306 ** argv[0] - login (add_user)
1307 ** argv[3] - last name
1308 ** argv[4] - first name
1309 ** argv[5] - middle name
1313 followup_ausr(q, argv, cl)
1318 EXEC SQL BEGIN DECLARE SECTION;
1320 char *login, *entity;
1322 EXEC SQL END DECLARE SECTION;
1325 who = cl->client_id;
1326 entity = cl->entity;
1328 /* build fullname */
1329 if (strlen(argv[4]) && strlen(argv[5]))
1330 sprintf(fullname, "%s %s %s", argv[4], argv[5], argv[3]);
1331 else if (strlen(argv[4]))
1332 sprintf(fullname, "%s %s", argv[4], argv[3]);
1334 sprintf(fullname, "%s", argv[3]);
1336 /* create finger entry, pobox & set modtime on user */
1337 ## repeat replace u (modtime = "now", modby=@who, modwith=@entity,
1338 ## #fullname=@fullname, mit_affil = u.mit_year,
1339 ## fmodtime="now", fmodby=@who, fmodwith=@entity,
1340 ## potype="NONE", pmodtime="now", pmodby=@who, pmodwith=@entity)
1341 ## where u.#login = @login
1347 /* followup_gpob: fixes argv[2] based on the IDs currently there and the
1348 * type in argv[1]. Then completes the upcall to the user.
1350 * argv[2] is of the form "123:234" where the first integer is the machine
1351 * ID if it is a pop box, and the second is the string ID if it is an SMTP
1352 * box. argv[1] should be "POP", "SMTP", or "NONE". Boxes of type NONE
1356 followup_gpob(q, sq, v, action, actarg, cl)
1357 register struct query *q;
1358 register struct save_queue *sq;
1359 register struct validate *v;
1360 register int (*action)();
1364 char **argv, *index();
1366 int mid, sid, status;
1369 while (sq_get_data(sq, &argv)) {
1370 mr_trim_args(2, argv);
1372 p = index(argv[2], ':');
1374 mid = atoi(argv[2]);
1377 if (!strcmp(ptype, "POP")) {
1378 status = id_to_name(mid, "MACHINE", &argv[2]);
1379 if (status == MR_NO_MATCH)
1381 } else if (!strcmp(ptype, "SMTP")) {
1382 status = id_to_name(sid, "STRING", &argv[2]);
1383 if (status == MR_NO_MATCH)
1385 } else /* ptype == "NONE" */ {
1388 if (status) return(status);
1390 if (!strcmp(q->shortname, "gpob")) {
1391 sid = atoi(argv[4]);
1393 status = id_to_name(sid, "USER", &argv[4]);
1395 status = id_to_name(-sid, "STRING", &argv[4]);
1397 if (status && status != MR_NO_MATCH) return(status);
1399 (*action)(q->vcnt, argv, actarg);
1401 /* free saved data */
1409 return (MR_SUCCESS);
1413 /* followup_glin: fix the ace_name in argv[8]. argv[7] will contain the
1414 * ace_type: "LIST", "USER", or "NONE". Decode the id in argv[8] into the
1415 * proper name based on the type, and repace that string in the argv.
1416 * Also fixes the modby field by called followup_fix_modby.
1419 followup_glin(q, sq, v, action, actarg, cl)
1420 register struct query *q;
1421 register struct save_queue *sq;
1422 register struct validate *v;
1423 register int (*action)();
1427 char **argv, *malloc(), *realloc(), *type;
1428 int id, i, idx, status;
1431 if (!strcmp(q->shortname, "gsin"))
1434 while (sq_get_data(sq, &argv)) {
1435 mr_trim_args(q->vcnt, argv);
1437 id = atoi(argv[i = q->vcnt - 2]);
1439 status = id_to_name(id, "USER", &argv[i]);
1441 status = id_to_name(-id, "STRING", &argv[i]);
1442 if (status && status != MR_NO_MATCH)
1445 id = atoi(argv[idx]);
1446 type = argv[idx - 1];
1448 if (!strcmp(type, "LIST")) {
1449 status = id_to_name(id, "LIST", &argv[idx]);
1450 } else if (!strcmp(type, "USER")) {
1451 status = id_to_name(id, "USER", &argv[idx]);
1452 } else if (!strcmp(type, "KERBEROS")) {
1453 status = id_to_name(id, "STRING", &argv[idx]);
1454 } else if (!strcmp(type, "NONE")) {
1457 argv[idx] = strsave("NONE");
1461 argv[idx] = strsave("???");
1463 if (status && status != MR_NO_MATCH)
1466 if (!strcmp(q->shortname, "glin") && atoi(argv[6]) == -1) {
1467 argv[6] = realloc(argv[6], strlen(UNIQUE_GID) + 1);
1468 strcpy(argv[6], UNIQUE_GID);
1472 (*action)(q->vcnt, argv, actarg);
1474 /* free saved data */
1475 for (i = 0; i < q->vcnt; i++)
1481 return (MR_SUCCESS);
1485 /* followup_gqot: Fix the entity name, directory name & modby fields
1486 * argv[0] = filsys_id
1488 * argv[2] = entity_id
1489 * argv[3] = ascii(quota)
1492 followup_gqot(q, sq, v, action, actarg, cl)
1494 register struct save_queue *sq;
1496 register int (*action)();
1497 register int actarg;
1501 char **argv, *malloc();
1502 EXEC SQL BEGIN DECLARE SECTION;
1505 EXEC SQL END DECLARE SECTION;
1508 if (!strcmp(q->name, "get_quota") ||
1509 !strcmp(q->name, "get_quota_by_filesys"))
1513 while (sq_get_data(sq, &argv)) {
1515 switch (argv[1][0]) {
1517 status = id_to_name(atoi(argv[2]), "USER", &argv[2]);
1521 status = id_to_name(atoi(argv[2]), "LIST", &argv[2]);
1525 argv[2] = strsave("system:anyuser");
1529 argv[2] = malloc(8);
1530 sprintf(argv[2], "%d", id);
1533 id = atoi(argv[idx]);
1535 argv[idx] = malloc(256);
1539 EXEC SQL SELECT name
1542 WHERE label = :label;
1547 WHERE nfsphys_id = :id;
1549 if (sqlca.sqlcode < 0 || sqlca.sqlerrd[2] != 1) {
1550 sprintf(argv[idx], "#%d", id);
1553 id = atoi(argv[idx+3]);
1555 status = id_to_name(id, "USER", &argv[idx+3]);
1557 status = id_to_name(-id, "STRING", &argv[idx+3]);
1558 if (status && status != MR_NO_MATCH)
1560 (*action)(q->vcnt, argv, actarg);
1561 for (j = 0; j < q->vcnt; j++)
1570 /* followup_aqot: Add allocation to nfsphys after creating quota.
1571 * argv[0] = filsys_id
1572 * argv[1] = type if "add_quota" or "update_quota"
1574 * argv[3 or 2] = ascii(quota)
1577 followup_aqot(q, argv, cl)
1582 EXEC SQL BEGIN DECLARE SECTION;
1583 int quota, id, fs, who;
1584 char *entity, *qtype;
1585 EXEC SQL END DECLARE SECTION;
1587 fs = *(int *)argv[0];
1588 if (!strcmp(q->name, "add_quota") || !strcmp(q->name, "update_quota")) {
1590 id = *(int *)argv[2];
1591 quota = atoi(argv[3]);
1594 id = *(int *)argv[1];
1595 quota = atoi(argv[2]);
1597 who = cl->client_id;
1598 entity = cl->entity;
1600 ## repeat replace q (modtime = "now", modby = @who, modwith = @entity)
1601 ## where q.filsys_id = @fs and q.type = @qtype and q.entity_id = @id
1602 ## repeat replace nfsphys (allocated = nfsphys.allocated + @quota)
1603 ## where nfsphys.nfsphys_id = filesys.#phys_id and filesys.filsys_id = @fs
1604 if (ingres_errno) return(mr_errcode);
1609 followup_gpce(q, sq, v, action, actarg, cl)
1611 register struct save_queue *sq;
1613 register int (*action)();
1614 register int actarg;
1618 char **argv, *malloc();
1622 while (sq_get_data(sq, &argv)) {
1623 id = atoi(argv[PCAP_QSERVER]);
1624 status = id_to_name(id, "MACHINE", &argv[PCAP_QSERVER]);
1625 if (status) return (status);
1628 status = id_to_name(id, "USER", &argv[i]);
1630 status = id_to_name(-id, "STRING", &argv[i]);
1631 if (status && status != MR_NO_MATCH)
1633 (*action)(q->vcnt, argv, actarg);
1634 for (j = 0; j < q->vcnt; j++)
1646 followup_gzcl(q, sq, v, action, actarg, cl)
1647 register struct query *q;
1648 register struct save_queue *sq;
1649 register struct validate *v;
1650 register int (*action)();
1657 while (sq_get_data(sq, &argv)) {
1658 mr_trim_args(q->vcnt, argv);
1660 id = atoi(argv[i = q->vcnt - 2]);
1662 status = id_to_name(id, "USER", &argv[i]);
1664 status = id_to_name(-id, "STRING", &argv[i]);
1665 if (status && status != MR_NO_MATCH)
1668 for (i = 1; i < 8; i+=2) {
1669 id = atoi(argv[i+1]);
1670 if (!strcmp(argv[i], "LIST")) {
1671 status = id_to_name(id, "LIST", &argv[i+1]);
1672 } else if (!strcmp(argv[i], "USER")) {
1673 status = id_to_name(id, "USER", &argv[i+1]);
1674 } else if (!strcmp(argv[i], "KERBEROS")) {
1675 status = id_to_name(id, "STRING", &argv[i+1]);
1676 } else if (!strcmp(argv[i], "NONE")) {
1679 argv[i+1] = strsave("NONE");
1683 argv[i+1] = strsave("???");
1685 if (status && status != MR_NO_MATCH)
1690 (*action)(q->vcnt, argv, actarg);
1692 /* free saved data */
1693 for (i = 0; i < q->vcnt; i++)
1705 followup_gsha(q, sq, v, action, actarg, cl)
1706 register struct query *q;
1707 register struct save_queue *sq;
1708 register struct validate *v;
1709 register int (*action)();
1716 while (sq_get_data(sq, &argv)) {
1717 mr_trim_args(q->vcnt, argv);
1721 status = id_to_name(id, "USER", &argv[4]);
1723 status = id_to_name(-id, "STRING", &argv[4]);
1724 if (status && status != MR_NO_MATCH)
1728 if (!strcmp(argv[1], "LIST")) {
1729 status = id_to_name(id, "LIST", &argv[2]);
1730 } else if (!strcmp(argv[1], "USER")) {
1731 status = id_to_name(id, "USER", &argv[2]);
1732 } else if (!strcmp(argv[1], "KERBEROS")) {
1733 status = id_to_name(id, "STRING", &argv[2]);
1734 } else if (!strcmp(argv[1], "NONE")) {
1737 argv[2] = strsave("NONE");
1741 argv[2] = strsave("???");
1743 if (status && status != MR_NO_MATCH)
1747 (*action)(q->vcnt, argv, actarg);
1749 /* free saved data */
1750 for (i = 0; i < q->vcnt; i++)
1760 /* Special query routines */
1762 /* set_pobox - this does all of the real work.
1763 * argv = user_id, type, box
1764 * if type is POP, then box should be a machine, and its ID should be put in
1765 * pop_id. If type is SMTP, then box should be a string and its ID should
1766 * be put in box_id. If type is NONE, then box doesn't matter.
1769 int set_pobox(q, argv, cl)
1774 EXEC SQL BEGIN DECLARE SECTION;
1776 char *box, potype[9];
1777 EXEC SQL END DECLARE SECTION;
1781 user = *(int *)argv[0];
1782 EXEC SQL SELECT pop_id, potype
1785 WHERE users_id = :user;
1786 if (ingres_errno) return(mr_errcode);
1787 if (!strcmp(strtrim(potype), "POP"))
1788 set_pop_usage(id, -1);
1790 if (!strcmp(argv[1], "POP")) {
1791 status = name_to_id(box, "MACHINE", &id);
1792 if (status == MR_NO_MATCH)
1796 ## repeat replace users (#potype = "POP", pop_id = @id)
1797 ## where users.users_id = @user
1798 set_pop_usage(id, 1);
1799 } else if (!strcmp(argv[1], "SMTP")) {
1800 if (index(box, '/') || index(box, '|'))
1801 return(MR_BAD_CHAR);
1802 status = name_to_id(box, "STRING", &id);
1803 if (status == MR_NO_MATCH) {
1804 EXEC SQL SELECT value
1807 WHERE name = "strings_id";
1809 ## repeat replace values_tbl.(value = @id) where values_tbl.name = "strings_id"
1810 ## append to strings (string_id = id, string = box)
1813 ## repeat replace users (#potype = "SMTP", box_id = @id)
1814 ## where users.users_id = @user
1815 } else /* argv[1] == "NONE" */ {
1816 ## repeat replace users (#potype = "NONE") where users.users_id = @user
1819 set_pobox_modtime(q, argv, cl);
1820 ## repeat replace tblstats (updates = tblstats.updates + 1, modtime = "now")
1821 ## where tblstats.#table = "users"
1822 if (ingres_errno) return(mr_errcode);
1827 /* get_list_info: passed a wildcard list name, returns lots of stuff about
1828 * each list. This is tricky: first build a queue of all requested
1829 * data. Rest of processing consists of fixing gid, ace_name, and modby.
1832 get_list_info(q, aargv, cl, action, actarg)
1833 register struct query *q;
1836 register int (*action)();
1839 char *argv[13], *malloc(), *realloc();
1840 EXEC SQL BEGIN DECLARE SECTION;
1841 char *name, acl_type[9], listname[33], active[5], public[5], hidden[5];
1842 char maillist[5], grp[5], gid[6], acl_name[256], desc[256], modtime[27];
1843 char modby[256], modwith[9];
1844 int id, rowcount, acl_id, hid, modby_id;
1845 EXEC SQL END DECLARE SECTION;
1846 int returned, status;
1847 struct save_queue *sq, *sq_create();
1849 returned = rowcount = 0;
1853 EXEC SQL DECLARE l_cursor CURSOR FOR
1856 WHERE L.name = :name;
1857 EXEC SQL OPEN l_cursor;
1859 EXEC SQL FETCH l_cursor INTO :id;
1860 if (sqlca.sqlcode != 0) break;
1861 sq_save_data(sq, id);
1864 EXEC SQL CLOSE l_cursor;
1865 if (ingres_errno) return(mr_errcode);
1867 return(MR_NO_MATCH);
1869 argv[0] = listname; argv[1] = active; argv[2] = public; argv[3] = hidden;
1870 argv[4] = maillist; argv[5] = grp; argv[6] = gid; argv[7] = acl_type;
1871 argv[9] = desc; argv[10] = modtime; argv[12] = modwith;
1873 while (sq_get_data(sq, &id)) {
1877 ## repeat retrieve (listname = l.#name, active = text(l.#active),
1878 ## public = text(l.#public), hidden = text(l.#hidden),
1879 ## hid = l.#hidden, maillist = text(l.#maillist),
1880 ## group = text(l.#grp), gid = text(l.#gid),
1881 ## acl_type = trim(l.#acl_type), acl_id = l.#acl_id,
1882 ## desc = l.#desc, modtime = l.#modtime, modby_id = l.#modby,
1883 ## modwith =l.#modwith)
1884 ## where l.list_id = @id
1885 if (ingres_errno) return(mr_errcode);
1887 if (atoi(gid) == -1)
1888 argv[6] = UNIQUE_GID;
1890 argv[8] = malloc(0);
1891 if (!strcmp(acl_type, "LIST")) {
1892 status = id_to_name(acl_id, "LIST", &argv[8]);
1893 } else if (!strcmp(acl_type, "USER")) {
1894 status = id_to_name(acl_id, "USER", &argv[8]);
1895 } else if (!strcmp(acl_type, "KERBEROS")) {
1896 status = id_to_name(acl_id, "STRING", &argv[8]);
1897 } else if (!strcmp(acl_type, "NONE")) {
1900 argv[8] = strsave("NONE");
1904 argv[8] = strsave("???");
1906 if (status && status != MR_NO_MATCH) return(status);
1908 argv[11] = malloc(0);
1910 status = id_to_name(modby_id, "USER", &argv[11]);
1912 status = id_to_name(-modby_id, "STRING", &argv[11]);
1913 if (status && status != MR_NO_MATCH) return(status);
1915 mr_trim_args(q->vcnt, argv);
1917 (*action)(q->vcnt, argv, actarg);
1923 if (ingres_errno) return(mr_errcode);
1924 return (MR_SUCCESS);
1928 /* Add_member_to_list: do list flattening as we go! MAXLISTDEPTH is
1929 * how many different ancestors a member is allowed to have.
1932 #define MAXLISTDEPTH 1024
1934 int add_member_to_list(q, argv, cl)
1939 EXEC SQL BEGIN DECLARE SECTION;
1940 int id, lid, mid, exist, error, who, ref;
1941 char *mtype, dtype[9], *entity;
1942 EXEC SQL END DECLARE SECTION;
1943 int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a;
1944 int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d;
1946 char *dtypes[MAXLISTDEPTH];
1947 char *iargv[3], *buf;
1949 EXEC SQL DECLARE m_cursor_a CURSOR FOR
1950 SELECT M.list_id, M.ref_count
1952 WHERE M.member_id = :lid AND M.member_type = "LIST";
1953 EXEC SQL OPEN m_cursor_a;
1955 lid = *(int *)argv[0];
1957 mid = *(int *)argv[2];
1958 /* if the member is already a direct member of the list, punt */
1959 ## repeat retrieve (exist = any(m.list_id where m.list_id=@lid and
1960 ## m.member_id = @mid and m.member_type = @mtype
1961 ## and m.direct = 1))
1964 if (!strcasecmp(mtype, "STRING")) {
1966 status = id_to_name(mid, "STRING", &buf);
1967 if (status) return(status);
1968 if (index(buf, '/') || index(buf, '|')) {
1970 return(MR_BAD_CHAR);
1979 EXEC SQL FETCH m_cursor_a INTO :id, :ref;
1980 if (sqlca.sqlcode != 0) break;
1982 ancestors[acount++] = id;
1983 if (acount >= MAXLISTDEPTH) {
1984 return(MR_INTERNAL);
1987 if (ingres_errno) return(mr_errcode);
1988 if (acount >= MAXLISTDEPTH) {
1989 return(MR_INTERNAL);
1991 EXEC SQL CLOSE m_cursor_a;
1992 descendants[0] = mid;
1999 if (!strcmp(mtype, "LIST")) {
2000 EXEC SQL DECLARE m_cursor_l CURSOR FOR
2001 SELECT M.member_id, M.memeber_type, M.ref_count
2003 WHERE M.list_id = :mid;
2004 EXEC SQL OPEN m_cursor_l;
2006 EXEC SQL FETCH m_cursor_l INTO :id, :dtype, :ref;
2007 if (sqlca.sqlcode != 0) break;
2010 dtypes[dcount] = "LIST";
2013 dtypes[dcount] = "USER";
2016 dtypes[dcount] = "STRING";
2019 dtypes[dcount] = "KERBEROS";
2025 descendants[dcount++] = id;
2026 if (dcount >= MAXLISTDEPTH) {
2030 EXEC SQL CLOSE m_cursor_l;
2031 if (ingres_errno) return(mr_errcode);
2033 return(MR_INTERNAL);
2035 for (a = 0; a < acount; a++) {
2037 for (d = 0; d < dcount; d++) {
2038 mid = descendants[d];
2040 if (mid == lid && !strcmp(mtype, "LIST")) {
2041 return(MR_LISTLOOP);
2043 ## repeat retrieve (exist = any(m.ref_count where m.list_id = @lid
2044 ## and m.member_id = @mid
2045 ## and m.member_type = @mtype))
2046 ref = aref[a] * dref[d];
2048 if (a == 0 && d == 0)
2049 ## replace m (ref_count = m.ref_count+ref, direct = 1)
2050 ## where m.list_id = lid and m.member_id = mid and
2051 ## m.member_type = mtype
2053 ## replace m (ref_count = m.ref_count+ref)
2054 ## where m.list_id = lid and m.member_id = mid and
2055 ## m.member_type = mtype
2057 incremental_clear_before();
2058 if (a == 0 && d == 0)
2059 ## append imembers (list_id=lid, member_id = mid, direct = 1,
2060 ## member_type=mtype, ref_count = 1)
2062 ## append imembers (list_id=lid, member_id = mid,
2063 ## member_type=mtype, ref_count = ref)
2064 iargv[0] = (char *)lid;
2066 iargv[2] = (char *)mid;
2067 incremental_after("members", 0, iargv);
2071 lid = *(int *)argv[0];
2072 entity = cl->entity;
2073 who = cl->client_id;
2074 ## repeat replace list (modtime = "now", modby = @who, modwith = @entity)
2075 ## where list.#list_id = @lid
2076 if (ingres_errno) return(mr_errcode);
2081 /* Delete_member_from_list: do list flattening as we go!
2084 int delete_member_from_list(q, argv, cl)
2089 EXEC SQL BEGIN DECLARE SECTION;
2090 int id, lid, mid, cnt, exist, error, who, ref;
2091 char *mtype, dtype[9], *entity;
2092 EXEC SQL END DECLARE SECTION;
2093 int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a;
2094 int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d;
2095 char *dtypes[MAXLISTDEPTH];
2098 ## range of m is imembers
2099 lid = *(int *)argv[0];
2101 mid = *(int *)argv[2];
2102 /* if the member is not a direct member of the list, punt */
2103 ## repeat retrieve (exist = any(m.list_id where m.list_id=@lid and
2104 ## m.member_id = @mid and m.member_type = @mtype
2105 ## and m.direct = 1))
2106 if (ingres_errno) return(mr_errcode);
2108 return(MR_NO_MATCH);
2113 EXEC SQL DECLARE m3_cursor CURSOR FOR
2114 SELECT M.list_id, M.ref_count
2116 WHERE M.member_id = :lid AND M.member_type = "LIST";
2117 EXEC SQL OPEN m3_cursor;
2119 EXEC SQL FETCH m3_cursor INTO :id, :ref;
2120 if (sqlca.sqlcode != 0) break;
2122 ancestors[acount++] = id;
2123 if (acount >= MAXLISTDEPTH)
2126 EXEC SQL CLOSE m3_cursor;
2127 if (ingres_errno) return(mr_errcode);
2128 if (acount >= MAXLISTDEPTH)
2129 return(MR_INTERNAL);
2130 descendants[0] = mid;
2135 if (!strcmp(mtype, "LIST")) {
2136 EXEC SQL DECLARE m4_cursor CURSOR FOR
2137 SELECT M.member_id, M.memeber_type, M.ref_count
2139 WHERE M.list_id = :mid;
2140 EXEC SQL OPEN m4_cursor;
2142 EXEC SQL FETCH m4_cursor INTO :id, :dtype, :ref;
2143 if (sqlca.sqlcode != 0) break;
2146 dtypes[dcount] = "LIST";
2149 dtypes[dcount] = "USER";
2152 dtypes[dcount] = "STRING";
2155 dtypes[dcount] = "KERBEROS";
2161 descendants[dcount++] = id;
2162 if (dcount >= MAXLISTDEPTH)
2165 EXEC SQL CLOSE m4_cursor;
2166 if (ingres_errno) return(mr_errcode);
2168 return(MR_INTERNAL);
2170 EXEC SQL DECLARE m5_cursor CURSOR FOR
2173 WHERE M.list_id = :lid AND M.member_id = :mid AND M.member_type = :mtype;
2174 EXEC SQL OPEN m5_cursor;
2175 for (a = 0; a < acount; a++) {
2177 for (d = 0; d < dcount; d++) {
2178 mid = descendants[d];
2180 if (mid == lid && !strcmp(mtype, "LIST")) {
2181 return(MR_LISTLOOP);
2183 EXEC SQL FETCH m5_cursor INTO :cnt;
2184 if (sqlca.sqlcode != 0) break;
2185 ref = aref[a] * dref[d];
2187 iargv[0] = (char *)lid;
2189 iargv[2] = (char *)mid;
2190 incremental_before("members", 0, iargv);
2193 WHERE list_id = :lid AND member_id = :mid
2194 AND member_type = :mtype;
2195 incremental_clear_after();
2196 } else if (a == 0 && d == 0) {
2197 EXEC SQL UPDATE imembers
2198 SET ref_count = ref_count - :ref, direct = 0
2199 WHERE list_id = :lid AND member_id = :mid
2200 AND member_type = :mtype;
2202 EXEC SQL UPDATE imembers
2203 SET ref_count = ref_count - :ref
2204 WHERE list_id = :lid AND member_id = :mid
2205 AND member_type = :mtype;
2209 EXEC SQL CLOSE m5_cursor;
2210 lid = *(int *)argv[0];
2211 entity = cl->entity;
2212 who = cl->client_id;
2213 EXEC SQL UPDATE list
2214 SET modtime = "now", modby = :who, modwith = :entity
2215 WHERE list = :list_id;
2216 if (ingres_errno) return(mr_errcode);
2221 /* get_ace_use - given a type and a name, return a type and a name.
2222 * The ace_type is one of "LIST", "USER", "RLIST", or "RUSER" in argv[0],
2223 * and argv[1] will contain the ID of the entity in question. The R*
2224 * types mean to recursively look at every containing list, not just
2225 * when the object in question is a direct member. On return, the
2226 * usage type will be one of LIST, SERVICE, FILESYS, QUOTA, QUERY, or ZEPHYR.
2229 int get_ace_use(q, argv, cl, action, actarg)
2237 EXEC SQL BEGIN DECLARE SECTION;
2239 int aid, listid, id;
2240 EXEC SQL END DECLARE SECTION;
2241 struct save_queue *sq, *sq_create();
2244 aid = *(int *)argv[1];
2245 if (!strcmp(atype, "LIST") || !strcmp(atype, "USER") ||
2246 !strcmp(atype, "KERBEROS")) {
2247 return(get_ace_internal(atype, aid, action, actarg));
2251 if (!strcmp(atype, "RLIST")) {
2252 sq_save_data(sq, aid);
2253 /* get all the list_id's of containing lists */
2254 EXEC SQL DECLARE m6_cursor CURSOR FOR
2257 WHERE M.member_type = "LIST" AND M.member_id = :id;
2258 EXEC SQL OPEN m6_cursor;
2260 EXEC SQL FETCH m6_cursor INTO :listid;
2261 if (sqlca.sqlcode != 0) break;
2262 sq_save_unique_data(sq, listid);
2264 /* now process each one */
2265 while (sq_get_data(sq, &id)) {
2266 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2269 EXEC SQL CLOSE m6_cursor;
2272 if (!strcmp(atype, "RUSER")) {
2273 EXEC SQL DECLARE m7_cursor CURSOR FOR
2276 WHERE M.member_type = "USER" AND M.member_id = :aid;
2277 EXEC SQL OPEN m7_cursor;
2279 EXEC SQL FETCH m7_cursor INTO :listid;
2280 if (sqlca.sqlcode != 0) break;
2281 sq_save_data(sq, listid);
2283 /* now process each one */
2284 while (sq_get_data(sq, &id)) {
2285 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2288 if (get_ace_internal("USER", aid, action, actarg) == MR_SUCCESS)
2290 EXEC SQL CLOSE m7_cursor;
2293 if (!strcmp(atype, "RKERBERO")) {
2294 EXEC SQL DECLARE m8_cursor CURSOR FOR
2297 WHERE M.member_type = "KERBEROS" AND M.member_id = :aid;
2298 EXEC SQL OPEN m8_cursor;
2300 EXEC SQL FETCH m8_cursor INTO :listid;
2301 if (sqlca.sqlcode != 0) break;
2302 sq_save_data(sq, listid);
2304 /* now process each one */
2305 while (sq_get_data(sq, &id)) {
2306 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2309 if (get_ace_internal("KERBEROS", aid, action, actarg) == MR_SUCCESS)
2311 EXEC SQL CLOSE m8_cursor;
2315 if (ingres_errno) return(mr_errcode);
2316 if (!found) return(MR_NO_MATCH);
2321 /* This looks up a single list or user for ace use. atype must be "USER"
2322 * or "LIST", and aid is the ID of the corresponding object. This is used
2323 * by get_ace_use above.
2326 ##get_ace_internal(atype, aid, action, actarg)
2327 EXEC SQL BEGIN DECLARE SECTION;
2330 EXEC SQL END DECLARE SECTION;
2336 EXEC SQL BEGIN DECLARE SECTION;
2338 EXEC SQL END DECLARE SECTION;
2341 EXEC SQL DECLARE F1_cursor CURSOR FOR
2344 WHERE F.owners = :aid;
2345 EXEC SQL OPEN F1_cursor;
2347 EXEC SQL DECLARE C1_cursor CURSOR FOR
2350 WHERE C.list_id = :aid;
2351 EXEC SQL OPEN C1_cursor;
2353 if (!strcmp(atype, "LIST")) {
2354 rargv[0] = "FILESYS";
2356 EXEC SQL FETCH F1_cursor INTO :name;
2357 if (sqlca.sqlcode != 0) break;
2358 (*action)(2, rargv, actarg);
2363 EXEC SQL FETCH C1_cursor INTO :name;
2364 if (sqlca.sqlcode != 0) break;
2365 (*action)(2, rargv, actarg);
2368 } else if (!strcmp(atype, "USER")) {
2369 rargv[0] = "FILESYS";
2371 EXEC SQL FETCH F1_cursor INTO :name;
2372 if (sqlca.sqlcode != 0) break;
2373 (*action)(2, rargv, actarg);
2377 EXEC SQL CLOSE F1_cursor;
2378 EXEC SQL CLOSE C1_cursor;
2381 EXEC SQL DECLARE l8_cursor CURSOR FOR
2384 WHERE L.acl_type = :atype AND L.acl_id = :aid;
2385 EXEC SQL OPEN l8_cursor;
2388 EXEC SQL FETCH l8_cursor INTO :name;
2389 if (sqlca.sqlcode != 0) break;
2390 (*action)(2, rargv, actarg);
2393 EXEC SQL CLOSE l8_cursor;
2395 rargv[0] = "SERVICE";
2396 EXEC SQL DECLARE s_cursor CURSOR FOR
2399 WHERE S.acl_type = :atype AND S.acl_id = :aid;
2400 EXEC SQL OPEN s_cursor;
2403 EXEC SQL FETCH s_cursor INTO :name;
2404 if (sqlca.sqlcode != 0) break;
2405 (*action)(2, rargv, actarg);
2408 EXEC SQL CLOSE s_cursor;
2410 rargv[0] = "HOSTACCESS";
2411 EXEC SQL DECLARE h_cursor CURSOR FOR
2413 FROM MACHINE M, HOSTACCESS H
2414 WHERE M.mach_id = H.mach_id
2415 AND H.acl_type = :atype AND H.acl_id = :aid;
2416 EXEC SQL OPEN h_cursor;
2418 EXEC SQL FETCH h_cursor INTO :name;
2419 if (sqlca.sqlcode != 0) break;
2420 (*action)(2, rargv, actarg);
2423 EXEC SQL CLOSE h_cursor;
2425 rargv[0] = "ZEPHYR";
2426 EXEC SQL DECLARE z_cursor CURSOR FOR
2429 WHERE Z.xmt_type = :atype AND Z.xmt_id = :aid OR
2430 Z.sub_type = :atype AND Z.sub_id = :aid OR
2431 Z.iws_type = :atype AND Z.iws_id = :aid OR
2432 Z.iui_type = :atype AND Z.iui_id = :aid;
2434 EXEC SQL OPEN z_cursor;
2436 EXEC SQL FETCH h_cursor INTO :name;
2437 if (sqlca.sqlcode != 0) break;
2438 (*action)(2, rargv, actarg);
2441 EXEC SQL CLOSE z_cursor;
2443 if (!found) return(MR_NO_MATCH);
2448 /* get_lists_of_member - given a type and a name, return the name and flags
2449 * of all of the lists of the given member. The member_type is one of
2450 * "LIST", "USER", "STRING", "RLIST", "RUSER", or "RSTRING" in argv[0],
2451 * and argv[1] will contain the ID of the entity in question. The R*
2452 * types mean to recursively look at every containing list, not just
2453 * when the object in question is a direct member.
2456 int get_lists_of_member(q, argv, cl, action, actarg)
2463 int found = 0, direct = 1;
2465 EXEC SQL BEGIN DECLARE SECTION;
2467 int aid, listid, id;
2468 char name[33], active[5], public[5], hidden[5], maillist[5], grp[5];
2469 EXEC SQL END DECLARE SECTION;
2472 aid = *(int *)argv[1];
2473 if (!strcmp(atype, "RLIST")) {
2477 if (!strcmp(atype, "RUSER")) {
2481 if (!strcmp(atype, "RSTRING")) {
2485 if (!strcmp(atype, "RKERBEROS")) {
2494 rargv[4] = maillist;
2496 ## range of m is imembers
2498 ## repeat retrieve (name = list.#name, active = text(list.#active),
2499 ## public = text(list.#public), hidden = text(list.#hidden),
2500 ## maillist = text(list.#maillist), grp = text(list.#group))
2501 ## where list.list_id = m.list_id and m.direct = 1 and
2502 ## m.member_type = @atype and m.member_id = @aid {
2503 (*action)(6, rargv, actarg);
2507 ## repeat retrieve (name = list.#name, active = text(list.#active),
2508 ## public = text(list.#public), hidden = text(list.#hidden),
2509 ## maillist = text(list.#maillist), grp = text(list.#group))
2510 ## where list.list_id = m.list_id and
2511 ## m.member_type = @atype and m.member_id = @aid {
2512 (*action)(6, rargv, actarg);
2517 if (ingres_errno) return(mr_errcode);
2518 if (!found) return(MR_NO_MATCH);
2523 /* qualified_get_lists: passed "TRUE", "FALSE", or "DONTCARE" for each of
2524 * the five flags associated with each list. It will return the name of
2525 * each list that meets the quailifications. It does this by building a
2526 * where clause based on the arguments, then doing a retrieve.
2529 static char *lflags[5] = { "active", "public", "hidden", "maillist", "group" };
2531 int qualified_get_lists(q, argv, cl, action, actarg)
2538 return(qualified_get(q, argv, action, actarg, "l.list_id != 0",
2539 "l", "name", lflags));
2543 /** get_members_of_list - optimized query for retrieval of list members
2546 ** argv[0] - list_id
2549 ** - retrieve USER members, then LIST members, then STRING members
2552 get_members_of_list(q, argv, cl, action, actarg)
2559 EXEC SQL BEGIN DECLARE SECTION;
2560 int list_id, member_id;
2561 char member_name[129], member_type[9];
2562 EXEC SQL END DECLARE SECTION;
2565 struct save_queue *sq;
2567 list_id = *(int *)argv[0];
2571 EXEC SQL DECLARE m9_cursor CURSOR FOR
2572 SELECT M.member_type, M.member_id
2574 WHERE M.list_id = :list_id AND M.direct = 1;
2575 EXEC SQL OPEN m9_cursor;
2577 EXEC SQL FETCH m9_cursor INTO :member_type, :member_id;
2578 if (sqlca.sqlcode != 0) break;
2581 sq_save_data(sq, (member_type[0] << 24) | (member_id & 0xffffff));
2583 EXEC SQL CLOSE m9_cursor;
2584 if (members <= 49) {
2585 targv[1] = malloc(0);
2586 while (sq_remove_data(sq, &member_id)) {
2587 switch (member_id >> 24) {
2590 id_to_name(member_id & 0xffffff, "USER", &targv[1]);
2591 (*action)(2, targv, actarg);
2595 id_to_name(member_id & 0xffffff, "LIST", &targv[1]);
2596 (*action)(2, targv, actarg);
2599 targv[0] = "STRING";
2600 id_to_name(member_id & 0xffffff, "STRING", &targv[1]);
2601 (*action)(2, targv, actarg);
2604 targv[0] = "KERBEROS";
2605 id_to_name(member_id & 0xffffff, "STRING", &targv[1]);
2606 (*action)(2, targv, actarg);
2610 return(MR_INTERNAL);
2619 targv[1] = member_name;
2621 ## range of m is imembers
2622 ## repeat retrieve (member_name = users.login)
2623 ## where m.#list_id = @list_id and m.#member_type = "USER"
2624 ## and m.#member_id = users.users_id and m.direct = 1
2625 ## sort by #member_name
2627 (*action)(2, targv, actarg);
2629 if (ingres_errno) return(mr_errcode);
2632 ## repeat retrieve (member_name = list.name)
2633 ## where m.#list_id = @list_id and m.#member_type = "LIST"
2634 ## and m.#member_id = list.#list_id and m.direct = 1
2635 ## sort by #member_name
2637 (*action)(2, targv, actarg);
2639 if (ingres_errno) return(mr_errcode);
2641 targv[0] = "STRING";
2642 ## repeat retrieve (member_name = strings.string)
2643 ## where m.#list_id = @list_id and m.#member_type = "STRING"
2644 ## and m.#member_id = strings.string_id and m.direct = 1
2645 ## sort by #member_name
2647 (*action)(2, targv, actarg);
2649 if (ingres_errno) return(mr_errcode);
2651 targv[0] = "KERBEROS";
2652 ## repeat retrieve (member_name = strings.string)
2653 ## where m.#list_id = @list_id and m.#member_type = "KERBEROS"
2654 ## and m.#member_id = strings.string_id and m.direct = 1
2655 ## sort by #member_name
2657 (*action)(2, targv, actarg);
2659 if (ingres_errno) return(mr_errcode);
2665 /* count_members_of_list: this is a simple query, but it cannot be done
2666 * through the dispatch table.
2669 int count_members_of_list(q, argv, cl, action, actarg)
2676 EXEC SQL BEGIN DECLARE SECTION;
2678 EXEC SQL END DECLARE SECTION;
2679 char *rargv[1], countbuf[5];
2681 list = *(int *)argv[0];
2682 rargv[0] = countbuf;
2683 ## repeat retrieve (ct = count(imembers.list_id
2684 ## where imembers.list_id = @list and
2685 ## imembers.direct = 1))
2686 if (ingres_errno) return(mr_errcode);
2687 sprintf(countbuf, "%d", ct);
2688 (*action)(1, rargv, actarg);
2693 /* qualified_get_server: passed "TRUE", "FALSE", or "DONTCARE" for each of
2694 * the three flags associated with each service. It will return the name of
2695 * each service that meets the quailifications. It does this by building a
2696 * where clause based on the arguments, then doing a retrieve.
2699 static char *sflags[3] = { "enable", "inprogress", "harderror" };
2701 int qualified_get_server(q, argv, cl, action, actarg)
2708 return(qualified_get(q, argv, action, actarg, "s.name != \"\"",
2709 "s", "name", sflags));
2713 /* generic qualified get routine, used by qualified_get_lists,
2714 * qualified_get_server, and qualified_get_serverhost.
2716 * start - a simple where clause, must not be empty
2717 * range - the name of the range variable
2718 * field - the field to return
2719 * flags - an array of strings, names of the flag variables
2722 int qualified_get(q, argv, action, actarg, start, range, field, flags)
2732 EXEC SQL BEGIN DECLARE SECTION;
2733 char name[33], qual[256], *rvar, *rtbl, *rfield;
2735 EXEC SQL END DECLARE SECTION;
2736 char *rargv[1], buf[32];
2738 strcpy(qual, start);
2739 for (i = 0; i < q->argc; i++) {
2740 if (!strcmp(argv[i], "TRUE")) {
2741 sprintf(buf, " and %s.%s != 0", range, flags[i]);
2742 (void) strcat(qual, buf);
2743 } else if (!strcmp(argv[i], "FALSE")) {
2744 sprintf(buf, " and %s.%s = 0", range, flags[i]);
2745 (void) strcat(qual, buf);
2753 EXEC SQL DECLARE r9_cursor CURSOR FOR
2757 EXEC SQL OPEN r9_cursor;
2759 EXEC SQL FETCH r9_cursor INTO :name;
2760 if (sqlca.sqlcode != 0) break;
2761 (*action)(1, rargv, actarg);
2763 EXEC SQL CLOSE r9_cursor;
2764 if (ingres_errno) return(mr_errcode);
2765 if (sqlca.sqlcode == 100) return(MR_NO_MATCH);
2770 /* qualified_get_serverhost: passed "TRUE", "FALSE", or "DONTCARE" for each of
2771 * the five flags associated with each serverhost. It will return the name of
2772 * each service and host that meets the quailifications. It does this by
2773 * building a where clause based on the arguments, then doing a retrieve.
2776 static char *shflags[6] = { "service", "enable", "override", "success",
2777 "inprogress", "hosterror" };
2779 int qualified_get_serverhost(q, argv, cl, action, actarg)
2786 EXEC SQL BEGIN DECLARE SECTION;
2787 char sname[33], mname[33], qual[256];
2789 EXEC SQL END DECLARE SECTION;
2790 char *rargv[2], buf[32];
2792 sprintf(qual, "machine.mach_id = sh.mach_id and sh.service = uppercase(\"%s\")",
2794 for (i = 1; i < q->argc; i++) {
2795 if (!strcmp(argv[i], "TRUE")) {
2796 sprintf(buf, " and sh.%s != 0", shflags[i]);
2798 } else if (!strcmp(argv[i], "FALSE")) {
2799 sprintf(buf, " and sh.%s = 0", shflags[i]);
2806 EXEC SQL DECLARE s9_cursor CURSOR FOR
2807 SELECT S.service, M.name
2808 FROM SERVERHOSTS S, MACHINE M
2810 EXEC SQL OPEN s9_cursor;
2812 EXEC SQL FETCH s_cursor INTO :sname, :mname;
2813 if (sqlca.sqlcode != 0) break;
2814 (*action)(2, rargv, actarg);
2816 EXEC SQL CLOSE s9_cursor;
2817 if (ingres_errno) return(mr_errcode);
2818 if (sqlca.sqlcode == 100) return(MR_NO_MATCH);
2823 /* register_user - change user's login name and allocate a pobox, group,
2824 * filesystem, and quota for them. The user's status must start out as 0,
2825 * and is left as 2. Arguments are: user's UID, new login name, and user's
2826 * type for filesystem allocation (MR_FS_STUDENT, MR_FS_FACULTY,
2827 * MR_FS_STAFF, MR_FS_MISC).
2830 register_user(q, argv, cl)
2835 EXEC SQL BEGIN DECLARE SECTION;
2836 char *login, dir[65], *entity, *directory, machname[33];
2837 int who, rowcount, mid, uid, users_id, flag, utype, nid, list_id, quota;
2838 int size, alloc, pid, m_id;
2839 EXEC SQL END DECLARE SECTION;
2840 char buffer[256], *aargv[3];
2843 entity = cl->entity;
2844 who = cl->client_id;
2846 uid = atoi(argv[0]);
2848 utype = atoi(argv[2]);
2850 ## range of u is users
2851 ## range of l is list
2852 ## range of sh is serverhosts
2853 ## range of n is nfsphys
2854 ## range of m is machine
2857 EXEC SQL DECLARE u_cursor CURSOR FOR
2860 WHERE U.uid = :uid AND (U.status = 0 OR U.status = 5 OR U.status = 6);
2861 EXEC SQL OPEN u_cursor;
2863 EXEC SQL FETCH u_cursor INTO :users_id;
2864 if (sqlca.sqlcode != 0) break;
2866 if (sqlca.sqlcode == 100) return(MR_NO_MATCH);
2867 if (sqlca.sqlerrd[2] > 1) return(MR_NOT_UNIQUE);
2869 /* check new login name */
2870 ## repeat retrieve (flag = any(u.#login where u.#login = @login and
2871 ## u.#users_id != users_id))
2872 if (ingres_errno) return(mr_errcode);
2873 if (flag) return(MR_IN_USE);
2874 ## repeat retrieve (flag = any(l.#name where l.#name = @login))
2875 if (ingres_errno) return(mr_errcode);
2876 if (flag) return(MR_IN_USE);
2877 ## repeat retrieve (flag = any(filesys.#label where filesys.#label = @login))
2878 if (ingres_errno) return(mr_errcode);
2879 if (flag) return(MR_IN_USE);
2880 com_err(whoami, 0, "new login name OK");
2882 /* choose place for pobox, put in mid */
2884 ## repeat retrieve (mid = sh.mach_id, machname = m.name)
2885 ## where sh.service = "POP" and m.mach_id = sh.mach_id and
2886 ## sh.value2 - sh.value1 = max(sh.value2-sh.value1 where sh.service="POP")
2887 if (ingres_errno) return(mr_errcode);
2888 if (sqlca.sqlcode == 100) return(MR_NO_POBOX);
2890 /* change login name, set pobox */
2891 sprintf(buffer, "u.users_id = %d", users_id);
2892 incremental_before("users", buffer, 0);
2893 ## repeat replace u (#login = @login, status = 2, modtime = "now",
2894 ## modby = @who, modwith = @entity, potype="POP",
2895 ## pop_id = @mid, pmodtime="now", pmodby=@who,
2896 ## pmodwith=@entity)
2897 ## where u.#users_id = @users_id
2898 if (ingres_errno) return(mr_errcode);
2899 if (sqlca.sqlcode < 0 || sqlca.sqlerrd[2] != 1)
2900 return(MR_INTERNAL);
2901 set_pop_usage(mid, 1);
2902 com_err(whoami, 0, "set login name to %s and pobox to %s", login,
2904 incremental_after("users", buffer, 0);
2906 /* create group list */
2907 if (set_next_object_id("gid", "list"))
2909 if (set_next_object_id("list_id", "list"))
2912 EXEC SQL DECLARE v_cursor CURSOR FOR
2915 WHERE V.name = "list_id";
2916 EXEC SQL OPEN v_cursor;
2918 EXEC SQL FETCH v_cursor INTO :list_id;
2919 if (sqlca.sqlcode != 0) break;
2921 EXEC SQL CLOSE v_cursor;
2923 if (ingres_errno) return(mr_errcode);
2924 if (sqlca.sqlcode < 0 || sqlca.sqlerrd[2] != 1)
2925 return(MR_INTERNAL);
2926 incremental_clear_before();
2927 ## repeat append list (name = @login, #list_id = @list_id, active = 1,
2928 ## public = 0, hidden = 0, maillist = 0, group = 1,
2929 ## #gid = values_tbl.value, desc = "User Group",
2930 ## acl_type = "USER", acl_id = @users_id, modtime = "now",
2931 ## modby = @who, modwith = @entity)
2932 ## where values_tbl.name = "gid"
2933 if (ingres_errno) return(mr_errcode);
2934 if (sqlca.sqlcode < 0 || sqlca.sqlerrd[2] != 1)
2935 return(MR_INTERNAL);
2936 sprintf(buffer, "l.list_id = %d", list_id);
2937 incremental_after("list", buffer, 0);
2938 aargv[0] = (char *) list_id;
2940 aargv[2] = (char *) users_id;
2941 incremental_clear_before();
2942 ## repeat append imembers (#list_id = @list_id, member_type = "USER",
2943 ## member_id = @users_id, ref_count = 1, direct = 1)
2944 if (ingres_errno) return(mr_errcode);
2945 if (sqlca.sqlcode < 0 || sqlca.sqlerrd[2] != 1)
2946 return(MR_INTERNAL);
2948 incremental_after("members", 0, aargv);
2949 com_err(whoami, 0, "group list created");
2951 /* decide where to put filesystem */
2954 ## repeat retrieve (mid = n.mach_id, dir = trim(n.#dir), nid = n.nfsphys_id,
2955 ## flag = n.status, size = n.#size, alloc = n.allocated) {
2956 if ((flag & utype) && (size != 0) && (size - alloc > maxsize)) {
2957 maxsize = size - alloc;
2960 directory = strsave(dir);
2965 if (ingres_errno) return(mr_errcode);
2967 return(MR_NO_FILESYS);
2969 /* create filesystem */
2970 if (set_next_object_id("filsys_id", "filesys"))
2972 incremental_clear_before();
2973 ## repeat append filesys (filsys_id = values_tbl.value, phys_id = @pid,
2974 ## label = @login, type = "NFS", mach_id = @m_id,
2975 ## name = @directory + "/" + @login,
2976 ## mount = "/mit/" + @login,
2977 ## access = "w", comments = "User Locker",
2978 ## owner = @users_id, owners = @list_id, createflg = 1,
2979 ## lockertype = "HOMEDIR", modtime = "now",
2980 ## modby = @who, modwith = @entity)
2981 ## where values_tbl.name = "filsys_id"
2982 if (ingres_errno) return(mr_errcode);
2983 if (sqlca.sqlcode < 0 || sqlca.sqlerrd[2] != 1)
2984 return(MR_INTERNAL);
2985 incremental_after("filesys",
2986 "fs.filsys_id = values_tbl.value and values_tbl.name = \"filsys_id\"",
2988 com_err(whoami, 0, "filesys created on mach %d in %s/%s", m_id,
2992 ## repeat retrieve (quota = values_tbl.value) where values_tbl.name = "def_quota"
2993 if (ingres_errno) return(mr_errcode);
2994 if (sqlca.sqlcode < 0 || sqlca.sqlerrd[2] != 1)
2995 return(MR_NO_QUOTA);
2996 incremental_clear_before();
2997 ## repeat append #quota (entity_id = @users_id, filsys_id = values_tbl.value,
2999 ## #quota = @quota, phys_id = @pid, modtime = "now",
3000 ## modby = @who, modwith = @entity)
3001 ## where values_tbl.name = "filsys_id"
3002 if (ingres_errno) return(mr_errcode);
3003 if (sqlca.sqlcode < 0 || sqlca.sqlerrd[2] != 1)
3004 return(MR_INTERNAL);
3005 ## repeat replace nfsphys (allocated = nfsphys.allocated + @quota)
3006 ## where nfsphys.nfsphys_id = filesys.#phys_id and
3007 ## filesys.filsys_id = values_tbl.value and values_tbl.name = "filsys_id"
3008 if (ingres_errno) return(mr_errcode);
3009 if (sqlca.sqlcode < 0 || sqlca.sqlerrd[2] != 1)
3010 return(MR_INTERNAL);
3014 sprintf(buffer, "q.entity_id = %d and q.filsys_id = values_tbl.value and q.type = \"USER\" and values_tbl.name = \"filsys_id\"", users_id);
3015 incremental_after("quota", buffer, aargv);
3016 com_err(whoami, 0, "quota of %d assigned", quota);
3017 if (ingres_errno) return(mr_errcode);
3019 cache_entry(login, "USER", users_id);
3021 EXEC SQL UPDATE tblstats
3022 SET updates = tblstats.update + 1, modtime = "now"
3023 WHERE table_name = "users";
3025 EXEC SQL UPDATE tblstats
3026 SET appends = tblstats.appends + 1, modtime = "now"
3027 WHERE table_name = "list" OR table_name = "filesys"
3028 OR table_name = "quota";
3030 if (ingres_errno) return(mr_errcode);
3036 /** set_pop_usage - incr/decr usage count for pop server in serverhosts talbe
3040 ** delta (will be +/- 1)
3043 ** - incr/decr value field in serverhosts table for pop/mach_id
3047 static int set_pop_usage(id, count)
3051 EXEC SQL BEGIN DECLARE SECTION;
3054 EXEC SQL END DECLARE SECTION;
3056 EXEC SQL UPDATE serverhosts
3057 SET value1 = value1 + :n
3058 WHERE service = "POP" AND mach_id = :mach_id;
3060 if (ingres_errno) return(mr_errcode);
3066 /* Validation Routines */
3068 validate_row(q, argv, v)
3069 register struct query *q;
3071 register struct validate *v;
3073 EXEC SQL BEGIN DECLARE SECTION;
3079 EXEC SQL END DECLARE SECTION;
3081 /* build where clause */
3082 build_qual(v->qual, v->argc, argv, qual);
3084 /* setup ingres variables */
3089 if (log_flags & LOG_VALID)
3090 /* tell the logfile what we're doing */
3091 com_err(whoami, 0, "validating row: %s", qual);
3093 /* look for the record */
3094 ## range of rvar is tbl
3095 ## retrieve (rowcount = count(rvar.name where qual))
3096 if (ingres_errno) return(mr_errcode);
3097 if (rowcount == 0) return(MR_NO_MATCH);
3098 if (rowcount > 1) return(MR_NOT_UNIQUE);
3102 validate_fields(q, argv, vo, n)
3104 register char *argv[];
3105 register struct valobj *vo;
3108 register int status;
3113 if (log_flags & LOG_VALID)
3114 com_err(whoami, 0, "validating %s in %s: %s",
3115 vo->namefield, vo->table, argv[vo->index]);
3116 status = validate_name(argv, vo);
3120 if (log_flags & LOG_VALID)
3121 com_err(whoami, 0, "validating %s in %s: %s",
3122 vo->idfield, vo->table, argv[vo->index]);
3123 status = validate_id(argv, vo);
3127 if (log_flags & LOG_VALID)
3128 com_err(whoami, 0, "validating date: %s", argv[vo->index]);
3129 status = validate_date(argv, vo);
3133 if (log_flags & LOG_VALID)
3134 com_err(whoami, 0, "validating %s type: %s",
3135 vo->table, argv[vo->index]);
3136 status = validate_type(argv, vo);
3140 if (log_flags & LOG_VALID)
3141 com_err(whoami, 0, "validating typed data (%s): %s",
3142 argv[vo->index - 1], argv[vo->index]);
3143 status = validate_typedata(q, argv, vo);
3147 if (log_flags & LOG_VALID)
3148 com_err(whoami, 0, "validating rename %s in %s",
3149 argv[vo->index], vo->table);
3150 status = validate_rename(argv, vo);
3154 if (log_flags & LOG_VALID)
3155 com_err(whoami, 0, "validating chars: %s", argv[vo->index]);
3156 status = validate_chars(argv[vo->index]);
3164 status = lock_table(vo);
3168 if (status != MR_EXISTS) return(status);
3172 if (ingres_errno) return(mr_errcode);
3177 /* validate_chars: verify that there are no illegal characters in
3178 * the string. Legal characters are printing chars other than
3179 * ", *, ?, \, [ and ].
3181 static int illegalchars[] = {
3182 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
3183 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
3184 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
3185 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
3186 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ - O */
3187 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* P - _ */
3188 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
3189 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
3190 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3191 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3192 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3193 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3194 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3195 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3196 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3197 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3204 if (illegalchars[*s++])
3205 return(MR_BAD_CHAR);
3210 validate_id(argv, vo)
3212 register struct valobj *vo;
3214 EXEC SQL BEGIN DECLARE SECTION;
3220 EXEC SQL END DECLARE SECTION;
3225 name = argv[vo->index];
3227 namefield = vo->namefield;
3228 idfield = vo->idfield;
3230 if ((!strcmp(tbl, "users") && !strcmp(namefield, "login")) ||
3231 !strcmp(tbl, "machine") ||
3232 !strcmp(tbl, "filesys") ||
3233 !strcmp(tbl, "list") ||
3234 !strcmp(tbl, "cluster") ||
3235 !strcmp(tbl, "string")) {
3236 if (!strcmp(tbl, "machine"))
3237 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3238 status = name_to_id(name, tbl, &id);
3240 *(int *)argv[vo->index] = id;
3242 } else if (status == MR_NO_MATCH || status == MR_NOT_UNIQUE)
3248 if (!strcmp(namefield, "uid")) {
3249 ## retrieve (id = tbl.idfield) where tbl.namefield = int4(name)
3250 if (ingres_errno) return(mr_errcode);
3252 ## retrieve (id = table.idfield) where table.namefield = name
3253 if (ingres_errno) return(mr_errcode);
3255 if (sqlca.sqlcode < 0 || sqlca.sqlerrd[2] != 1)
3257 *(int *)argv[vo->index] = id;
3261 validate_name(argv, vo)
3263 register struct valobj *vo;
3265 EXEC SQL BEGIN DECLARE SECTION;
3270 EXEC SQL END DECLARE SECTION;
3273 name = argv[vo->index];
3275 namefield = vo->namefield;
3276 if (!strcmp(tbl, "servers") && !strcmp(namefield, "name")) {
3277 for (c = name; *c; c++)
3281 ## retrieve (rowcount = countu(tbl.namefield
3282 ## where tbl.namefield = name))
3283 if (ingres_errno) return(mr_errcode);
3284 return ((rowcount == 1) ? MR_EXISTS : vo->error);
3287 validate_date(argv, vo)
3291 EXEC SQL BEGIN DECLARE SECTION;
3295 EXEC SQL END DECLARE SECTION;
3297 idate = argv[vo->index];
3299 ## retrieve (dd = interval("years", date(idate) - date("today")))
3300 if (sqlca.sqlcode < 0 || dd > 5.0) return(MR_DATE);
3305 validate_rename(argv, vo)
3309 EXEC SQL BEGIN DECLARE SECTION;
3310 char *name, *tbl, *namefield, *idfield;
3312 EXEC SQL END DECLARE SECTION;
3316 c = name = argv[vo->index];
3318 if (illegalchars[*c++])
3319 return(MR_BAD_CHAR);
3321 /* minor kludge to upcasify machine names */
3322 if (!strcmp(tbl, "machine"))
3323 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3324 namefield = vo->namefield;
3325 idfield = vo->idfield;
3328 if (!strcmp(argv[vo->index], argv[vo->index - 1]))
3330 ## retrieve (id = any(tbl.namefield where tbl.namefield = name))
3331 if (ingres_errno) return(mr_errcode);
3337 status = name_to_id(name, tbl, &id);
3338 if (status == MR_NO_MATCH || id == *(int *)argv[vo->index - 1])
3345 validate_type(argv, vo)
3347 register struct valobj *vo;
3349 EXEC SQL BEGIN DECLARE SECTION;
3353 EXEC SQL END DECLARE SECTION;
3356 typename = vo->table;
3357 c = value = argv[vo->index];
3359 if (illegalchars[*c++])
3360 return(MR_BAD_CHAR);
3362 /* uppercase type fields */
3363 for (c = value; *c; c++) if (islower(*c)) *c = toupper(*c);
3365 ## repeat retrieve (exist = any(alias.trans where alias.name = @typename and
3366 ## alias.type = "TYPE" and alias.trans = @value))
3367 if (ingres_errno) return(mr_errcode);
3368 return (exist ? MR_EXISTS : vo->error);
3371 /* validate member or type-specific data field */
3373 validate_typedata(q, argv, vo)
3374 register struct query *q;
3375 register char *argv[];
3376 register struct valobj *vo;
3378 EXEC SQL BEGIN DECLARE SECTION;
3381 char data_type[129];
3383 EXEC SQL END DECLARE SECTION;
3389 /* get named object */
3390 name = argv[vo->index];
3392 /* get field type string (known to be at index-1) */
3393 field_type = argv[vo->index-1];
3395 /* get corresponding data type associated with field type name */
3396 ## repeat retrieve (data_type = alias.trans)
3397 ## where alias.#name = @field_type and alias.type = "TYPEDATA"
3398 if (ingres_errno) return(mr_errcode);
3399 if (sqlca.sqlcode < 0 || sqlca.sqlerrd[2] != 1)
3402 /* now retrieve the record id corresponding to the named object */
3403 if (index(data_type, ' '))
3404 *index(data_type, ' ') = 0;
3405 if (!strcmp(data_type, "user")) {
3407 status = name_to_id(name, data_type, &id);
3408 if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
3410 if (status) return(status);
3411 } else if (!strcmp(data_type, "list")) {
3413 status = name_to_id(name, data_type, &id);
3414 if (status && status == MR_NOT_UNIQUE)
3416 if (status == MR_NO_MATCH) {
3417 /* if idfield is non-zero, then if argv[0] matches the string
3418 * that we're trying to resolve, we should get the value of
3419 * values_tbl.[idfield] for the id.
3421 if (vo->idfield && !strcmp(argv[0], argv[vo->index])) {
3422 set_next_object_id(q->validate->object_id, q->rtable);
3424 ## repeat retrieve (id = values_tbl.value) where values_tbl.#name = @name
3425 if (sqlca.sqlcode < 0 || sqlca.sqlerrd[2] != 1)
3429 } else if (status) return(status);
3430 } else if (!strcmp(data_type, "machine")) {
3432 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3433 status = name_to_id(name, data_type, &id);
3434 if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
3436 if (status) return(status);
3437 } else if (!strcmp(data_type, "string")) {
3439 status = name_to_id(name, data_type, &id);
3440 if (status && status == MR_NOT_UNIQUE)
3442 if (status == MR_NO_MATCH) {
3443 if (q->type != APPEND && q->type != UPDATE) return(MR_STRING);
3444 ## retrieve (id = values_tbl.value) where values_tbl.#name = "strings_id"
3446 ## replace values_tbl.(value = id) where values_tbl.#name = "strings_id"
3447 ## append to strings (string_id = id, string = name)
3448 } else if (status) return(status);
3449 } else if (!strcmp(data_type, "none")) {
3455 /* now set value in argv */
3456 *(int *)argv[vo->index] = id;
3462 /* Lock the table named by the validation object */
3467 EXEC SQL BEGIN DECLARE SECTION;
3468 char *tbl, *idfield;
3470 EXEC SQL END DECLARE SECTION;
3473 idfield = vo->idfield;
3474 ## replace tbl (modtime = "now") where tbl.idfield = 0
3475 if (ingres_errno) return(mr_errcode);
3476 if (sqlca.sqlcode < 0 || sqlca.sqlerrd[2] != 1)
3483 /* Check the database at startup time. For now this just resets the
3484 * inprogress flags that the DCM uses.
3487 sanity_check_database()