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"
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)
60 build_qual(q->qual, q->argc, argv, qual);
61 ## range of u is users
62 ## retrieve (id = u.users_id) where qual
63 ## inquire_equel(rowcount = "rowcount")
64 if (rowcount != 1 || id != cl->users_id)
72 /* access_list - check access for most list operations
74 * Inputs: argv[0] - list_id
76 * argv[2] - member ID (only for queries "amtl" and "dmfl")
77 * argv[7] - group IID (only for query "ulis")
80 * - check that client is a member of the access control list
81 * - OR, if the query is add_member_to_list or delete_member_from_list
82 * and the list is public, allow access if client = member
85 access_list(q, argv, cl)
90 ## int list_id, acl_id, flags, rowcount, gid;
93 int client_id, status;
95 list_id = *(int *)argv[0];
96 ## repeat retrieve (acl_id = list.#acl_id, acl_type = list.#acl_type,
97 ## gid = list.#gid, flags = list.#public)
98 ## where list.#list_id = @list_id
99 ## inquire_equel(rowcount = "rowcount")
103 /* parse client structure */
104 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
107 /* if amtl or dmfl and list is public allow client to add or delete self */
108 if (((!strcmp("amtl", q->shortname) && flags) ||
109 (!strcmp("dmfl", q->shortname))) &&
110 (!strcmp("USER", argv[1]))) {
111 if (*(int *)argv[2] == client_id) return(MR_SUCCESS);
112 /* if update_list, don't allow them to change the GID */
113 } else if (!strcmp("ulis", q->shortname)) {
114 if ((!strcmp(argv[7], UNIQUE_GID) && (gid != -1)) ||
115 (strcmp(argv[7], UNIQUE_GID) && (gid != atoi(argv[7]))))
119 /* check for client in access control list */
120 status = find_member(acl_type, acl_id, client_type, client_id, 0);
121 if (!status) return(MR_PERM);
127 /* access_visible_list - allow access to list only if it is not hidden,
128 * or if the client is on the ACL
130 * Inputs: argv[0] - list_id
131 * cl - client identifier
134 access_visible_list(q, argv, cl)
139 ## int list_id, acl_id, flags, rowcount;
142 int client_id, status;
144 list_id = *(int *)argv[0];
145 ## repeat retrieve (flags = list.hidden, acl_id = list.#acl_id,
146 ## acl_type = list.#acl_type) where list.#list_id = @list_id
147 ## inquire_equel(rowcount = "rowcount")
154 /* parse client structure */
155 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
158 /* check for client in access control list */
159 status = find_member(acl_type, acl_id, client_type, client_id, 0);
167 /* access_vis_list_by_name - allow access to list only if it is not hidden,
168 * or if the client is on the ACL
170 * Inputs: argv[0] - list name
171 * cl - client identifier
174 access_vis_list_by_name(q, argv, cl)
179 ## int acl_id, flags, rowcount;
180 ## char acl_type[9], *listname;
182 int client_id, status;
185 ## repeat retrieve (flags = list.hidden, acl_id = list.#acl_id,
186 ## acl_type = list.#acl_type) where list.#name = @listname
187 ## inquire_equel(rowcount = "rowcount");
195 /* parse client structure */
196 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
199 /* check for client in access control list */
200 status = find_member(acl_type, acl_id, client_type, client_id, 0);
208 /* access_member - allow user to access member of type "USER" and name matches
209 * username, or to access member of type "LIST" and list is one that user is
210 * on the acl of, or the list is visible.
213 access_member(q, argv, cl)
218 if (!strcmp(argv[0], "LIST") || !strcmp(argv[0], "RLIST"))
219 return(access_visible_list(q, &argv[1], cl));
221 if (!strcmp(argv[0], "USER") || !strcmp(argv[0], "RUSER")) {
222 if (cl->users_id == *(int *)argv[1])
230 /* access_qgli - special access routine for Qualified_get_lists. Allows
231 * access iff argv[0] == "TRUE" and argv[2] == "FALSE".
234 access_qgli(q, argv, cl)
239 if (!strcmp(argv[0], "TRUE") && !strcmp(argv[2], "FALSE"))
245 /* access_service - allow access if user is on ACL of service. Don't
246 * allow access if a wildcard is used.
249 access_service(q, argv, cl)
254 ## int acl_id, rowcount;
255 ## char *name, acl_type[9];
256 int client_id, status;
260 ## repeat retrieve (acl_id = servers.#acl_id, acl_type = servers.#acl_type)
261 ## where servers.#name = uppercase(@name)
262 ## inquire_equel(rowcount = "rowcount")
266 /* parse client structure */
267 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
270 /* check for client in access control list */
271 status = find_member(acl_type, acl_id, client_type, client_id, 0);
272 if (!status) return(MR_PERM);
279 /* access_filesys - verify that client is owner or on owners list of filesystem
283 access_filesys(q, argv, cl)
288 ## int rowcount, users_id, list_id;
290 int status, client_id;
294 ## repeat retrieve (users_id = filesys.owner, list_id = filesys.owners)
295 ## where filesys.label = @name
296 ## inquire_equel(rowcount = "rowcount")
300 if (users_id == cl->users_id)
302 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
304 status = find_member("LIST", list_id, client_type, client_id, 0);
315 /* Setup routine for add_user
317 * Inputs: argv[0] - login
322 * - if argv[1] == UNIQUE_UID then set argv[1] = next(uid)
323 * - if argv[0] == UNIQUE_LOGIN then set argv[0] = "#<uid>"
326 setup_ausr(q, argv, cl)
328 register char *argv[];
331 ## int nuid, rowcount;
335 /* this is currently disabled because we need an index on ID's
336 * before it can run in finite time.
338 mit_id = argv[U_MITID];
339 ## retrieve (rowcount = any(u.#mit_id where u.#mit_id = mit_id))
340 if (ingres_errno) return(mr_errcode);
341 if (rowcount) return(MR_EXISTS);
344 if (!strcmp(argv[1], UNIQUE_UID) || atoi(argv[1]) == -1) {
345 if (set_next_object_id("uid", "users"))
346 return(MR_INGRES_ERR);
347 ## repeat retrieve (nuid = values.value) where values.name = "uid"
348 ## inquire_equel(rowcount = "rowcount")
351 sprintf(argv[1], "%d", nuid);
354 if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[1]) == -1) {
355 sprintf(argv[0], "#%s", argv[1]);
362 /* setup_dusr - verify that the user is no longer being referenced
363 * and may safely be deleted.
366 int setup_dusr(q, argv)
372 id = *(int *)argv[0];
374 /* For now, only allow users to be deleted if their status is 0 */
375 ## repeat retrieve (flag = u.status) where u.users_id = @id
376 if (flag != 0 && flag != 4)
379 ## repeat delete quota where quota.entity_id = @id and quota.type = "USER"
380 ## repeat delete krbmap where krbmap.users_id = @id
381 ## repeat retrieve (flag = any(imembers.member_id where imembers.member_id=@id
382 ## and imembers.member_type = "USER"))
385 ## repeat retrieve (flag = any(filesys.label where filesys.owner=@id))
388 ## repeat retrieve (flag = any(list.name where list.acl_id=@id and
389 ## list.acl_type = "USER"))
392 ## repeat retrieve (flag = any(servers.name where servers.acl_id=@id and
393 ## servers.acl_type = "USER"))
396 ## repeat retrieve (flag=any(hostaccess.acl_id where hostaccess.acl_id=@id and
397 ## hostaccess.acl_type = "USER"))
406 /* setup_spop: verify that there is already a valid POP machine_id in the
407 * pop_id field. Also take care of keeping track of the post office usage.
409 int setup_spop(q, argv)
413 ## int id, mid, flag;
416 id = *(int *)argv[0];
417 ## repeat retrieve (type = u.potype, mid = u.pop_id,
418 ## flag = any(machine.name where machine.mach_id = u.pop_id
419 ## and u.pop_id != 0 and u.users_id = @id))
420 ## where u.users_id = @id
423 if (strcmp(strtrim(type), "POP"))
424 set_pop_usage(mid, 1);
429 /* setup_dpob: Take care of keeping track of the post office usage.
431 int setup_dpob(q, argv)
438 user = *(int *)argv[0];
439 ## repeat retrieve (type = u.potype, id = u.pop_id)
440 ## where u.users_id = @user
441 if (ingres_errno) return(mr_errcode);
443 if (!strcmp(strtrim(type), "POP"))
444 set_pop_usage(id, -1);
449 /* setup_dmac - verify that the machine is no longer being referenced
450 * and may safely be deleted.
453 int setup_dmac(q, argv)
459 id = *(int *)argv[0];
460 ## repeat retrieve (flag = any(users.login where users.potype = "POP"
461 ## and users.pop_id=@id))
464 ## repeat retrieve (flag = any(serverhosts.mach_id
465 ## where serverhosts.mach_id=@id))
468 ## repeat retrieve (flag = any(nfsphys.mach_id where nfsphys.mach_id=@id))
471 ## repeat retrieve (flag = any(hostaccess.mach_id where hostaccess.mach_id=@id))
474 ## repeat retrieve (flag = any(printcap.mach_id where printcap.mach_id=@id))
477 ## repeat retrieve (flag = any(printcap.quotaserver where printcap.quotaserver=@id))
480 ## repeat retrieve (flag = any(palladium.mach_id where palladium.mach_id=@id))
484 ## repeat delete mcmap where mcmap.mach_id = @id
485 if (ingres_errno) return(mr_errcode);
490 /* setup_dclu - verify that the cluster is no longer being referenced
491 * and may safely be deleted.
494 int setup_dclu(q, argv)
500 id = *(int *)argv[0];
501 ## repeat retrieve (flag = any(mcmap.mach_id where mcmap.clu_id=@id))
504 ## repeat retrieve (flag = any(svc.clu_id where svc.clu_id=@id))
513 /* setup_alis - if argv[5] is non-zero and argv[6] is UNIQUE_ID, then allocate
514 * a new gid and put it in argv[6]. Otherwise if argv[6] is UNIQUE_ID but
515 * argv[5] is not, then remember that UNIQUE_ID is being stored by putting
516 * a -1 there. Remember that this is also used for ulis, with the indexes
520 int setup_alis(q, argv)
528 if (!strcmp(q->shortname, "alis"))
530 else if (!strcmp(q->shortname, "ulis"))
533 if (!strcmp(argv[idx], UNIQUE_GID) || atoi(argv[idx]) == -1) {
534 if (atoi(argv[idx - 1])) {
535 if (set_next_object_id("gid", "list"))
536 return(MR_INGRES_ERR);
537 ## repeat retrieve (ngid = values.value) where values.name = "gid"
538 if (ingres_errno) return(mr_errcode);
539 sprintf(argv[idx], "%d", ngid);
541 strcpy(argv[idx], "-1");
549 /* setup_dlist - verify that the list is no longer being referenced
550 * and may safely be deleted.
553 int setup_dlis(q, argv)
559 id = *(int *)argv[0];
560 ## repeat retrieve (flag = any(imembers.member_id where imembers.member_id=@id
561 ## and imembers.member_type = "LIST"))
564 ## repeat retrieve (flag = any(imembers.member_id where imembers.list_id=@id))
567 ## repeat retrieve (flag = any(filesys.label where filesys.owners=@id))
570 ## repeat retrieve (flag = any(capacls.tag where capacls.list_id=@id))
573 ## repeat retrieve (flag = any(list.name where list.acl_id=@id and
574 ## list.acl_type = "LIST" and list.list_id != @id))
577 ## repeat retrieve (flag = any(servers.name where servers.acl_id=@id and
578 ## servers.acl_type = "LIST"))
581 ## repeat retrieve (flag = any(quota.entity_id where quota.entity_id=@id and
582 ## quota.type = "GROUP"))
585 ## repeat retrieve (flag=any(hostaccess.acl_id where hostaccess.acl_id=@id and
586 ## hostaccess.acl_type = "LIST"))
589 ## repeat retrieve (flag = any(zephyr.class
590 ## where zephyr.xmt_type = "LIST" and zephyr.xmt_id = @id or
591 ## zephyr.sub_type = "LIST" and zephyr.sub_id = @id or
592 ## zephyr.iws_type = "LIST" and zephyr.iws_id = @id or
593 ## zephyr.iui_type = "LIST" and zephyr.iui_id = @id))
602 /* setup_dsin - verify that the service is no longer being referenced
603 * and may safely be deleted.
606 int setup_dsin(q, argv)
614 ## repeat retrieve (flag = any(serverhosts.service
615 ## where serverhosts.service=uppercase(@name)))
618 ## repeat retrieve (flag = servers.inprogress) where servers.#name = @name
627 /* setup_dshi - verify that the service-host is no longer being referenced
628 * and may safely be deleted.
631 int setup_dshi(q, argv)
639 id = *(int *)argv[1];
640 ## repeat retrieve (flag=serverhosts.inprogress)
641 ## where serverhosts.service=uppercase(@name) and serverhosts.mach_id=@id
651 ** setup_add_filesys - verify existance of referenced file systems
663 ** * extract directory prefix from name
664 ** * verify mach_id/dir in nfsphys
665 ** * verify access in {r, w, R, W}
667 ** Side effect: sets variable var_phys_id to the ID of the physical
668 ** filesystem (nfsphys_id for NFS, 0 for RVD)
671 ** MR_NFS - specified directory not exported
672 ** MR_FILESYS_ACCESS - invalid filesys access
676 ##static int var_phys_id;
685 ## char ftype[32], *access;
688 mach_id = *(int *)argv[2];
693 sprintf(ftype, "fs_access_%s", type);
694 ## retrieve (ok = any(alias.trans where alias.name = ftype and
695 ## alias.type = "TYPE" and alias.trans = access))
696 if (ingres_errno) return(mr_errcode);
697 if (ok == 0) return(MR_FILESYS_ACCESS);
699 if (!strcmp(type, "NFS"))
700 return (check_nfs(mach_id, name, access));
706 /* Verify the arguments, depending on the FStype. Also, if this is an
707 * NFS filesystem, then update any quotas for that filesystem to reflect
711 setup_ufil(q, argv, cl)
718 ## int fid, total, who;
719 ## char *entity, ftype[32], *access;
722 mach_id = *(int *)argv[3];
726 fid = *(int *)argv[0];
730 sprintf(ftype, "fs_access_%s", type);
731 ## retrieve (total = any(alias.trans where alias.name = ftype and
732 ## alias.type = "TYPE" and alias.trans = access))
733 if (ingres_errno) return(mr_errcode);
734 if (total == 0) return(MR_FILESYS_ACCESS);
736 if (!strcmp(type, "NFS")) {
737 status = check_nfs(mach_id, name, access);
738 ## replace quota (phys_id = var_phys_id) where quota.filsys_id = fid
739 if (ingres_errno) return(mr_errcode);
741 } else if (!strcmp(type, "AFS")) {
743 ## retrieve (total = sum(quota.quota where quota.filsys_id = fid
744 ## and quota.phys_id != 0))
745 if (ingres_errno) return(mr_errcode);
747 ## append quota (quota = total, filsys_id = fid,
748 ## phys_id = 0, entity_id = 0, type = "ANY",
749 ## modtime = "now", modby = who, modwith = entity)
750 if (ingres_errno) return(mr_errcode);
753 ## replace quota (phys_id = 0) where quota.filsys_id = fid
754 if (ingres_errno) return(mr_errcode);
760 /* Find the NFS physical partition that the named directory is on.
761 * This is done by comparing the dir against the mount point of the
762 * partition. To make sure we get the correct match when there is
763 * more than one, we sort the query in reverse order by dir name.
766 ##check_nfs(mach_id, name, access)
778 ## range of np is nfsphys
779 ## repeat retrieve (var_phys_id = np.#nfsphys_id, dir = trim(np.#dir))
780 ## where np.#mach_id = @mach_id sort by #dir:d {
784 if (*cp1++ != *cp2) break;
798 /* setup_dfil: free any quota records and fsgroup info associated with
799 * a filesystem when it is deleted. Also adjust the allocation numbers.
802 setup_dfil(q, argv, cl)
809 id = *(int *)argv[0];
810 ## range of q is quota
811 ## range of n is nfsphys
812 ## repeat replace n (allocated=n.allocated-sum(q.quota where q.filsys_id=@id))
813 ## where n.nfsphys_id = filesys.phys_id and filesys.filsys_id = @id
815 ## repeat delete q where q.filsys_id = @id
816 ## repeat delete fsgroup where fsgroup.filsys_id = @id
817 ## repeat delete fsgroup where fsgroup.group_id = @id
818 if (ingres_errno) return(mr_errcode);
823 /* setup_dnfp: check to see that the nfs physical partition does not have
824 * any filesystems assigned to it before allowing it to be deleted.
827 setup_dnfp(q, argv, cl)
834 id = *(int *)argv[0];
835 ## repeat retrieve (exists = any(filesys.label where filesys.phys_id = @id))
844 /* setup_dqot: Remove allocation from nfsphys before deleting quota.
845 * argv[0] = filsys_id
846 * argv[1] = type if "update_quota" or "delete_quota"
847 * argv[2 or 1] = users_id or list_id
850 setup_dqot(q, argv, cl)
855 ## int quota, fs, id;
858 fs = *(int *)argv[0];
859 if (!strcmp(q->name, "update_quota") || !strcmp(q->name, "delete_quota")) {
861 id = *(int *)argv[2];
864 id = *(int *)argv[1];
867 ## range of q is #quota
868 ## repeat retrieve (quota = q.#quota) where q.type = @qtype and
869 ## q.entity_id = @id and q.filsys_id = @fs
870 ## repeat replace nfsphys (allocated = nfsphys.allocated - @quota)
871 ## where nfsphys.nfsphys_id = filesys.#phys_id and filesys.filsys_id = @fs
872 if (ingres_errno) return(mr_errcode);
877 /* setup_sshi: don't exclusive lock the machine table during
878 * set_server_host_internal.
881 setup_sshi(q, argv, cl)
886 ## set lockmode session where readlock = system
890 /* setup add_kerberos_user_mapping: add the string to the string
891 * table if necessary.
894 setup_akum(q, argv, cl)
903 if (name_to_id(name, "STRING", &id) != MR_SUCCESS) {
904 if (q->type != APPEND) return(MR_STRING);
905 ## range of v is values
906 ## retrieve (id = v.value) where v.#name = "strings_id"
908 ## replace v (value = id) where v.#name = "strings_id"
909 ## append to strings (string_id = id, string = name)
910 cache_entry(name, "STRING", id);
912 if (ingres_errno) return(mr_errcode);
913 *(int *)argv[1] = id;
919 /* FOLLOWUP ROUTINES */
921 /* generic set_modtime routine. This takes the table name from the query,
922 * and will update the modtime, modby, and modwho fields in the entry in
923 * the table whose name field matches argv[0].
926 set_modtime(q, argv, cl)
931 ## char *name, *entity, *table;
939 ## replace table (modtime = "now", modby = who, modwith = entity)
940 ## where table.#name = name
944 /* generic set_modtime_by_id routine. This takes the table name from
945 * the query, and the id name from the validate record,
946 * and will update the modtime, modby, and modwho fields in the entry in
947 * the table whose id matches argv[0].
950 set_modtime_by_id(q, argv, cl)
955 ## char *entity, *table, *id_name;
961 id_name = q->validate->object_id;
963 id = *(int *)argv[0];
964 ## replace table (modtime = "now", modby = who, modwith = entity)
965 ## where table.id_name = id
970 /* Sets the finger modtime on a user record. The users_id will be in argv[0].
973 set_finger_modtime(q, argv, cl)
978 ## int users_id, who;
983 users_id = *(int *)argv[0];
985 ## repeat replace u (fmodtime = "now", fmodby = @who, fmodwith = @entity)
986 ## where u.#users_id = @users_id
991 /* Sets the pobox modtime on a user record. The users_id will be in argv[0].
994 set_pobox_modtime(q, argv, cl)
999 ## int users_id, who;
1002 entity = cl->entity;
1003 who = cl->client_id;
1004 users_id = *(int *)argv[0];
1006 ## repeat replace users (pmodtime = "now", pmodby = @who, pmodwith = @entity)
1007 ## where users.#users_id = @users_id
1012 /* Like set_modtime, but uppercases the name first.
1015 set_uppercase_modtime(q, argv, cl)
1020 ## char *name, *entity, *table;
1023 entity = cl->entity;
1024 who = cl->client_id;
1028 ## replace table (modtime = "now", modby = who, modwith = entity)
1029 ## where table.#name = uppercase(name)
1034 /* Sets the modtime on the machine whose mach_id is in argv[0]. This routine
1035 * is necessary for add_machine_to_cluster becuase the table that query
1036 * operates on is "mcm", not "machine".
1039 set_mach_modtime_by_id(q, argv, cl)
1047 entity = cl->entity;
1048 who = cl->client_id;
1050 id = *(int *)argv[0];
1051 ## repeat replace machine (modtime = "now", modby = @who, modwith = @entity)
1052 ## where machine.mach_id = @id
1057 /* Sets the modtime on the cluster whose mach_id is in argv[0]. This routine
1058 * is necessary for add_cluster_data and delete_cluster_data becuase the
1059 * table that query operates on is "svc", not "cluster".
1062 set_cluster_modtime_by_id(q, argv, cl)
1070 entity = cl->entity;
1071 who = cl->client_id;
1073 id = *(int *)argv[0];
1074 ## repeat replace cluster (modtime = "now", modby = @who, modwith = @entity)
1075 ## where cluster.clu_id = @id
1080 /* sets the modtime on the serverhost where the service name is in argv[0]
1081 * and the mach_id is in argv[1].
1084 set_serverhost_modtime(q, argv, cl)
1089 ## char *entity, *serv;
1092 entity = cl->entity;
1093 who = cl->client_id;
1096 id = *(int *)argv[1];
1097 ## repeat replace sh (modtime = "now", modby = @who, modwith = @entity)
1098 ## where sh.service = uppercase(@serv) and sh.mach_id = @id
1103 /* sets the modtime on the nfsphys where the mach_id is in argv[0] and the
1104 * directory name is in argv[1].
1107 set_nfsphys_modtime(q, argv, cl)
1112 ## char *entity, *dir;
1115 entity = cl->entity;
1116 who = cl->client_id;
1118 id = *(int *)argv[0];
1120 ## repeat replace np (modtime = "now", modby = @who, modwith = @entity)
1121 ## where np.#dir = @dir and np.mach_id = @id
1126 /* sets the modtime on a filesystem, where argv[0] contains the filesys
1130 set_filesys_modtime(q, argv, cl)
1135 ## char *label, *entity;
1138 entity = cl->entity;
1139 who = cl->client_id;
1142 if (!strcmp(q->shortname, "ufil"))
1145 ## repeat replace fs (modtime = "now", modby = @who, modwith = @entity,
1146 ## #phys_id = @var_phys_id) where fs.#label = @label
1151 /* sets the modtime on a zephyr class, where argv[0] contains the class
1155 set_zephyr_modtime(q, argv, cl)
1160 ## char *class, *entity;
1163 entity = cl->entity;
1164 who = cl->client_id;
1168 ## repeat replace z (modtime = "now", modby = @who, modwith = @entity)
1169 ## where z.#class = @class
1174 /* fixes the modby field. This will be the second to last thing in the
1175 * argv, the argv length is determined from the query structure. It is
1176 * passed as a pointer to an integer. This will either turn it into a
1177 * username, or # + the users_id.
1179 followup_fix_modby(q, sq, v, action, actarg, cl)
1181 register struct save_queue *sq;
1183 register int (*action)();
1184 register int actarg;
1188 char **argv, *malloc();
1192 while (sq_get_data(sq, &argv)) {
1195 status = id_to_name(id, "USER", &argv[i]);
1197 status = id_to_name(-id, "STRING", &argv[i]);
1198 if (status && status != MR_NO_MATCH)
1200 (*action)(q->vcnt, argv, actarg);
1201 for (j = 0; j < q->vcnt; j++)
1211 ** followup_ausr - add finger and pobox entries, set_user_modtime
1214 ** argv[0] - login (add_user)
1215 ** argv[3] - last name
1216 ** argv[4] - first name
1217 ** argv[5] - middle name
1221 followup_ausr(q, argv, cl)
1227 ## char *login, *entity;
1228 ## char fullname[129];
1231 who = cl->client_id;
1232 entity = cl->entity;
1234 /* build fullname */
1235 if (strlen(argv[4]) && strlen(argv[5]))
1236 sprintf(fullname, "%s %s %s", argv[4], argv[5], argv[3]);
1237 else if (strlen(argv[4]))
1238 sprintf(fullname, "%s %s", argv[4], argv[3]);
1240 sprintf(fullname, "%s", argv[3]);
1242 /* create finger entry, pobox & set modtime on user */
1243 ## repeat replace u (modtime = "now", modby=@who, modwith=@entity,
1244 ## #fullname=@fullname, mit_affil = u.mit_year,
1245 ## fmodtime="now", fmodby=@who, fmodwith=@entity,
1246 ## potype="NONE", pmodtime="now", pmodby=@who, pmodwith=@entity)
1247 ## where u.#login = @login
1253 /* followup_gpob: fixes argv[2] based on the IDs currently there and the
1254 * type in argv[1]. Then completes the upcall to the user.
1256 * argv[2] is of the form "123:234" where the first integer is the machine
1257 * ID if it is a pop box, and the second is the string ID if it is an SMTP
1258 * box. argv[1] should be "POP", "SMTP", or "NONE". Boxes of type NONE
1262 followup_gpob(q, sq, v, action, actarg, cl)
1263 register struct query *q;
1264 register struct save_queue *sq;
1265 register struct validate *v;
1266 register int (*action)();
1270 char **argv, *index();
1272 int mid, sid, status;
1275 while (sq_get_data(sq, &argv)) {
1276 mr_trim_args(2, argv);
1278 p = index(argv[2], ':');
1280 mid = atoi(argv[2]);
1283 if (!strcmp(ptype, "POP")) {
1284 status = id_to_name(mid, "MACHINE", &argv[2]);
1285 if (status == MR_NO_MATCH)
1287 } else if (!strcmp(ptype, "SMTP")) {
1288 status = id_to_name(sid, "STRING", &argv[2]);
1289 if (status == MR_NO_MATCH)
1291 } else /* ptype == "NONE" */ {
1294 if (status) return(status);
1296 if (!strcmp(q->shortname, "gpob")) {
1297 sid = atoi(argv[4]);
1299 status = id_to_name(sid, "USER", &argv[4]);
1301 status = id_to_name(-sid, "STRING", &argv[4]);
1303 if (status && status != MR_NO_MATCH) return(status);
1305 (*action)(q->vcnt, argv, actarg);
1307 /* free saved data */
1315 return (MR_SUCCESS);
1319 /* followup_glin: fix the ace_name in argv[8]. argv[7] will contain the
1320 * ace_type: "LIST", "USER", or "NONE". Decode the id in argv[8] into the
1321 * proper name based on the type, and repace that string in the argv.
1322 * Also fixes the modby field by called followup_fix_modby.
1325 followup_glin(q, sq, v, action, actarg, cl)
1326 register struct query *q;
1327 register struct save_queue *sq;
1328 register struct validate *v;
1329 register int (*action)();
1333 char **argv, *malloc(), *realloc(), *type;
1334 int id, i, idx, status;
1337 if (!strcmp(q->shortname, "gsin"))
1340 while (sq_get_data(sq, &argv)) {
1341 mr_trim_args(q->vcnt, argv);
1343 id = atoi(argv[i = q->vcnt - 2]);
1345 status = id_to_name(id, "USER", &argv[i]);
1347 status = id_to_name(-id, "STRING", &argv[i]);
1348 if (status && status != MR_NO_MATCH)
1351 id = atoi(argv[idx]);
1352 type = argv[idx - 1];
1354 if (!strcmp(type, "LIST")) {
1355 status = id_to_name(id, "LIST", &argv[idx]);
1356 } else if (!strcmp(type, "USER")) {
1357 status = id_to_name(id, "USER", &argv[idx]);
1358 } else if (!strcmp(type, "KERBEROS")) {
1359 status = id_to_name(id, "STRING", &argv[idx]);
1360 } else if (!strcmp(type, "NONE")) {
1363 argv[idx] = strsave("NONE");
1367 argv[idx] = strsave("???");
1369 if (status && status != MR_NO_MATCH)
1372 if (!strcmp(q->shortname, "glin") && atoi(argv[6]) == -1) {
1373 argv[6] = realloc(argv[6], strlen(UNIQUE_GID) + 1);
1374 strcpy(argv[6], UNIQUE_GID);
1378 (*action)(q->vcnt, argv, actarg);
1380 /* free saved data */
1381 for (i = 0; i < q->vcnt; i++)
1387 return (MR_SUCCESS);
1391 /* followup_gqot: Fix the entity name, directory name & modby fields
1392 * argv[0] = filsys_id
1394 * argv[2] = entity_id
1395 * argv[3] = ascii(quota)
1398 followup_gqot(q, sq, v, action, actarg, cl)
1400 register struct save_queue *sq;
1402 register int (*action)();
1403 register int actarg;
1407 char **argv, *malloc();
1408 ## int id, rowcount;
1409 ## char *name, *label;
1412 if (!strcmp(q->name, "get_quota") ||
1413 !strcmp(q->name, "get_quota_by_filesys"))
1417 while (sq_get_data(sq, &argv)) {
1419 switch (argv[1][0]) {
1421 status = id_to_name(atoi(argv[2]), "USER", &argv[2]);
1425 status = id_to_name(atoi(argv[2]), "LIST", &argv[2]);
1429 argv[2] = strsave("system:anyuser");
1433 argv[2] = malloc(8);
1434 sprintf(argv[2], "%d", id);
1437 id = atoi(argv[idx]);
1439 argv[idx] = malloc(256);
1443 ## repeat retrieve (name = filesys.#name) where filesys.#label = @label
1445 ## repeat retrieve (name = nfsphys.dir) where nfsphys.nfsphys_id = @id
1447 ## inquire_equel(rowcount = "rowcount")
1448 if (rowcount != 1) {
1449 sprintf(argv[idx], "#%d", id);
1452 id = atoi(argv[idx+3]);
1454 status = id_to_name(id, "USER", &argv[idx+3]);
1456 status = id_to_name(-id, "STRING", &argv[idx+3]);
1457 if (status && status != MR_NO_MATCH)
1459 (*action)(q->vcnt, argv, actarg);
1460 for (j = 0; j < q->vcnt; j++)
1469 /* followup_aqot: Add allocation to nfsphys after creating quota.
1470 * argv[0] = filsys_id
1471 * argv[1] = type if "add_quota" or "update_quota"
1473 * argv[3 or 2] = ascii(quota)
1476 followup_aqot(q, argv, cl)
1481 ## int quota, id, fs, who;
1482 ## char *entity, *qtype;
1484 fs = *(int *)argv[0];
1485 if (!strcmp(q->name, "add_quota") || !strcmp(q->name, "update_quota")) {
1487 id = *(int *)argv[2];
1488 quota = atoi(argv[3]);
1491 id = *(int *)argv[1];
1492 quota = atoi(argv[2]);
1494 who = cl->client_id;
1495 entity = cl->entity;
1497 ## repeat replace q (modtime = "now", modby = @who, modwith = @entity)
1498 ## where q.filsys_id = @fs and q.type = @qtype and q.entity_id = @id
1499 ## repeat replace nfsphys (allocated = nfsphys.allocated + @quota)
1500 ## where nfsphys.nfsphys_id = filesys.#phys_id and filesys.filsys_id = @fs
1501 if (ingres_errno) return(mr_errcode);
1506 followup_gpce(q, sq, v, action, actarg, cl)
1508 register struct save_queue *sq;
1510 register int (*action)();
1511 register int actarg;
1515 char **argv, *malloc();
1519 while (sq_get_data(sq, &argv)) {
1520 id = atoi(argv[PCAP_QSERVER]);
1521 status = id_to_name(id, "MACHINE", &argv[PCAP_QSERVER]);
1522 if (status) return (status);
1525 status = id_to_name(id, "USER", &argv[i]);
1527 status = id_to_name(-id, "STRING", &argv[i]);
1528 if (status && status != MR_NO_MATCH)
1530 (*action)(q->vcnt, argv, actarg);
1531 for (j = 0; j < q->vcnt; j++)
1543 followup_gzcl(q, sq, v, action, actarg, cl)
1544 register struct query *q;
1545 register struct save_queue *sq;
1546 register struct validate *v;
1547 register int (*action)();
1554 while (sq_get_data(sq, &argv)) {
1555 mr_trim_args(q->vcnt, argv);
1557 id = atoi(argv[i = q->vcnt - 2]);
1559 status = id_to_name(id, "USER", &argv[i]);
1561 status = id_to_name(-id, "STRING", &argv[i]);
1562 if (status && status != MR_NO_MATCH)
1565 for (i = 1; i < 8; i+=2) {
1566 id = atoi(argv[i+1]);
1567 if (!strcmp(argv[i], "LIST")) {
1568 status = id_to_name(id, "LIST", &argv[i+1]);
1569 } else if (!strcmp(argv[i], "USER")) {
1570 status = id_to_name(id, "USER", &argv[i+1]);
1571 } else if (!strcmp(argv[i], "KERBEROS")) {
1572 status = id_to_name(id, "STRING", &argv[i+1]);
1573 } else if (!strcmp(argv[i], "NONE")) {
1576 argv[i+1] = strsave("NONE");
1580 argv[i+1] = strsave("???");
1582 if (status && status != MR_NO_MATCH)
1587 (*action)(q->vcnt, argv, actarg);
1589 /* free saved data */
1590 for (i = 0; i < q->vcnt; i++)
1602 followup_gsha(q, sq, v, action, actarg, cl)
1603 register struct query *q;
1604 register struct save_queue *sq;
1605 register struct validate *v;
1606 register int (*action)();
1613 while (sq_get_data(sq, &argv)) {
1614 mr_trim_args(q->vcnt, argv);
1618 status = id_to_name(id, "USER", &argv[4]);
1620 status = id_to_name(-id, "STRING", &argv[4]);
1621 if (status && status != MR_NO_MATCH)
1625 if (!strcmp(argv[1], "LIST")) {
1626 status = id_to_name(id, "LIST", &argv[2]);
1627 } else if (!strcmp(argv[1], "USER")) {
1628 status = id_to_name(id, "USER", &argv[2]);
1629 } else if (!strcmp(argv[1], "KERBEROS")) {
1630 status = id_to_name(id, "STRING", &argv[2]);
1631 } else if (!strcmp(argv[1], "NONE")) {
1634 argv[2] = strsave("NONE");
1638 argv[2] = strsave("???");
1640 if (status && status != MR_NO_MATCH)
1644 (*action)(q->vcnt, argv, actarg);
1646 /* free saved data */
1647 for (i = 0; i < q->vcnt; i++)
1657 /* Special query routines */
1659 /* set_pobox - this does all of the real work.
1660 * argv = user_id, type, box
1661 * if type is POP, then box should be a machine, and its ID should be put in
1662 * pop_id. If type is SMTP, then box should be a string and its ID should
1663 * be put in box_id. If type is NONE, then box doesn't matter.
1666 int set_pobox(q, argv, cl)
1671 ## int user, id, rowcount;
1672 ## char *box, potype[9];
1676 user = *(int *)argv[0];
1678 ## repeat retrieve (id = users.pop_id, potype = users.#potype)
1679 ## where users.users_id = @user
1680 if (ingres_errno) return(mr_errcode);
1681 if (!strcmp(strtrim(potype), "POP"))
1682 set_pop_usage(id, -1);
1684 if (!strcmp(argv[1], "POP")) {
1685 status = name_to_id(box, "MACHINE", &id);
1686 if (status == MR_NO_MATCH)
1690 ## repeat replace users (#potype = "POP", pop_id = @id)
1691 ## where users.users_id = @user
1692 set_pop_usage(id, 1);
1693 } else if (!strcmp(argv[1], "SMTP")) {
1694 if (index(box, '/') || index(box, '|'))
1695 return(MR_BAD_CHAR);
1696 status = name_to_id(box, "STRING", &id);
1697 if (status == MR_NO_MATCH) {
1698 ## repeat retrieve (id = values.value) where values.name = "strings_id"
1700 ## repeat replace values (value = @id) where values.name = "strings_id"
1701 ## append to strings (string_id = id, string = box)
1704 ## repeat replace users (#potype = "SMTP", box_id = @id)
1705 ## where users.users_id = @user
1706 } else /* argv[1] == "NONE" */ {
1707 ## repeat replace users (#potype = "NONE") where users.users_id = @user
1710 set_pobox_modtime(q, argv, cl);
1711 ## repeat replace tblstats (updates = tblstats.updates + 1, modtime = "now")
1712 ## where tblstats.#table = "users"
1713 if (ingres_errno) return(mr_errcode);
1718 /* get_list_info: passed a wildcard list name, returns lots of stuff about
1719 * each list. This is tricky: first build a queue of all requested
1720 * data. Rest of processing consists of fixing gid, ace_name, and modby.
1723 get_list_info(q, aargv, cl, action, actarg)
1724 register struct query *q;
1727 register int (*action)();
1730 char *argv[13], *malloc(), *realloc();
1731 ## char *name, acl_type[9], listname[33], active[5], public[5], hidden[5];
1732 ## char maillist[5], group[5], gid[6], acl_name[256], desc[256], modtime[27];
1733 ## char modby[256], modwith[9];
1734 ## int id, rowcount, acl_id, hid, modby_id;
1735 int returned, status;
1736 struct save_queue *sq, *sq_create();
1738 returned = rowcount = 0;
1742 ## range of l is list
1743 ## repeat retrieve (id = l.list_id) where l.#name = @name {
1744 sq_save_data(sq, id);
1747 if (ingres_errno) return(mr_errcode);
1749 return(MR_NO_MATCH);
1751 argv[0] = listname; argv[1] = active; argv[2] = public; argv[3] = hidden;
1752 argv[4] = maillist; argv[5] = group; argv[6] = gid; argv[7] = acl_type;
1753 argv[9] = desc; argv[10] = modtime; argv[12] = modwith;
1755 while (sq_get_data(sq, &id)) {
1759 ## repeat retrieve (listname = l.#name, active = text(l.#active),
1760 ## public = text(l.#public), hidden = text(l.#hidden),
1761 ## hid = l.#hidden, maillist = text(l.#maillist),
1762 ## group = text(l.#group), gid = text(l.#gid),
1763 ## acl_type = trim(l.#acl_type), acl_id = l.#acl_id,
1764 ## desc = l.#desc, modtime = l.#modtime, modby_id = l.#modby,
1765 ## modwith =l.#modwith)
1766 ## where l.list_id = @id
1767 if (ingres_errno) return(mr_errcode);
1769 if (atoi(gid) == -1)
1770 argv[6] = UNIQUE_GID;
1772 argv[8] = malloc(0);
1773 if (!strcmp(acl_type, "LIST")) {
1774 status = id_to_name(acl_id, "LIST", &argv[8]);
1775 } else if (!strcmp(acl_type, "USER")) {
1776 status = id_to_name(acl_id, "USER", &argv[8]);
1777 } else if (!strcmp(acl_type, "KERBEROS")) {
1778 status = id_to_name(acl_id, "STRING", &argv[8]);
1779 } else if (!strcmp(acl_type, "NONE")) {
1782 argv[8] = strsave("NONE");
1786 argv[8] = strsave("???");
1788 if (status && status != MR_NO_MATCH) return(status);
1790 argv[11] = malloc(0);
1792 status = id_to_name(modby_id, "USER", &argv[11]);
1794 status = id_to_name(-modby_id, "STRING", &argv[11]);
1795 if (status && status != MR_NO_MATCH) return(status);
1797 mr_trim_args(q->vcnt, argv);
1799 (*action)(q->vcnt, argv, actarg);
1805 if (ingres_errno) return(mr_errcode);
1806 return (MR_SUCCESS);
1810 /* Add_member_to_list: do list flattening as we go! MAXLISTDEPTH is
1811 * how many different ancestors a member is allowed to have.
1814 #define MAXLISTDEPTH 1024
1816 int add_member_to_list(q, argv, cl)
1821 ## int id, lid, mid, exists, error, who, ref;
1822 ## char *mtype, dtype[9], *entity;
1823 int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a;
1824 int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d;
1826 char *dtypes[MAXLISTDEPTH];
1827 char *iargv[3], *buf;
1829 ## range of m is imembers
1830 lid = *(int *)argv[0];
1832 mid = *(int *)argv[2];
1833 /* if the member is already a direct member of the list, punt */
1834 ## repeat retrieve (exists = any(m.list_id where m.list_id=@lid and
1835 ## m.member_id = @mid and m.member_type = @mtype
1836 ## and m.direct = 1))
1839 if (!strcasecmp(mtype, "STRING")) {
1841 status = id_to_name(mid, "STRING", &buf);
1842 if (status) return(status);
1843 if (index(buf, '/') || index(buf, '|')) {
1845 return(MR_BAD_CHAR);
1853 ## repeat retrieve (id = m.list_id, ref = m.ref_count)
1854 ## where m.member_id = @lid and m.member_type = "LIST" {
1856 ancestors[acount++] = id;
1857 if (acount >= MAXLISTDEPTH) {
1861 if (ingres_errno) return(mr_errcode);
1862 if (acount >= MAXLISTDEPTH) {
1863 return(MR_INTERNAL);
1865 descendants[0] = mid;
1870 if (!strcmp(mtype, "LIST")) {
1871 ## repeat retrieve (id = m.member_id, dtype = m.member_type,
1872 ## ref = m.ref_count)
1873 ## where m.list_id = @mid {
1876 dtypes[dcount] = "LIST";
1879 dtypes[dcount] = "USER";
1882 dtypes[dcount] = "STRING";
1885 dtypes[dcount] = "KERBEROS";
1892 descendants[dcount++] = id;
1893 if (dcount >= MAXLISTDEPTH) {
1898 if (ingres_errno) return(mr_errcode);
1900 return(MR_INTERNAL);
1902 for (a = 0; a < acount; a++) {
1904 for (d = 0; d < dcount; d++) {
1905 mid = descendants[d];
1907 if (mid == lid && !strcmp(mtype, "LIST")) {
1908 return(MR_LISTLOOP);
1910 ## repeat retrieve (exists = any(m.ref_count where m.list_id = @lid
1911 ## and m.member_id = @mid
1912 ## and m.member_type = @mtype))
1913 ref = aref[a] * dref[d];
1915 if (a == 0 && d == 0)
1916 ## replace m (ref_count = m.ref_count+ref, direct = 1)
1917 ## where m.list_id = lid and m.member_id = mid and
1918 ## m.member_type = mtype
1920 ## replace m (ref_count = m.ref_count+ref)
1921 ## where m.list_id = lid and m.member_id = mid and
1922 ## m.member_type = mtype
1924 incremental_clear_before();
1925 if (a == 0 && d == 0)
1926 ## append imembers (list_id=lid, member_id = mid, direct = 1,
1927 ## member_type=mtype, ref_count = 1)
1929 ## append imembers (list_id=lid, member_id = mid,
1930 ## member_type=mtype, ref_count = ref)
1931 iargv[0] = (char *)lid;
1933 iargv[2] = (char *)mid;
1934 incremental_after("members", 0, iargv);
1938 lid = *(int *)argv[0];
1939 entity = cl->entity;
1940 who = cl->client_id;
1941 ## repeat replace list (modtime = "now", modby = @who, modwith = @entity)
1942 ## where list.#list_id = @lid
1943 if (ingres_errno) return(mr_errcode);
1948 /* Delete_member_from_list: do list flattening as we go!
1951 int delete_member_from_list(q, argv, cl)
1956 ## int id, lid, mid, cnt, exists, error, who, ref;
1957 ## char *mtype, dtype[9], *entity;
1958 int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a;
1959 int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d;
1960 char *dtypes[MAXLISTDEPTH];
1963 ## range of m is imembers
1964 lid = *(int *)argv[0];
1966 mid = *(int *)argv[2];
1967 /* if the member is not a direct member of the list, punt */
1968 ## repeat retrieve (exists = any(m.list_id where m.list_id=@lid and
1969 ## m.member_id = @mid and m.member_type = @mtype
1970 ## and m.direct = 1))
1971 if (ingres_errno) return(mr_errcode);
1973 return(MR_NO_MATCH);
1977 ## repeat retrieve (id = m.list_id, ref = m.ref_count)
1978 ## where m.member_id = @lid and m.member_type = "LIST" {
1980 ancestors[acount++] = id;
1981 if (acount >= MAXLISTDEPTH)
1984 if (ingres_errno) return(mr_errcode);
1985 if (acount >= MAXLISTDEPTH)
1986 return(MR_INTERNAL);
1987 descendants[0] = mid;
1992 if (!strcmp(mtype, "LIST")) {
1993 ## repeat retrieve (id = m.member_id, dtype = m.member_type,
1994 ## ref = m.ref_count)
1995 ## where m.list_id = @mid {
1998 dtypes[dcount] = "LIST";
2001 dtypes[dcount] = "USER";
2004 dtypes[dcount] = "STRING";
2007 dtypes[dcount] = "KERBEROS";
2014 descendants[dcount++] = id;
2015 if (dcount >= MAXLISTDEPTH)
2018 if (ingres_errno) return(mr_errcode);
2020 return(MR_INTERNAL);
2022 for (a = 0; a < acount; a++) {
2024 for (d = 0; d < dcount; d++) {
2025 mid = descendants[d];
2027 if (mid == lid && !strcmp(mtype, "LIST")) {
2028 return(MR_LISTLOOP);
2030 ## repeat retrieve (cnt = m.ref_count)
2031 ## where m.list_id = @lid and m.member_id = @mid
2032 ## and m.member_type = @mtype
2033 ref = aref[a] * dref[d];
2035 iargv[0] = (char *)lid;
2037 iargv[2] = (char *)mid;
2038 incremental_before("members", 0, iargv);
2039 ## delete m where m.list_id = lid and m.member_id = mid and
2040 ## m.member_type = mtype
2041 incremental_clear_after();
2042 } else if (a == 0 && d == 0) {
2043 ## replace m (ref_count = m.ref_count-ref, direct = 0)
2044 ## where m.list_id = lid and m.member_id = mid and
2045 ## m.member_type = mtype
2047 ## replace m (ref_count = m.ref_count-ref)
2048 ## where m.list_id = lid and m.member_id = mid and
2049 ## m.member_type = mtype
2053 lid = *(int *)argv[0];
2054 entity = cl->entity;
2055 who = cl->client_id;
2056 ## repeat replace list (modtime = "now", modby = @who, modwith = @entity)
2057 ## where list.#list_id = @lid
2058 if (ingres_errno) return(mr_errcode);
2063 /* get_ace_use - given a type and a name, return a type and a name.
2064 * The ace_type is one of "LIST", "USER", "RLIST", or "RUSER" in argv[0],
2065 * and argv[1] will contain the ID of the entity in question. The R*
2066 * types mean to recursively look at every containing list, not just
2067 * when the object in question is a direct member. On return, the
2068 * usage type will be one of LIST, SERVICE, FILESYS, QUOTA, QUERY, or ZEPHYR.
2071 int get_ace_use(q, argv, cl, action, actarg)
2080 ## int aid, listid, id;
2081 struct save_queue *sq, *sq_create();
2083 ## range of m is imembers
2085 aid = *(int *)argv[1];
2086 if (!strcmp(atype, "LIST") || !strcmp(atype, "USER") ||
2087 !strcmp(atype, "KERBEROS")) {
2088 return(get_ace_internal(atype, aid, action, actarg));
2092 if (!strcmp(atype, "RLIST")) {
2093 sq_save_data(sq, aid);
2094 /* get all the list_id's of containing lists */
2095 ## repeat retrieve (listid = m.list_id)
2096 ## where m.member_type = "LIST" and m.member_id = @id {
2097 sq_save_unique_data(sq, listid);
2099 /* now process each one */
2100 while (sq_get_data(sq, &id)) {
2101 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2106 if (!strcmp(atype, "RUSER")) {
2107 ## repeat retrieve (listid = m.list_id)
2108 ## where m.member_type = "USER" and m.member_id = @aid {
2109 sq_save_data(sq, listid);
2111 /* now process each one */
2112 while (sq_get_data(sq, &id)) {
2113 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2116 if (get_ace_internal("USER", aid, action, actarg) == MR_SUCCESS)
2120 if (!strcmp(atype, "RKERBERO")) {
2121 ## repeat retrieve (listid = m.list_id)
2122 ## where m.member_type = "KERBEROS" and m.member_id = @aid {
2123 sq_save_data(sq, listid);
2125 /* now process each one */
2126 while (sq_get_data(sq, &id)) {
2127 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2130 if (get_ace_internal("KERBEROS", aid, action, actarg) == MR_SUCCESS)
2135 if (ingres_errno) return(mr_errcode);
2136 if (!found) return(MR_NO_MATCH);
2141 /* This looks up a single list or user for ace use. atype must be "USER"
2142 * or "LIST", and aid is the ID of the corresponding object. This is used
2143 * by get_ace_use above.
2146 ##get_ace_internal(atype, aid, action, actarg)
2157 if (!strcmp(atype, "LIST")) {
2158 rargv[0] = "FILESYS";
2159 ## repeat retrieve (name = filesys.label)
2160 ## where filesys.owners = @aid {
2161 (*action)(2, rargv, actarg);
2166 ## repeat retrieve (name = capacls.capability)
2167 ## where capacls.list_id = @aid {
2168 (*action)(2, rargv, actarg);
2171 } else if (!strcmp(atype, "USER")) {
2172 rargv[0] = "FILESYS";
2173 ## repeat retrieve (name = filesys.label)
2174 ## where filesys.owner = @aid {
2175 (*action)(2, rargv, actarg);
2181 ## repeat retrieve (name = list.#name)
2182 ## where list.acl_type = @atype and list.acl_id = @aid {
2183 (*action)(2, rargv, actarg);
2187 rargv[0] = "SERVICE";
2188 ## repeat retrieve (name = servers.#name)
2189 ## where servers.acl_type = @atype and servers.acl_id = @aid {
2190 (*action)(2, rargv, actarg);
2194 rargv[0] = "HOSTACCESS";
2195 ## repeat retrieve (name = machine.#name)
2196 ## where machine.mach_id = hostaccess.mach_id and
2197 ## hostaccess.acl_type = @atype and hostaccess.acl_id = @aid {
2198 (*action)(2, rargv, actarg);
2201 rargv[0] = "ZEPHYR";
2202 ## repeat retrieve (name = zephyr.class)
2203 ## where zephyr.xmt_type = @atype and zephyr.xmt_id = @aid or
2204 ## zephyr.sub_type = @atype and zephyr.sub_id = @aid or
2205 ## zephyr.iws_type = @atype and zephyr.iws_id = @aid or
2206 ## zephyr.iui_type = @atype and zephyr.iui_id = @aid {
2207 (*action)(2, rargv, actarg);
2211 if (!found) return(MR_NO_MATCH);
2216 /* get_lists_of_member - given a type and a name, return the name and flags
2217 * of all of the lists of the given member. The member_type is one of
2218 * "LIST", "USER", "STRING", "RLIST", "RUSER", or "RSTRING" in argv[0],
2219 * and argv[1] will contain the ID of the entity in question. The R*
2220 * types mean to recursively look at every containing list, not just
2221 * when the object in question is a direct member.
2224 int get_lists_of_member(q, argv, cl, action, actarg)
2231 int found = 0, direct = 1;
2234 ## int aid, listid, id;
2235 ## char name[33], active[5], public[5], hidden[5], maillist[5], group[5];
2238 aid = *(int *)argv[1];
2239 if (!strcmp(atype, "RLIST")) {
2243 if (!strcmp(atype, "RUSER")) {
2247 if (!strcmp(atype, "RSTRING")) {
2251 if (!strcmp(atype, "RKERBEROS")) {
2260 rargv[4] = maillist;
2262 ## range of m is imembers
2264 ## repeat retrieve (name = list.#name, active = text(list.#active),
2265 ## public = text(list.#public), hidden = text(list.#hidden),
2266 ## maillist = text(list.#maillist), group = text(list.#group))
2267 ## where list.list_id = m.list_id and m.direct = 1 and
2268 ## m.member_type = @atype and m.member_id = @aid {
2269 (*action)(6, rargv, actarg);
2273 ## repeat retrieve (name = list.#name, active = text(list.#active),
2274 ## public = text(list.#public), hidden = text(list.#hidden),
2275 ## maillist = text(list.#maillist), group = text(list.#group))
2276 ## where list.list_id = m.list_id and
2277 ## m.member_type = @atype and m.member_id = @aid {
2278 (*action)(6, rargv, actarg);
2283 if (ingres_errno) return(mr_errcode);
2284 if (!found) return(MR_NO_MATCH);
2289 /* qualified_get_lists: passed "TRUE", "FALSE", or "DONTCARE" for each of
2290 * the five flags associated with each list. It will return the name of
2291 * each list that meets the quailifications. It does this by building a
2292 * where clause based on the arguments, then doing a retrieve.
2295 static char *lflags[5] = { "active", "public", "hidden", "maillist", "group" };
2297 int qualified_get_lists(q, argv, cl, action, actarg)
2304 return(qualified_get(q, argv, action, actarg, "l.list_id != 0",
2305 "l", "name", lflags));
2309 /** get_members_of_list - optimized query for retrieval of list members
2312 ** argv[0] - list_id
2315 ** - retrieve USER members, then LIST members, then STRING members
2318 get_members_of_list(q, argv, cl, action, actarg)
2325 ## int list_id, member_id;
2326 ## char member_name[129], member_type[9];
2329 struct save_queue *sq;
2331 list_id = *(int *)argv[0];
2335 ## repeat retrieve (member_type = imembers.#member_type,
2336 ## member_id = imembers.#member_id)
2337 ## where imembers.#list_id = @list_id and imembers.direct = 1 {
2340 sq_save_data(sq, (member_type[0] << 24) | (member_id & 0xffffff));
2342 if (members <= 49) {
2343 targv[1] = malloc(0);
2344 while (sq_remove_data(sq, &member_id)) {
2345 switch (member_id >> 24) {
2348 id_to_name(member_id & 0xffffff, "USER", &targv[1]);
2349 (*action)(2, targv, actarg);
2353 id_to_name(member_id & 0xffffff, "LIST", &targv[1]);
2354 (*action)(2, targv, actarg);
2357 targv[0] = "STRING";
2358 id_to_name(member_id & 0xffffff, "STRING", &targv[1]);
2359 (*action)(2, targv, actarg);
2362 targv[0] = "KERBEROS";
2363 id_to_name(member_id & 0xffffff, "STRING", &targv[1]);
2364 (*action)(2, targv, actarg);
2368 return(MR_INTERNAL);
2377 targv[1] = member_name;
2379 ## range of m is imembers
2380 ## repeat retrieve (member_name = users.login)
2381 ## where m.#list_id = @list_id and m.#member_type = "USER"
2382 ## and m.#member_id = users.users_id and m.direct = 1
2383 ## sort by #member_name
2385 (*action)(2, targv, actarg);
2387 if (ingres_errno) return(mr_errcode);
2390 ## repeat retrieve (member_name = list.name)
2391 ## where m.#list_id = @list_id and m.#member_type = "LIST"
2392 ## and m.#member_id = list.#list_id and m.direct = 1
2393 ## sort by #member_name
2395 (*action)(2, targv, actarg);
2397 if (ingres_errno) return(mr_errcode);
2399 targv[0] = "STRING";
2400 ## repeat retrieve (member_name = strings.string)
2401 ## where m.#list_id = @list_id and m.#member_type = "STRING"
2402 ## and m.#member_id = strings.string_id and m.direct = 1
2403 ## sort by #member_name
2405 (*action)(2, targv, actarg);
2407 if (ingres_errno) return(mr_errcode);
2409 targv[0] = "KERBEROS";
2410 ## repeat retrieve (member_name = strings.string)
2411 ## where m.#list_id = @list_id and m.#member_type = "KERBEROS"
2412 ## and m.#member_id = strings.string_id and m.direct = 1
2413 ## sort by #member_name
2415 (*action)(2, targv, actarg);
2417 if (ingres_errno) return(mr_errcode);
2423 /* count_members_of_list: this is a simple query, but it cannot be done
2424 * through the dispatch table.
2427 int count_members_of_list(q, argv, cl, action, actarg)
2434 ## int list, ct = 0;
2435 char *rargv[1], countbuf[5];
2437 list = *(int *)argv[0];
2438 rargv[0] = countbuf;
2439 ## repeat retrieve (ct = count(imembers.list_id
2440 ## where imembers.list_id = @list and
2441 ## imembers.direct = 1))
2442 if (ingres_errno) return(mr_errcode);
2443 sprintf(countbuf, "%d", ct);
2444 (*action)(1, rargv, actarg);
2449 /* qualified_get_server: passed "TRUE", "FALSE", or "DONTCARE" for each of
2450 * the three flags associated with each service. It will return the name of
2451 * each service that meets the quailifications. It does this by building a
2452 * where clause based on the arguments, then doing a retrieve.
2455 static char *sflags[3] = { "enable", "inprogress", "harderror" };
2457 int qualified_get_server(q, argv, cl, action, actarg)
2464 return(qualified_get(q, argv, action, actarg, "s.name != \"\"",
2465 "s", "name", sflags));
2469 /* generic qualified get routine, used by qualified_get_lists,
2470 * qualified_get_server, and qualified_get_serverhost.
2472 * start - a simple where clause, must not be empty
2473 * range - the name of the range variable
2474 * field - the field to return
2475 * flags - an array of strings, names of the flag variables
2478 int qualified_get(q, argv, action, actarg, start, range, field, flags)
2488 ## char name[33], qual[256], *rvar, *rtbl, *rfield;
2489 char *rargv[1], buf[32];
2492 strcpy(qual, start);
2493 for (i = 0; i < q->argc; i++) {
2494 if (!strcmp(argv[i], "TRUE")) {
2495 sprintf(buf, " and %s.%s != 0", range, flags[i]);
2496 (void) strcat(qual, buf);
2497 } else if (!strcmp(argv[i], "FALSE")) {
2498 sprintf(buf, " and %s.%s = 0", range, flags[i]);
2499 (void) strcat(qual, buf);
2507 ## range of rvar is rtbl
2508 ## retrieve (name = rvar.rfield) where qual {
2509 (*action)(1, rargv, actarg);
2511 if (ingres_errno) return(mr_errcode);
2512 ## inquire_equel(rowcount = "rowcount")
2514 return(MR_NO_MATCH);
2519 /* qualified_get_serverhost: passed "TRUE", "FALSE", or "DONTCARE" for each of
2520 * the five flags associated with each serverhost. It will return the name of
2521 * each service and host that meets the quailifications. It does this by
2522 * building a where clause based on the arguments, then doing a retrieve.
2525 static char *shflags[6] = { "service", "enable", "override", "success",
2526 "inprogress", "hosterror" };
2528 int qualified_get_serverhost(q, argv, cl, action, actarg)
2535 ## char sname[33], mname[33], qual[256];
2536 char *rargv[2], buf[32];
2539 sprintf(qual, "machine.mach_id = sh.mach_id and sh.service = uppercase(\"%s\")",
2541 for (i = 1; i < q->argc; i++) {
2542 if (!strcmp(argv[i], "TRUE")) {
2543 sprintf(buf, " and sh.%s != 0", shflags[i]);
2545 } else if (!strcmp(argv[i], "FALSE")) {
2546 sprintf(buf, " and sh.%s = 0", shflags[i]);
2553 ## range of sh is serverhosts
2554 ## retrieve (sname = sh.service, mname = machine.name) where qual {
2555 (*action)(2, rargv, actarg);
2557 if (ingres_errno) return(mr_errcode);
2558 ## inquire_equel(rowcount = "rowcount")
2560 return(MR_NO_MATCH);
2565 /* register_user - change user's login name and allocate a pobox, group,
2566 * filesystem, and quota for them. The user's status must start out as 0,
2567 * and is left as 2. Arguments are: user's UID, new login name, and user's
2568 * type for filesystem allocation (MR_FS_STUDENT, MR_FS_FACULTY,
2569 * MR_FS_STAFF, MR_FS_MISC).
2572 register_user(q, argv, cl)
2577 ## char *login, dir[65], *entity, *directory, machname[33];
2578 ## int who, rowcount, mid, uid, users_id, flag, utype, nid, list_id, quota;
2579 ## int size, alloc, pid, m_id;
2580 char buffer[256], *aargv[3];
2583 entity = cl->entity;
2584 who = cl->client_id;
2586 uid = atoi(argv[0]);
2588 utype = atoi(argv[2]);
2590 ## range of u is users
2591 ## range of l is list
2592 ## range of sh is serverhosts
2593 ## range of n is nfsphys
2594 ## range of m is machine
2597 ## repeat retrieve (users_id = u.#users_id)
2598 ## where u.#uid = @uid and (u.status = 0 or u.status = 5 or u.status = 6)
2599 ## inquire_equel(rowcount = "rowcount");
2601 return(MR_NO_MATCH);
2603 return(MR_NOT_UNIQUE);
2605 /* check new login name */
2606 ## repeat retrieve (flag = any(u.#login where u.#login = @login and
2607 ## u.#users_id != users_id))
2608 if (ingres_errno) return(mr_errcode);
2609 if (flag) return(MR_IN_USE);
2610 ## repeat retrieve (flag = any(l.#name where l.#name = @login))
2611 if (ingres_errno) return(mr_errcode);
2612 if (flag) return(MR_IN_USE);
2613 ## repeat retrieve (flag = any(filesys.#label where filesys.#label = @login))
2614 if (ingres_errno) return(mr_errcode);
2615 if (flag) return(MR_IN_USE);
2616 com_err(whoami, 0, "new login name OK");
2618 /* choose place for pobox, put in mid */
2619 ## repeat retrieve (mid = sh.mach_id, machname = m.name)
2620 ## where sh.service = "POP" and m.mach_id = sh.mach_id and
2621 ## sh.value2 - sh.value1 = max(sh.value2-sh.value1 where sh.service="POP")
2622 if (ingres_errno) return(mr_errcode);
2623 ## inquire_equel(rowcount = "rowcount");
2625 return(MR_NO_POBOX);
2627 /* change login name, set pobox */
2628 sprintf(buffer, "u.users_id = %d", users_id);
2629 incremental_before("users", buffer, 0);
2630 ## repeat replace u (#login = @login, status = 2, modtime = "now",
2631 ## modby = @who, modwith = @entity, potype="POP",
2632 ## pop_id = @mid, pmodtime="now", pmodby=@who,
2633 ## pmodwith=@entity)
2634 ## where u.#users_id = @users_id
2635 ## inquire_equel(rowcount = "rowcount");
2636 if (ingres_errno) return(mr_errcode);
2638 return(MR_INTERNAL);
2639 set_pop_usage(mid, 1);
2640 com_err(whoami, 0, "set login name to %s and pobox to %s", login,
2642 incremental_after("users", buffer, 0);
2644 /* create group list */
2645 if (set_next_object_id("gid", "list"))
2647 if (set_next_object_id("list_id", "list"))
2649 ## repeat retrieve (list_id = values.value) where values.name = "list_id"
2650 if (ingres_errno) return(mr_errcode);
2651 ## inquire_equel(rowcount = "rowcount");
2653 return(MR_INTERNAL);
2654 incremental_clear_before();
2655 ## repeat append list (name = @login, #list_id = @list_id, active = 1,
2656 ## public = 0, hidden = 0, maillist = 0, group = 1,
2657 ## #gid = values.value, desc = "User Group",
2658 ## acl_type = "USER", acl_id = @users_id, modtime = "now",
2659 ## modby = @who, modwith = @entity)
2660 ## where values.name = "gid"
2661 if (ingres_errno) return(mr_errcode);
2662 ## inquire_equel(rowcount = "rowcount");
2664 return(MR_INTERNAL);
2665 sprintf(buffer, "l.list_id = %d", list_id);
2666 incremental_after("list", buffer, 0);
2667 aargv[0] = (char *) list_id;
2669 aargv[2] = (char *) users_id;
2670 incremental_clear_before();
2671 ## repeat append imembers (#list_id = @list_id, member_type = "USER",
2672 ## member_id = @users_id, ref_count = 1, direct = 1)
2673 if (ingres_errno) return(mr_errcode);
2674 ## inquire_equel(rowcount = "rowcount");
2676 return(MR_INTERNAL);
2677 incremental_after("members", 0, aargv);
2678 com_err(whoami, 0, "group list created");
2680 /* decide where to put filesystem */
2683 ## repeat retrieve (mid = n.mach_id, dir = trim(n.#dir), nid = n.nfsphys_id,
2684 ## flag = n.status, size = n.#size, alloc = n.allocated) {
2685 if ((flag & utype) && (size != 0) && (size - alloc > maxsize)) {
2686 maxsize = size - alloc;
2689 directory = strsave(dir);
2694 if (ingres_errno) return(mr_errcode);
2696 return(MR_NO_FILESYS);
2698 /* create filesystem */
2699 if (set_next_object_id("filsys_id", "filesys"))
2701 incremental_clear_before();
2702 ## repeat append filesys (filsys_id = values.value, phys_id = @pid,
2703 ## label = @login, type = "NFS", mach_id = @m_id,
2704 ## name = @directory + "/" + @login,
2705 ## mount = "/mit/" + @login,
2706 ## access = "w", comments = "User Locker",
2707 ## owner = @users_id, owners = @list_id, createflg = 1,
2708 ## lockertype = "HOMEDIR", modtime = "now",
2709 ## modby = @who, modwith = @entity)
2710 ## where values.name = "filsys_id"
2711 if (ingres_errno) return(mr_errcode);
2712 ## inquire_equel(rowcount = "rowcount");
2714 return(MR_INTERNAL);
2715 incremental_after("filesys",
2716 "fs.filsys_id = values.value and values.name = \"filsys_id\"",
2718 com_err(whoami, 0, "filesys created on mach %d in %s/%s", m_id,
2722 ## repeat retrieve (quota = values.value) where values.name = "def_quota"
2723 if (ingres_errno) return(mr_errcode);
2724 ## inquire_equel(rowcount = "rowcount");
2726 return(MR_NO_QUOTA);
2727 incremental_clear_before();
2728 ## repeat append #quota (entity_id = @users_id, filsys_id = values.value,
2730 ## #quota = @quota, phys_id = @pid, modtime = "now",
2731 ## modby = @who, modwith = @entity)
2732 ## where values.name = "filsys_id"
2733 if (ingres_errno) return(mr_errcode);
2734 ## inquire_equel(rowcount = "rowcount");
2736 return(MR_INTERNAL);
2737 ## repeat replace nfsphys (allocated = nfsphys.allocated + @quota)
2738 ## where nfsphys.nfsphys_id = filesys.#phys_id and
2739 ## filesys.filsys_id = values.value and values.name = "filsys_id"
2740 if (ingres_errno) return(mr_errcode);
2741 ## inquire_equel(rowcount = "rowcount");
2743 return(MR_INTERNAL);
2747 sprintf(buffer, "q.entity_id = %d and q.filsys_id = values.value and q.type = \"USER\" and values.name = \"filsys_id\"", users_id);
2748 incremental_after("quota", buffer, aargv);
2749 com_err(whoami, 0, "quota of %d assigned", quota);
2750 if (ingres_errno) return(mr_errcode);
2752 cache_entry(login, "USER", users_id);
2754 ## repeat replace tblstats (updates = tblstats.updates + 1, modtime = "now")
2755 ## where tblstats.table = "users"
2756 ## repeat replace tblstats (appends = tblstats.appends + 1, modtime = "now")
2757 ## where tblstats.table = "list" or tblstats.table = "filesys" or
2758 ## tblstats.table = "quota"
2759 if (ingres_errno) return(mr_errcode);
2765 /** set_pop_usage - incr/decr usage count for pop server in serverhosts talbe
2769 ** delta (will be +/- 1)
2772 ** - incr/decr value field in serverhosts table for pop/mach_id
2776 static int set_pop_usage(id, count)
2780 ## int mach_id = id;
2783 ## repeat replace serverhosts (value1 = serverhosts.value1 + @n)
2784 ## where serverhosts.service = "POP" and serverhosts.#mach_id = @mach_id
2786 if (ingres_errno) return(mr_errcode);
2792 /* Validation Routines */
2794 validate_row(q, argv, v)
2795 register struct query *q;
2797 register struct validate *v;
2805 /* build where clause */
2806 build_qual(v->qual, v->argc, argv, qual);
2808 /* setup ingres variables */
2813 if (log_flags & LOG_VALID)
2814 /* tell the logfile what we're doing */
2815 com_err(whoami, 0, "validating row: %s", qual);
2817 /* look for the record */
2818 ## range of rvar is table
2819 ## retrieve (rowcount = count(rvar.name where qual))
2820 if (ingres_errno) return(mr_errcode);
2821 if (rowcount == 0) return(MR_NO_MATCH);
2822 if (rowcount > 1) return(MR_NOT_UNIQUE);
2826 validate_fields(q, argv, vo, n)
2828 register char *argv[];
2829 register struct valobj *vo;
2832 register int status;
2837 if (log_flags & LOG_VALID)
2838 com_err(whoami, 0, "validating %s in %s: %s",
2839 vo->namefield, vo->table, argv[vo->index]);
2840 status = validate_name(argv, vo);
2844 if (log_flags & LOG_VALID)
2845 com_err(whoami, 0, "validating %s in %s: %s",
2846 vo->idfield, vo->table, argv[vo->index]);
2847 status = validate_id(argv, vo);
2851 if (log_flags & LOG_VALID)
2852 com_err(whoami, 0, "validating date: %s", argv[vo->index]);
2853 status = validate_date(argv, vo);
2857 if (log_flags & LOG_VALID)
2858 com_err(whoami, 0, "validating %s type: %s",
2859 vo->table, argv[vo->index]);
2860 status = validate_type(argv, vo);
2864 if (log_flags & LOG_VALID)
2865 com_err(whoami, 0, "validating typed data (%s): %s",
2866 argv[vo->index - 1], argv[vo->index]);
2867 status = validate_typedata(q, argv, vo);
2871 if (log_flags & LOG_VALID)
2872 com_err(whoami, 0, "validating rename %s in %s",
2873 argv[vo->index], vo->table);
2874 status = validate_rename(argv, vo);
2878 if (log_flags & LOG_VALID)
2879 com_err(whoami, 0, "validating chars: %s", argv[vo->index]);
2880 status = validate_chars(argv[vo->index]);
2888 status = lock_table(vo);
2892 if (status != MR_EXISTS) return(status);
2896 if (ingres_errno) return(mr_errcode);
2901 /* validate_chars: verify that there are no illegal characters in
2902 * the string. Legal characters are printing chars other than
2903 * ", *, ?, \, [ and ].
2905 static int illegalchars[] = {
2906 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
2907 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
2908 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
2909 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
2910 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ - O */
2911 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* P - _ */
2912 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
2913 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
2914 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2915 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2916 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2917 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2918 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2919 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2920 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2921 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2928 if (illegalchars[*s++])
2929 return(MR_BAD_CHAR);
2934 validate_id(argv, vo)
2936 register struct valobj *vo;
2942 ## int id, rowcount;
2947 name = argv[vo->index];
2949 namefield = vo->namefield;
2950 idfield = vo->idfield;
2952 if ((!strcmp(table, "users") && !strcmp(namefield, "login")) ||
2953 !strcmp(table, "machine") ||
2954 !strcmp(table, "filesys") ||
2955 !strcmp(table, "list") ||
2956 !strcmp(table, "cluster") ||
2957 !strcmp(table, "string")) {
2958 if (!strcmp(table, "machine"))
2959 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
2960 status = name_to_id(name, table, &id);
2962 *(int *)argv[vo->index] = id;
2964 } else if (status == MR_NO_MATCH || status == MR_NOT_UNIQUE)
2970 if (!strcmp(namefield, "uid")) {
2971 ## retrieve (id = table.idfield) where table.namefield = int4(name)
2972 if (ingres_errno) return(mr_errcode);
2973 ## inquire_equel (rowcount = "rowcount")
2975 ## retrieve (id = table.idfield) where table.namefield = name
2976 if (ingres_errno) return(mr_errcode);
2977 ## inquire_equel (rowcount = "rowcount")
2979 if (rowcount != 1) return(vo->error);
2980 *(int *)argv[vo->index] = id;
2984 validate_name(argv, vo)
2986 register struct valobj *vo;
2994 name = argv[vo->index];
2996 namefield = vo->namefield;
2997 if (!strcmp(table, "servers") && !strcmp(namefield, "name")) {
2998 for (c = name; *c; c++)
3002 ## retrieve (rowcount = countu(table.namefield
3003 ## where table.namefield = name))
3004 if (ingres_errno) return(mr_errcode);
3005 return ((rowcount == 1) ? MR_EXISTS : vo->error);
3008 validate_date(argv, vo)
3016 idate = argv[vo->index];
3018 ## retrieve (dd = interval("years", date(idate) - date("today")))
3019 ## inquire_equel (errorno = "errorno")
3020 if (errorno != 0 || dd > 5.0) return(MR_DATE);
3025 validate_rename(argv, vo)
3029 ## char *name, *table, *namefield, *idfield;
3034 c = name = argv[vo->index];
3036 if (illegalchars[*c++])
3037 return(MR_BAD_CHAR);
3039 /* minor kludge to upcasify machine names */
3040 if (!strcmp(table, "machine"))
3041 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3042 namefield = vo->namefield;
3043 idfield = vo->idfield;
3046 if (!strcmp(argv[vo->index], argv[vo->index - 1]))
3048 ## retrieve (id = any(table.namefield where table.namefield = name))
3049 if (ingres_errno) return(mr_errcode);
3055 status = name_to_id(name, table, &id);
3056 if (status == MR_NO_MATCH || id == *(int *)argv[vo->index - 1])
3063 validate_type(argv, vo)
3065 register struct valobj *vo;
3072 typename = vo->table;
3073 c = value = argv[vo->index];
3075 if (illegalchars[*c++])
3076 return(MR_BAD_CHAR);
3078 /* uppercase type fields */
3079 for (c = value; *c; c++) if (islower(*c)) *c = toupper(*c);
3081 ## repeat retrieve (exists = any(alias.trans where alias.name = @typename and
3082 ## alias.type = "TYPE" and alias.trans = @value))
3083 if (ingres_errno) return(mr_errcode);
3084 return (exists ? MR_EXISTS : vo->error);
3087 /* validate member or type-specific data field */
3089 validate_typedata(q, argv, vo)
3090 register struct query *q;
3091 register char *argv[];
3092 register struct valobj *vo;
3095 ## char *field_type;
3096 ## char data_type[129];
3097 ## int id, rowcount;
3102 /* get named object */
3103 name = argv[vo->index];
3105 /* get field type string (known to be at index-1) */
3106 field_type = argv[vo->index-1];
3108 /* get corresponding data type associated with field type name */
3109 ## repeat retrieve (data_type = alias.trans)
3110 ## where alias.#name = @field_type and alias.type = "TYPEDATA"
3111 if (ingres_errno) return(mr_errcode);
3112 ## inquire_equel (rowcount = "rowcount")
3113 if (rowcount != 1) return(MR_TYPE);
3115 /* now retrieve the record id corresponding to the named object */
3116 if (index(data_type, ' '))
3117 *index(data_type, ' ') = 0;
3118 if (!strcmp(data_type, "user")) {
3120 status = name_to_id(name, data_type, &id);
3121 if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
3123 if (status) return(status);
3124 } else if (!strcmp(data_type, "list")) {
3126 status = name_to_id(name, data_type, &id);
3127 if (status && status == MR_NOT_UNIQUE)
3129 if (status == MR_NO_MATCH) {
3130 /* if idfield is non-zero, then if argv[0] matches the string
3131 * that we're trying to resolve, we should get the value of
3132 * values.[idfield] for the id.
3134 if (vo->idfield && !strcmp(argv[0], argv[vo->index])) {
3135 set_next_object_id(q->validate->object_id, q->rtable);
3137 ## repeat retrieve (id = values.value) where values.#name = @name
3138 ## inquire_equel(rowcount = "rowcount")
3139 if (rowcount != 1) return(MR_LIST);
3142 } else if (status) return(status);
3143 } else if (!strcmp(data_type, "machine")) {
3145 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3146 status = name_to_id(name, data_type, &id);
3147 if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
3149 if (status) return(status);
3150 } else if (!strcmp(data_type, "string")) {
3152 status = name_to_id(name, data_type, &id);
3153 if (status && status == MR_NOT_UNIQUE)
3155 if (status == MR_NO_MATCH) {
3156 if (q->type != APPEND && q->type != UPDATE) return(MR_STRING);
3157 ## retrieve (id = values.value) where values.#name = "strings_id"
3159 ## replace values (value = id) where values.#name = "strings_id"
3160 ## append to strings (string_id = id, string = name)
3161 } else if (status) return(status);
3162 } else if (!strcmp(data_type, "none")) {
3168 /* now set value in argv */
3169 *(int *)argv[vo->index] = id;
3175 /* Lock the table named by the validation object */
3180 ## char *table, *idfield;
3184 idfield = vo->idfield;
3185 ## replace table (modtime = "now") where table.idfield = 0
3186 if (ingres_errno) return(mr_errcode);
3187 ## inquire_equel (rowcount = "rowcount")
3195 /* Check the database at startup time. For now this just resets the
3196 * inprogress flags that the DCM uses.
3199 sanity_check_database()