6 * Copyright (C) 1987 by the Massachusetts Institute of Technology
7 * For copying and distribution information, please see the file
13 static char *rcsid_qsupport_qc = "$Header$";
16 #include <mit-copyright.h>
18 #include "sms_server.h"
22 extern char *whoami, *strsave();
23 extern int ingres_errno, sms_errcode;
26 /* Specialized Access Routines */
28 /* access_user - verify that client name equals specified login name
30 * - since field validation routines are called first, a users_id is
31 * now in argv[0] instead of the login name.
34 access_user(q, argv, cl)
39 if (cl->users_id != *(int *)argv[0])
47 /* access_login - verify that client name equals specified login name
49 * argv[0...n] contain search info. q->
52 access_login(q, argv, cl)
60 build_qual(q->qual, q->argc, argv, qual);
61 ## 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")
101 return(SMS_INTERNAL);
103 /* parse client structure */
104 if ((status = get_client(cl, &client_type, &client_id)) != SMS_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(SMS_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 if (!strcmp(strtrim(acl_type), "LIST")) {
120 if (!client_is_member(cl, acl_id))
126 /* check for client in access control list */
127 status = find_member(acl_type, acl_id, client_type, client_id, 0);
128 if (!status) return(SMS_PERM);
134 /* access_visible_list - allow access to list only if it is not hidden,
135 * or if the client is on the ACL
137 * Inputs: argv[0] - list_id
138 * cl - client identifier
141 access_visible_list(q, argv, cl)
146 ## int list_id, acl_id, flags, rowcount;
149 int client_id, status;
151 list_id = *(int *)argv[0];
152 ## repeat retrieve (flags = list.hidden, acl_id = list.#acl_id,
153 ## acl_type = list.#acl_type) where list.#list_id = @list_id
154 ## inquire_equel(rowcount = "rowcount")
156 return(SMS_INTERNAL);
161 if (!strcmp(strtrim(acl_type), "LIST")) {
162 if (!client_is_member(cl, acl_id))
168 /* parse client structure */
169 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
172 /* check for client in access control list */
173 status = find_member(acl_type, acl_id, client_type, client_id, 0);
181 /* access_vis_list_by_name - allow access to list only if it is not hidden,
182 * or if the client is on the ACL
184 * Inputs: argv[0] - list name
185 * cl - client identifier
188 access_vis_list_by_name(q, argv, cl)
193 ## int acl_id, flags, rowcount;
194 ## char acl_type[9], *listname;
196 int client_id, status;
199 ## repeat retrieve (flags = list.hidden, acl_id = list.#acl_id,
200 ## acl_type = list.#acl_type) where list.#name = @listname
201 ## inquire_equel(rowcount = "rowcount");
203 return(SMS_WILDCARD);
205 return(SMS_NO_MATCH);
209 if (!strcmp(strtrim(acl_type), "LIST")) {
210 if (!client_is_member(cl, acl_id))
216 /* parse client structure */
217 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
220 /* check for client in access control list */
221 status = find_member(acl_type, acl_id, client_type, client_id, 0);
229 /* access_member - allow user to access member of type "USER" and name matches
230 * username, or to access member of type "LIST" and list is one that user is
231 * on the acl of, or the list is visible.
234 access_member(q, argv, cl)
239 if (!strcmp(argv[0], "LIST") || !strcmp(argv[0], "RLIST"))
240 return(access_visible_list(q, &argv[1], cl));
242 if (!strcmp(argv[0], "USER") || !strcmp(argv[0], "RUSER")) {
243 if (cl->users_id == *(int *)argv[1])
251 /* access_qgli - special access routine for Qualified_get_lists. Allows
252 * access iff argv[0] == "TRUE" and argv[2] == "FALSE".
255 access_qgli(q, argv, cl)
260 if (!strcmp(argv[0], "TRUE") && !strcmp(argv[2], "FALSE"))
266 /* access_service - allow access if user is on ACL of service. Don't
267 * allow access if a wildcard is used.
270 access_service(q, argv, cl)
275 ## int acl_id, rowcount;
276 ## char *name, acl_type[9];
277 int client_id, status;
281 ## repeat retrieve (acl_id = servers.#acl_id, acl_type = servers.#acl_type)
282 ## where servers.#name = uppercase(@name)
283 ## inquire_equel(rowcount = "rowcount")
287 if (!strcmp(strtrim(acl_type), "LIST")) {
288 if (!client_is_member(cl, acl_id))
294 /* parse client structure */
295 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
298 /* check for client in access control list */
299 status = find_member(acl_type, acl_id, client_type, client_id, 0);
300 if (!status) return(SMS_PERM);
307 /* access_filesys - verify that client is owner or on owners list of filesystem
311 access_filesys(q, argv, cl)
316 ## int rowcount, users_id, list_id;
318 int status, client_id;
322 ## repeat retrieve (users_id = filesys.owner, list_id = filesys.owners)
323 ## where filesys.label = @name
324 ## inquire_equel(rowcount = "rowcount")
328 if (users_id == cl->users_id)
330 if (!client_is_member(cl, list_id))
340 /* Setup routine for add_user
342 * Inputs: argv[0] - login
347 * - if argv[1] == UNIQUE_UID then set argv[1] = next(uid)
348 * - if argv[0] == UNIQUE_LOGIN then set argv[0] = "#<uid>"
351 setup_ausr(q, argv, cl)
353 register char *argv[];
356 ## int nuid, rowcount;
358 if (!strcmp(argv[1], UNIQUE_UID) || atoi(argv[1]) == -1) {
359 if (set_next_object_id("uid", "users"))
360 return(SMS_INGRES_ERR);
361 ## repeat retrieve (nuid = values.value) where values.name = "uid"
362 ## inquire_equel(rowcount = "rowcount")
364 return(SMS_INTERNAL);
365 sprintf(argv[1], "%d", nuid);
368 if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[1]) == -1) {
369 sprintf(argv[0], "#%s", argv[1]);
376 /* setup_dusr - verify that the user is no longer being referenced
377 * and may safely be deleted.
380 int setup_dusr(q, argv)
386 id = *(int *)argv[0];
388 /* For now, only allow users to be deleted if their status is 0 */
389 ## repeat retrieve (flag = u.status) where u.users_id = @id
390 if (flag != 0 && flag != 4)
393 ## repeat delete nfsquota where nfsquota.users_id = @id
394 ## repeat delete krbmap where krbmap.users_id = @id
395 ## repeat retrieve (flag = any(imembers.member_id where imembers.member_id=@id
396 ## and imembers.member_type = "USER"))
399 ## repeat retrieve (flag = any(filesys.label where filesys.owner=@id))
402 ## repeat retrieve (flag = any(list.name where list.acl_id=@id and
403 ## list.acl_type = "USER"))
406 ## repeat retrieve (flag = any(servers.name where servers.acl_id=@id and
407 ## servers.acl_type = "USER"))
410 ## repeat retrieve (flag=any(hostaccess.acl_id where hostaccess.acl_id=@id and
411 ## hostaccess.acl_type = "USER"))
419 /* setup_spop: verify that there is already a valid POP machine_id in the
420 * pop_id field. Also take care of keeping track of the post office usage.
422 int setup_spop(q, argv)
426 ## int id, mid, flag;
429 id = *(int *)argv[0];
430 ## repeat retrieve (type = u.potype, mid = u.pop_id,
431 ## flag = any(machine.name where machine.mach_id = u.pop_id
432 ## and u.pop_id != 0 and u.users_id = @id))
433 ## where u.users_id = @id
436 if (strcmp(strtrim(type), "POP"))
437 set_pop_usage(mid, 1);
442 /* setup_dpob: Take care of keeping track of the post office usage.
444 int setup_dpob(q, argv)
451 user = *(int *)argv[0];
452 ## repeat retrieve (type = u.potype, id = u.pop_id)
453 ## where u.users_id = @user
455 if (!strcmp(strtrim(type), "POP"))
456 set_pop_usage(id, -1);
461 /* setup_dmac - verify that the machine is no longer being referenced
462 * and may safely be deleted.
465 int setup_dmac(q, argv)
471 id = *(int *)argv[0];
472 ## repeat retrieve (flag = any(users.login where users.potype = "POP"
473 ## and users.pop_id=@id))
476 ## repeat retrieve (flag = any(serverhosts.mach_id
477 ## where serverhosts.mach_id=@id))
480 ## repeat retrieve (flag = any(nfsphys.mach_id where nfsphys.mach_id=@id))
483 ## repeat retrieve (flag = any(hostaccess.mach_id where hostaccess.mach_id=@id))
486 ## repeat retrieve (flag = any(printcap.mach_id where printcap.mach_id=@id))
489 ## repeat retrieve (flag = any(palladium.mach_id where palladium.mach_id=@id))
493 ## repeat delete mcmap where mcmap.mach_id = @id
498 /* setup_dclu - verify that the cluster is no longer being referenced
499 * and may safely be deleted.
502 int setup_dclu(q, argv)
508 id = *(int *)argv[0];
509 ## repeat retrieve (flag = any(mcmap.mach_id where mcmap.clu_id=@id))
512 ## repeat retrieve (flag = any(svc.clu_id where svc.clu_id=@id))
520 /* setup_alis - if argv[5] is non-zero and argv[6] is UNIQUE_ID, then allocate
521 * a new gid and put it in argv[6]. Otherwise if argv[6] is UNIQUE_ID but
522 * argv[5] is not, then remember that UNIQUE_ID is being stored by putting
523 * a -1 there. Remember that this is also used for ulis, with the indexes
527 int setup_alis(q, argv)
535 if (!strcmp(q->shortname, "alis"))
537 else if (!strcmp(q->shortname, "ulis"))
540 if (!strcmp(argv[idx], UNIQUE_GID) || atoi(argv[idx]) == -1) {
541 if (atoi(argv[idx - 1])) {
542 if (set_next_object_id("gid", "list"))
543 return(SMS_INGRES_ERR);
544 ## repeat retrieve (ngid = values.value) where values.name = "gid"
545 sprintf(argv[idx], "%d", ngid);
547 strcpy(argv[idx], "-1");
555 /* setup_dlist - verify that the list is no longer being referenced
556 * and may safely be deleted.
559 int setup_dlis(q, argv)
565 id = *(int *)argv[0];
566 ## repeat retrieve (flag = any(imembers.member_id where imembers.member_id=@id
567 ## and imembers.member_type = "LIST"))
570 ## repeat retrieve (flag = any(imembers.member_id where imembers.list_id=@id))
573 ## repeat retrieve (flag = any(filesys.label where filesys.owners=@id))
576 ## repeat retrieve (flag = any(capacls.tag where capacls.list_id=@id))
579 ## repeat retrieve (flag = any(list.name where list.acl_id=@id and
580 ## list.acl_type = "LIST" and list.list_id != @id))
583 ## repeat retrieve (flag = any(servers.name where servers.acl_id=@id and
584 ## servers.acl_type = "LIST"))
587 ## repeat retrieve (flag=any(hostaccess.acl_id where hostaccess.acl_id=@id and
588 ## hostaccess.acl_type = "LIST"))
591 ## repeat retrieve (flag = any(zephyr.class
592 ## where zephyr.xmt_type = "LIST" and zephyr.xmt_id = @id or
593 ## zephyr.sub_type = "LIST" and zephyr.sub_id = @id or
594 ## zephyr.iws_type = "LIST" and zephyr.iws_id = @id or
595 ## zephyr.iui_type = "LIST" and zephyr.iui_id = @id))
603 /* setup_dsin - verify that the service is no longer being referenced
604 * and may safely be deleted.
607 int setup_dsin(q, argv)
615 ## repeat retrieve (flag = any(serverhosts.service
616 ## where serverhosts.service=uppercase(@name)))
619 ## 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
650 ** setup_add_filesys - verify existance of referenced file systems
662 ** * extract directory prefix from name
663 ** * verify mach_id/dir in nfsphys
664 ** * verify access in {r, w, R, W}
666 ** Side effect: sets variable var_phys_id to the ID of the physical
667 ** filesystem (nfsphys_id for NFS, 0 for RVD)
670 ** SMS_NFS - specified directory not exported
671 ** SMS_FILESYS_ACCESS - invalid filesys access
675 ##static int var_phys_id;
687 mach_id = *(int *)argv[2];
692 if (!strcmp(type, "NFS"))
693 return (check_nfs(mach_id, name, access));
699 /* Verify the arguments, depending on the FStype. Also, if this is an
700 * NFS filesystem, then update any quotas for that filesystem to reflect
709 char *type, *name, *access;
713 mach_id = *(int *)argv[3];
718 if (!strcmp(type, "NFS")) {
719 status = check_nfs(mach_id, name, access);
720 fid = *(int *)argv[0];
721 ## replace nfsquota (phys_id = var_phys_id) where nfsquota.filsys_id = fid
728 /* Find the NFS physical partition that the named directory is on.
729 * This is done by comparing the dir against the mount point of the
730 * partition. To make sure we get the correct match when there is
731 * more than one, we sort the query in reverse order by dir name.
734 ##check_nfs(mach_id, name, access)
745 caccess = (isupper(*access)) ? tolower(*access) : *access;
746 if (caccess != 'r' && caccess != 'w') return(SMS_FILESYS_ACCESS);
749 ## range of np is nfsphys
750 ## repeat retrieve (var_phys_id = np.#nfsphys_id, dir = trim(np.#dir))
751 ## where np.#mach_id = @mach_id sort by #dir:d {
755 if (*cp1++ != *cp2) break;
759 status = SMS_SUCCESS;
768 /* setup_dfil: free any quota records and fsgroup info associated with
769 * a filesystem when it is deleted. Also adjust the allocation numbers.
772 setup_dfil(q, argv, cl)
779 id = *(int *)argv[0];
780 ## range of q is nfsquota
781 ## range of fs is filesys
782 ## range of n is nfsphys
783 ## repeat replace n (allocated=n.allocated-sum(q.quota where q.filsys_id=@id))
784 ## where n.nfsphys_id = fs.phys_id and fs.filsys_id = @id
786 ## repeat delete q where q.filsys_id = @id
787 ## repeat delete fsgroup where fsgroup.filsys_id = @id
788 ## repeat delete fsgroup where fsgroup.group_id = @id
793 /* setup_dnfp: check to see that the nfs physical partition does not have
794 * any filesystems assigned to it before allowing it to be deleted.
797 setup_dnfp(q, argv, cl)
804 id = *(int *)argv[0];
805 ## repeat retrieve (exists = any(filesys.label where filesys.phys_id = @id))
812 /* setup_dnfq: Remove allocation from nfsphys before deleting quota.
813 * argv[0] = filsys_id
817 setup_dnfq(q, argv, cl)
822 ## int quota, fs, user;
824 fs = *(int *)argv[0];
825 user = *(int *)argv[1];
827 ## range of q is nfsquota
828 ## repeat retrieve (quota = q.#quota) where q.users_id = @user and
830 ## repeat replace nfsphys (allocated = nfsphys.allocated - @quota)
831 ## where nfsphys.nfsphys_id = filesys.#phys_id and filesys.filsys_id = @fs
836 /* setup_sshi: don't exclusive lock the machine table during
837 * set_server_host_internal.
840 setup_sshi(q, argv, cl)
845 ## set lockmode session where readlock = system
849 /* setup add_kerberos_user_mapping: add the string to the string
850 * table if necessary.
853 setup_akum(q, argv, cl)
862 ## range of s is strings
863 ## repeat retrieve (id = s.string_id) where s.string = @name
864 ## inquire_equel (rowcount = "rowcount")
866 if (q->type != APPEND) return(SMS_STRING);
867 ## range of v is values
868 ## retrieve (id = v.value) where v.#name = "strings_id"
870 ## replace v (value = id) where v.#name = "strings_id"
871 ## append to strings (string_id = id, string = name)
873 *(int *)argv[1] = id;
879 /* FOLLOWUP ROUTINES */
881 /* generic set_modtime routine. This takes the table name from the query,
882 * and will update the modtime, modby, and modwho fields in the entry in
883 * the table whose name field matches argv[0].
886 set_modtime(q, argv, cl)
891 ## char *name, *entity, *table;
899 ## replace table (modtime = "now", modby = who, modwith = entity)
900 ## where table.#name = name
904 /* generic set_modtime_by_id routine. This takes the table name from
905 * the query, and the id name from the validate record,
906 * and will update the modtime, modby, and modwho fields in the entry in
907 * the table whose id matches argv[0].
910 set_modtime_by_id(q, argv, cl)
915 ## char *entity, *table, *id_name;
921 id_name = q->validate->object_id;
923 id = *(int *)argv[0];
924 ## replace table (modtime = "now", modby = who, modwith = entity)
925 ## where table.id_name = id
930 /* Sets the finger modtime on a user record. The users_id will be in argv[0].
933 set_finger_modtime(q, argv, cl)
938 ## int users_id, who;
943 users_id = *(int *)argv[0];
945 ## repeat replace u (fmodtime = "now", fmodby = @who, fmodwith = @entity)
946 ## where u.#users_id = @users_id
951 /* Sets the pobox modtime on a user record. The users_id will be in argv[0].
954 set_pobox_modtime(q, argv, cl)
959 ## int users_id, who;
964 users_id = *(int *)argv[0];
966 ## repeat replace users (pmodtime = "now", pmodby = @who, pmodwith = @entity)
967 ## where users.#users_id = @users_id
972 /* Like set_modtime, but uppercases the name first.
975 set_uppercase_modtime(q, argv, cl)
980 ## char *name, *entity, *table;
988 ## replace table (modtime = "now", modby = who, modwith = entity)
989 ## where table.#name = uppercase(name)
994 /* Sets the modtime on the machine whose mach_id is in argv[0]. This routine
995 * is necessary for add_machine_to_cluster becuase the table that query
996 * operates on is "mcm", not "machine".
999 set_mach_modtime_by_id(q, argv, cl)
1007 entity = cl->entity;
1008 who = cl->client_id;
1010 id = *(int *)argv[0];
1011 ## range of m is machine
1012 ## repeat replace m (modtime = "now", modby = @who, modwith = @entity)
1013 ## where m.mach_id = @id
1014 return(SMS_SUCCESS);
1018 /* Sets the modtime on the cluster whose mach_id is in argv[0]. This routine
1019 * is necessary for add_cluster_data and delete_cluster_data becuase the
1020 * table that query operates on is "svc", not "cluster".
1023 set_cluster_modtime_by_id(q, argv, cl)
1031 entity = cl->entity;
1032 who = cl->client_id;
1034 id = *(int *)argv[0];
1035 ## range of c is cluster
1036 ## repeat replace c (modtime = "now", modby = @who, modwith = @entity)
1037 ## where c.clu_id = @id
1038 return(SMS_SUCCESS);
1042 /* sets the modtime on the serverhost where the service name is in argv[0]
1043 * and the mach_id is in argv[1].
1046 set_serverhost_modtime(q, argv, cl)
1051 ## char *entity, *serv;
1054 entity = cl->entity;
1055 who = cl->client_id;
1058 id = *(int *)argv[1];
1059 ## repeat replace sh (modtime = "now", modby = @who, modwith = @entity)
1060 ## where sh.service = uppercase(@serv) and sh.mach_id = @id
1061 return(SMS_SUCCESS);
1065 /* sets the modtime on the nfsphys where the mach_id is in argv[0] and the
1066 * directory name is in argv[1].
1069 set_nfsphys_modtime(q, argv, cl)
1074 ## char *entity, *dir;
1077 entity = cl->entity;
1078 who = cl->client_id;
1080 id = *(int *)argv[0];
1082 ## repeat replace np (modtime = "now", modby = @who, modwith = @entity)
1083 ## where np.#dir = @dir and np.mach_id = @id
1084 return(SMS_SUCCESS);
1088 /* sets the modtime on a filesystem, where argv[0] contains the filesys
1092 set_filesys_modtime(q, argv, cl)
1097 ## char *label, *entity;
1100 entity = cl->entity;
1101 who = cl->client_id;
1104 if (!strcmp(q->shortname, "ufil"))
1107 ## repeat replace fs (modtime = "now", modby = @who, modwith = @entity,
1108 ## #phys_id = @var_phys_id) where fs.#label = @label
1109 return(SMS_SUCCESS);
1113 /* sets the modtime on a zephyr class, where argv[0] contains the class
1117 set_zephyr_modtime(q, argv, cl)
1122 ## char *class, *entity;
1125 entity = cl->entity;
1126 who = cl->client_id;
1130 ## repeat replace z (modtime = "now", modby = @who, modwith = @entity)
1131 ## where z.#class = @class
1132 return(SMS_SUCCESS);
1136 /* fixes the modby field. This will be the second to last thing in the
1137 * argv, the argv length is determined from the query structure. It is
1138 * passed as a pointer to an integer. This will either turn it into a
1139 * username, or # + the users_id.
1141 followup_fix_modby(q, sq, v, action, actarg, cl)
1143 register struct save_queue *sq;
1145 register int (*action)();
1146 register int actarg;
1150 char **argv, *malloc();
1151 ## int id, rowcount;
1155 while (sq_get_data(sq, &argv)) {
1158 argv[i] = malloc(256);
1161 ## repeat retrieve (name = users.login) where users.users_id = @id
1164 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1167 ## inquire_equel(rowcount = "rowcount")
1168 if (rowcount != 1) {
1169 sprintf(argv[i], "#%d", id);
1171 (*action)(q->vcnt, argv, actarg);
1172 for (j = 0; j < q->vcnt; j++)
1177 return(SMS_SUCCESS);
1182 ** followup_ausr - add finger and pobox entries, set_user_modtime
1185 ** argv[0] - login (add_user)
1186 ** argv[3] - last name
1187 ** argv[4] - first name
1188 ** argv[5] - middle name
1192 followup_ausr(q, argv, cl)
1198 ## char *login, *entity;
1199 ## char fullname[129];
1202 who = cl->client_id;
1203 entity = cl->entity;
1205 /* build fullname */
1206 if (strlen(argv[4]) && strlen(argv[5]))
1207 sprintf(fullname, "%s %s %s", argv[4], argv[5], argv[3]);
1208 else if (strlen(argv[4]))
1209 sprintf(fullname, "%s %s", argv[4], argv[3]);
1211 sprintf(fullname, "%s", argv[3]);
1213 /* create finger entry, pobox & set modtime on user */
1214 ## repeat replace u (modtime = "now", modby=@who, modwith=@entity,
1215 ## #fullname=@fullname, mit_affil = u.mit_year,
1216 ## fmodtime="now", fmodby=@who, fmodwith=@entity,
1217 ## potype="NONE", pmodtime="now", pmodby=@who, pmodwith=@entity)
1218 ## where u.#login = @login
1220 return(SMS_SUCCESS);
1224 /* followup_gpob: fixes argv[2] based on the IDs currently there and the
1225 * type in argv[1]. Then completes the upcall to the user.
1227 * argv[2] is of the form "123:234" where the first integer is the machine
1228 * ID if it is a pop box, and the second is the string ID if it is an SMTP
1229 * box. argv[1] should be "POP", "SMTP", or "NONE". Boxes of type NONE
1233 followup_gpob(q, sq, v, action, actarg, cl)
1234 register struct query *q;
1235 register struct save_queue *sq;
1236 register struct validate *v;
1237 register int (*action)();
1241 char **argv, *index();
1243 ## char box[129], *name;
1244 ## int mid, sid, rowcount;
1247 while (sq_get_data(sq, &argv)) {
1248 sms_trim_args(2, argv);
1250 p = index(argv[2], ':');
1252 mid = atoi(argv[2]);
1256 if (!strcmp(ptype, "POP")) {
1257 ## repeat retrieve (box=machine.#name) where machine.mach_id=@mid
1258 ## inquire_equel(rowcount = "rowcount")
1260 return(SMS_MACHINE);
1261 } else if (!strcmp(ptype, "SMTP")) {
1262 ## repeat retrieve (box=strings.string) where strings.string_id=@sid
1263 ## inquire_equel(rowcount = "rowcount")
1266 } else /* ptype == "NONE" */ {
1270 if (!strcmp(q->shortname, "gpob")) {
1271 sid = atoi(argv[4]);
1273 argv[4] = malloc(256);
1276 ## repeat retrieve (name = users.login) where users.users_id = @sid
1279 ## repeat retrieve (name = strings.string)
1280 ## where strings.string_id = @sid
1283 ## inquire_equel(rowcount = "rowcount")
1285 sprintf(name, "#%d", sid);
1289 (*action)(q->vcnt, argv, actarg);
1291 /* free saved data */
1299 return (SMS_SUCCESS);
1303 /* followup_glin: fix the ace_name in argv[8]. argv[7] will contain the
1304 * ace_type: "LIST", "USER", or "NONE". Decode the id in argv[8] into the
1305 * proper name based on the type, and repace that string in the argv.
1306 * Also fixes the modby field by called followup_fix_modby.
1309 followup_glin(q, sq, v, action, actarg, cl)
1310 register struct query *q;
1311 register struct save_queue *sq;
1312 register struct validate *v;
1313 register int (*action)();
1317 char **argv, *malloc(), *realloc(), *type;
1319 ## int id, rowcount;
1323 if (!strcmp(q->shortname, "gsin"))
1326 while (sq_get_data(sq, &argv)) {
1327 sms_trim_args(q->vcnt, argv);
1329 id = atoi(argv[i = q->vcnt - 2]);
1331 name = argv[i] = malloc(256);
1333 ## repeat retrieve (name = users.login) where users.users_id = @id
1336 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1339 ## inquire_equel(rowcount = "rowcount")
1341 sprintf(argv[i], "#%d", id);
1343 id = atoi(argv[idx]);
1344 type = argv[idx - 1];
1345 if ((name = malloc(33)) == NULL)
1348 if (!strcmp(type, "LIST")) {
1349 ## repeat retrieve (name = list.#name) where list.list_id = @id
1350 ## inquire_equel(rowcount = "rowcount")
1352 strcpy(name, "???");
1353 } else if (!strcmp(type, "USER")) {
1354 ## repeat retrieve (name = users.login) where users.users_id = @id
1355 ## inquire_equel(rowcount = "rowcount")
1357 strcpy(name, "???");
1358 } else if (!strcmp(type, "KERBEROS")) {
1359 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1360 ## inquire_equel(rowcount = "rowcount")
1362 strcpy(name, "???");
1363 } else if (!strcmp(type, "NONE")) {
1364 strcpy(name, "NONE");
1366 strcpy(name, "???");
1370 if (!strcmp(q->shortname, "glin") && atoi(argv[6]) == -1) {
1371 argv[6] = realloc(argv[6], strlen(UNIQUE_GID) + 1);
1372 strcpy(argv[6], UNIQUE_GID);
1376 (*action)(q->vcnt, argv, actarg);
1378 /* free saved data */
1379 for (i = 0; i < q->vcnt; i++)
1385 return (SMS_SUCCESS);
1389 /** followup_amtl - followup for amtl and dmfl; when adding a list
1390 ** member to a maillist, make member list a maillist also
1391 ** unless list is a user-group.
1392 ** Then set_list_modtime_by_id.
1395 ** argv[0] - list_id
1396 ** argv[1] - member_type
1397 ** argv[2] - member_id
1401 followup_amtl(q, argv, cl)
1411 list_id = *(int *)argv[0];
1412 entity = cl->entity;
1413 who = cl->client_id;
1415 ## range of l is list
1416 ## repeat replace l (modtime = "now", modby = @who, modwith = @entity)
1417 ## where l.#list_id = @list_id
1419 /* if query is not amtl or if member_type is not LIST then return */
1420 if (bcmp(q->shortname, "amtl", 4) || bcmp(argv[1], "LIST", 4))
1421 return(SMS_SUCCESS);
1423 member_id = *(int *)argv[2];
1425 /* is parent list a mailing list? */
1426 ## repeat retrieve (exists = l.maillist) where l.#list_id=@list_id
1428 return(SMS_SUCCESS);
1430 /* list is not a user-group; add list to maillist table */
1431 ## repeat replace l (maillist = 1) where l.#list_id = @member_id
1432 return(SMS_SUCCESS);
1436 /* followup_gnfq: Fix the directory name & modby fields
1437 * argv[0] = filsys_id
1438 * argv[2] = ascii(quota)
1441 followup_gnfq(q, sq, v, action, actarg, cl)
1443 register struct save_queue *sq;
1445 register int (*action)();
1446 register int actarg;
1450 char **argv, *malloc();
1451 ## int id, rowcount;
1452 ## char *name, *label;
1454 while (sq_get_data(sq, &argv)) {
1457 argv[3] = malloc(256);
1461 ## repeat retrieve (name = filesys.#name) where filesys.#label = @label
1463 ## repeat retrieve (name = nfsphys.dir) where nfsphys.nfsphys_id = @id
1465 ## inquire_equel(rowcount = "rowcount")
1466 if (rowcount != 1) {
1467 sprintf(argv[3], "#%d", id);
1472 argv[6] = malloc(256);
1475 ## repeat retrieve (name = users.login) where users.users_id = @id
1478 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1481 ## inquire_equel(rowcount = "rowcount")
1482 if (rowcount != 1) {
1483 sprintf(argv[6], "#%d", id);
1485 (*action)(q->vcnt, argv, actarg);
1486 for (j = 0; j < q->vcnt; j++)
1491 return(SMS_SUCCESS);
1495 /* followup_anfq: Add allocation to nfsphys after creating quota.
1496 * argv[0] = filsys_id
1497 * argv[2] = ascii(quota)
1500 followup_anfq(q, argv, cl)
1505 ## int quota, user, fs, who;
1508 fs = *(int *)argv[0];
1509 user = *(int *)argv[1];
1510 quota = atoi(argv[2]);
1511 who = cl->client_id;
1512 entity = cl->entity;
1514 ## repeat replace nq (modtime = "now", modby = @who, modwith = @entity)
1515 ## where nq.filsys_id = @fs and nq.users_id = @user
1516 ## repeat replace nfsphys (allocated = nfsphys.allocated + @quota)
1517 ## where nfsphys.nfsphys_id = filesys.#phys_id and filesys.filsys_id = @fs
1518 return(SMS_SUCCESS);
1525 followup_gzcl(q, sq, v, action, actarg, cl)
1526 register struct query *q;
1527 register struct save_queue *sq;
1528 register struct validate *v;
1529 register int (*action)();
1534 ## int rowcount, id;
1538 while (sq_get_data(sq, &argv)) {
1539 sms_trim_args(q->vcnt, argv);
1541 id = atoi(argv[i = q->vcnt - 2]);
1543 name = argv[i] = malloc(256);
1545 ## repeat retrieve (name = users.login) where users.users_id = @id
1548 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1551 ## inquire_equel(rowcount = "rowcount")
1553 sprintf(argv[i], "#%d", id);
1555 for (i = 1; i < 8; i+=2) {
1556 id = atoi(argv[i+1]);
1558 if ((name = argv[i+1] = malloc(33)) == NULL)
1560 if (!strcmp(argv[i], "LIST")) {
1561 ## repeat retrieve (name = list.#name) where list.list_id = @id
1562 ## inquire_equel(rowcount = "rowcount")
1564 strcpy(name, "???");
1565 } else if (!strcmp(argv[i], "USER")) {
1566 ## repeat retrieve (name = users.login) where users.users_id = @id
1567 ## inquire_equel(rowcount = "rowcount")
1569 strcpy(name, "???");
1570 } else if (!strcmp(argv[i], "KERBEROS")) {
1571 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1572 ## inquire_equel(rowcount = "rowcount")
1574 strcpy(name, "???");
1575 } else if (!strcmp(argv[i], "NONE")) {
1576 strcpy(name, "NONE");
1578 strcpy(name, "???");
1583 (*action)(q->vcnt, argv, actarg);
1585 /* free saved data */
1586 for (i = 0; i < q->vcnt; i++)
1591 return(SMS_SUCCESS);
1598 followup_gsha(q, sq, v, action, actarg, cl)
1599 register struct query *q;
1600 register struct save_queue *sq;
1601 register struct validate *v;
1602 register int (*action)();
1607 ## int rowcount, id;
1611 while (sq_get_data(sq, &argv)) {
1612 sms_trim_args(q->vcnt, argv);
1616 name = argv[4] = malloc(256);
1618 ## repeat retrieve (name = users.login) where users.users_id = @id
1621 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1624 ## inquire_equel(rowcount = "rowcount")
1626 sprintf(argv[4], "#%d", id);
1630 if ((name = argv[2] = malloc(33)) == NULL)
1632 if (!strcmp(argv[1], "LIST")) {
1633 ## repeat retrieve (name = list.#name) where list.list_id = @id
1634 ## inquire_equel(rowcount = "rowcount")
1636 strcpy(name, "???");
1637 } else if (!strcmp(argv[1], "USER")) {
1638 ## repeat retrieve (name = users.login) where users.users_id = @id
1639 ## inquire_equel(rowcount = "rowcount")
1641 strcpy(name, "???");
1642 } else if (!strcmp(argv[1], "KERBEROS")) {
1643 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1644 ## inquire_equel(rowcount = "rowcount")
1646 strcpy(name, "???");
1647 } else if (!strcmp(argv[1], "NONE")) {
1648 strcpy(name, "NONE");
1650 strcpy(name, "???");
1654 (*action)(q->vcnt, argv, actarg);
1656 /* free saved data */
1657 for (i = 0; i < q->vcnt; i++)
1662 return(SMS_SUCCESS);
1667 /* Special query routines */
1669 /* set_pobox - this does all of the real work.
1670 * argv = user_id, type, box
1671 * if type is POP, then box should be a machine, and its ID should be put in
1672 * pop_id. If type is SMTP, then box should be a string and its ID should
1673 * be put in box_id. If type is NONE, then box doesn't matter.
1676 int set_pobox(q, argv, cl)
1681 ## int user, id, rowcount;
1682 ## char *box, potype[9];
1685 user = *(int *)argv[0];
1687 ## repeat retrieve (id = users.pop_id, potype = users.#potype)
1688 ## where users.users_id = @user
1689 if (!strcmp(strtrim(potype), "POP"))
1690 set_pop_usage(id, -1);
1692 if (!strcmp(argv[1], "POP")) {
1693 ## repeat retrieve (id=machine.mach_id) where machine.name=uppercase(@box)
1694 ## inquire_equel(rowcount = "rowcount")
1696 return(SMS_MACHINE);
1697 ## repeat replace users (#potype = "POP", pop_id = @id)
1698 ## where users.users_id = @user
1699 set_pop_usage(id, 1);
1700 } else if (!strcmp(argv[1], "SMTP")) {
1701 ## range of s is strings
1702 ## repeat retrieve (id = s.string_id) where s.string = @box
1703 ## inquire_equel (rowcount = "rowcount")
1704 if (rowcount == 0) {
1705 ## range of v is values
1706 ## repeat retrieve (id = v.value) where v.name = "strings_id"
1708 ## repeat replace v (value = @id) where v.name = "strings_id"
1709 ## append to strings (string_id = id, string = box)
1711 ## repeat replace users (#potype = "SMTP", box_id = @id)
1712 ## where users.users_id = @user
1713 } else /* argv[1] == "NONE" */ {
1714 ## repeat replace users (#potype = "NONE") where users.users_id = @user
1717 set_pobox_modtime(q, argv, cl);
1718 ## repeat replace tblstats (updates = tblstats.updates + 1, modtime = "now")
1719 ## where tblstats.#table = "users"
1720 return(SMS_SUCCESS);
1724 /* get_list_info: passed a wildcard list name, returns lots of stuff about
1725 * each list. This is tricky: first build a queue of all requested
1726 * data. Rest of processing consists of fixing gid, ace_name, and modby.
1729 get_list_info(q, aargv, cl, action, actarg)
1730 register struct query *q;
1733 register int (*action)();
1736 char *argv[13], *malloc(), *realloc();
1737 ## char *name, acl_type[9], listname[33], active[5], public[5], hidden[5];
1738 ## char maillist[5], group[5], gid[6], acl_name[33], desc[256], modtime[27];
1739 ## char modby[256], modwith[9];
1740 ## int id, rowcount, acl_id, hid, modby_id;
1742 struct save_queue *sq, *sq_create();
1744 returned = rowcount = 0;
1748 ## range of l is list
1749 ## repeat retrieve (id = l.list_id) where l.#name = @name {
1750 sq_save_data(sq, id);
1753 if (ingres_errno) return(sms_errcode);
1755 return(SMS_NO_MATCH);
1757 argv[0] = listname; argv[1] = active; argv[2] = public; argv[3] = hidden;
1758 argv[4] = maillist; argv[5] = group; argv[6] = gid; argv[7] = acl_type;
1759 argv[8] = acl_name; argv[9] = desc; argv[10] = modtime; argv[11] = modby;
1762 while (sq_get_data(sq, &id)) {
1766 ## repeat retrieve (listname = l.#name, active = text(l.#active),
1767 ## public = text(l.#public), hidden = text(l.#hidden),
1768 ## hid = l.#hidden, maillist = text(l.#maillist),
1769 ## group = text(l.#group), gid = text(l.#gid),
1770 ## acl_type = trim(l.#acl_type), acl_id = l.#acl_id,
1771 ## desc = l.#desc, modtime = l.#modtime, modby_id = l.#modby,
1772 ## modwith =l.#modwith)
1773 ## where l.list_id = @id
1774 if (ingres_errno) return(sms_errcode);
1776 if (atoi(gid) == -1)
1777 argv[6] = UNIQUE_GID;
1779 if (!strcmp(acl_type, "LIST")) {
1780 ## repeat retrieve (acl_name = l.#name) where l.list_id = @acl_id
1781 ## inquire_equel(rowcount = "rowcount")
1783 strcpy(acl_name, "???");
1784 } else if (!strcmp(acl_type, "USER")) {
1785 ## repeat retrieve (acl_name = users.#login)
1786 ## where users.users_id = @acl_id
1787 ## inquire_equel(rowcount = "rowcount")
1789 strcpy(acl_name, "???");
1790 } else if (!strcmp(acl_type, "KERBEROS")) {
1791 ## repeat retrieve (acl_name = strings.string)
1792 ## where strings.string_id = @acl_id
1793 ## inquire_equel(rowcount = "rowcount")
1795 strcpy(acl_name, "???");
1796 } else if (!strcmp(acl_type, "NONE")) {
1797 strcpy(acl_name, "NONE");
1799 strcpy(acl_name, "???");
1802 ## repeat retrieve (modby = users.login) where users.users_id = @modby_id
1804 modby_id = -modby_id;
1805 ## repeat retrieve (modby = strings.string)
1806 ## where strings.string_id = @modby_id
1807 modby_id = -modby_id;
1809 ## inquire_equel(rowcount = "rowcount")
1811 sprintf(modby, "#%d", modby_id);
1812 if (ingres_errno) return(sms_errcode);
1814 sms_trim_args(q->vcnt, argv);
1816 (*action)(q->vcnt, argv, actarg);
1820 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
1821 ## where tblstats.#table = "list"
1823 return (SMS_SUCCESS);
1827 /* Add_member_to_list: do list flattening as we go! MAXLISTDEPTH is
1828 * how many different ancestors a member is allowed to have.
1831 #define MAXLISTDEPTH 100
1833 int add_member_to_list(q, argv, cl)
1838 ## int id, lid, mid, exists, error;
1839 ## char *mtype, dtype[9];
1840 int ancestors[MAXLISTDEPTH], acount, a;
1841 int descendants[MAXLISTDEPTH], dcount, d;
1842 char *dtypes[MAXLISTDEPTH];
1845 ## range of m is imembers
1846 lid = *(int *)argv[0];
1848 mid = *(int *)argv[2];
1849 ## repeat retrieve (exists = any(m.list_id where m.list_id=@lid and
1850 ## m.member_id = @mid and m.member_type = @mtype
1851 ## and m.direct = 1))
1856 ## repeat retrieve (id = m.list_id)
1857 ## where m.member_id = @lid and m.member_type = "LIST" {
1858 ancestors[acount++] = id;
1859 if (acount >= MAXLISTDEPTH) {
1863 if (ingres_errno) return(sms_errcode);
1864 if (acount >= MAXLISTDEPTH) {
1865 return(SMS_INTERNAL);
1867 descendants[0] = mid;
1871 if (!strcmp(mtype, "LIST")) {
1872 ## repeat retrieve (id = m.member_id, dtype = m.member_type)
1873 ## where m.list_id = @mid {
1876 dtypes[dcount] = "LIST";
1879 dtypes[dcount] = "USER";
1882 dtypes[dcount] = "STRING";
1885 dtypes[dcount] = "KERBEROS";
1891 descendants[dcount++] = id;
1892 if (dcount >= MAXLISTDEPTH) {
1897 if (ingres_errno) return(sms_errcode);
1899 return(SMS_INTERNAL);
1901 for (a = 0; a < acount; a++) {
1903 for (d = 0; d < dcount; d++) {
1904 mid = descendants[d];
1906 if (mid == lid && !strcmp(mtype, "LIST")) {
1907 return(SMS_LISTLOOP);
1909 ## repeat retrieve (exists = any(m.ref_count where m.list_id = @lid
1910 ## and m.member_id = @mid
1911 ## and m.member_type = @mtype))
1913 if (a == 0 && d == 0)
1914 ## replace m (ref_count = m.ref_count+1, direct = 1)
1915 ## where m.list_id = lid and m.member_id = mid and
1916 ## m.member_type = mtype
1918 ## replace m (ref_count = m.ref_count+1)
1919 ## where m.list_id = lid and m.member_id = mid and
1920 ## m.member_type = mtype
1922 incremental_clear_before();
1923 if (a == 0 && d == 0)
1924 ## append imembers (list_id=lid, member_id = mid, direct = 1,
1925 ## member_type=mtype, ref_count = 1)
1927 ## append imembers (list_id=lid, member_id = mid,
1928 ## member_type=mtype, ref_count = 1)
1929 iargv[0] = (char *)lid;
1931 iargv[2] = (char *)mid;
1932 incremental_after("members", 0, iargv);
1936 if (ingres_errno) return(sms_errcode);
1937 return(SMS_SUCCESS);
1941 /* Delete_member_from_list: do list flattening as we go!
1944 int delete_member_from_list(q, argv, cl)
1949 ## int id, lid, mid, cnt, exists, error;
1950 ## char *mtype, dtype[9];
1951 int ancestors[MAXLISTDEPTH], acount, a;
1952 int descendants[MAXLISTDEPTH], dcount, d;
1953 char *dtypes[MAXLISTDEPTH];
1956 ## range of m is imembers
1957 lid = *(int *)argv[0];
1959 mid = *(int *)argv[2];
1960 ## repeat retrieve (exists = any(m.list_id where m.list_id=@lid and
1961 ## m.member_id = @mid and m.member_type = @mtype
1962 ## and m.direct = 1))
1963 if (ingres_errno) return(sms_errcode);
1965 return(SMS_NO_MATCH);
1968 ## repeat retrieve (id = m.list_id)
1969 ## where m.member_id = @lid and m.member_type = "LIST" {
1970 ancestors[acount++] = id;
1971 if (acount >= MAXLISTDEPTH)
1974 if (ingres_errno) return(sms_errcode);
1975 if (acount >= MAXLISTDEPTH)
1976 return(SMS_INTERNAL);
1977 descendants[0] = mid;
1981 if (!strcmp(mtype, "LIST")) {
1982 ## repeat retrieve (id = m.member_id, dtype = m.member_type)
1983 ## where m.list_id = @mid {
1986 dtypes[dcount] = "LIST";
1989 dtypes[dcount] = "USER";
1992 dtypes[dcount] = "STRING";
1995 dtypes[dcount] = "KERBEROS";
2001 descendants[dcount++] = id;
2002 if (dcount >= MAXLISTDEPTH)
2005 if (ingres_errno) return(sms_errcode);
2007 return(SMS_INTERNAL);
2009 for (a = 0; a < acount; a++) {
2011 for (d = 0; d < dcount; d++) {
2012 mid = descendants[d];
2014 if (mid == lid && !strcmp(mtype, "LIST")) {
2015 return(SMS_LISTLOOP);
2017 ## repeat retrieve (cnt = m.ref_count)
2018 ## where m.list_id = @lid and m.member_id = @mid
2019 ## and m.member_type = @mtype
2021 iargv[0] = (char *)lid;
2023 iargv[2] = (char *)mid;
2024 incremental_before("members", 0, iargv);
2025 ## delete m where m.list_id = lid and m.member_id = mid and
2026 ## m.member_type = mtype
2027 incremental_clear_after();
2028 } else if (a == 0 && d == 0) {
2029 ## replace m (ref_count = m.ref_count-1, direct = 0)
2030 ## where m.list_id = lid and m.member_id = mid and
2031 ## m.member_type = mtype
2033 ## replace m (ref_count = m.ref_count-1)
2034 ## where m.list_id = lid and m.member_idn = mid and
2035 ## m.member_type = mtype
2039 if (ingres_errno) return(sms_errcode);
2040 return(SMS_SUCCESS);
2044 /* get_ace_use - given a type and a name, return a type and a name.
2045 * The ace_type is one of "LIST", "USER", "RLIST", or "RUSER" in argv[0],
2046 * and argv[1] will contain the ID of the entity in question. The R*
2047 * types mean to recursively look at every containing list, not just
2048 * when the object in question is a direct member. On return, the
2049 * usage type will be one of LIST, SERVICE, FILESYS, QUOTA, QUERY, or ZEPHYR.
2052 int get_ace_use(q, argv, cl, action, actarg)
2061 ## int aid, listid, id;
2062 struct save_queue *sq, *sq_create();
2064 ## range of m is imembers
2066 aid = *(int *)argv[1];
2067 if (!strcmp(atype, "LIST") || !strcmp(atype, "USER") ||
2068 !strcmp(atype, "KERBEROS")) {
2069 return(get_ace_internal(atype, aid, action, actarg));
2073 if (!strcmp(atype, "RLIST")) {
2074 sq_save_data(sq, aid);
2075 /* get all the list_id's of containing lists */
2076 ## range of m is imembers
2077 ## repeat retrieve (listid = m.list_id)
2078 ## where m.member_type = "LIST" and m.member_id = @id {
2079 sq_save_unique_data(sq, listid);
2081 /* now process each one */
2082 while (sq_get_data(sq, &id)) {
2083 if (get_ace_internal("LIST", id, action, actarg) == SMS_SUCCESS)
2088 if (!strcmp(atype, "RUSER")) {
2089 ## repeat retrieve (listid = m.list_id)
2090 ## where m.member_type = "USER" and m.member_id = @aid {
2091 sq_save_data(sq, listid);
2093 /* now process each one */
2094 while (sq_get_data(sq, &id)) {
2095 if (get_ace_internal("LIST", id, action, actarg) == SMS_SUCCESS)
2098 if (get_ace_internal("USER", aid, action, actarg) == SMS_SUCCESS)
2102 if (!strcmp(atype, "RKERBERO")) {
2103 ## repeat retrieve (listid = m.list_id)
2104 ## where m.member_type = "KERBEROS" and m.member_id = @aid {
2105 sq_save_data(sq, listid);
2107 /* now process each one */
2108 while (sq_get_data(sq, &id)) {
2109 if (get_ace_internal("LIST", id, action, actarg) == SMS_SUCCESS)
2112 if (get_ace_internal("KERBEROS", aid, action, actarg) == SMS_SUCCESS)
2117 if (!found) return(SMS_NO_MATCH);
2118 return(SMS_SUCCESS);
2122 /* This looks up a single list or user for ace use. atype must be "USER"
2123 * or "LIST", and aid is the ID of the corresponding object. This is used
2124 * by get_ace_use above.
2127 ##get_ace_internal(atype, aid, action, actarg)
2138 if (!strcmp(atype, "LIST")) {
2139 rargv[0] = "FILESYS";
2140 ## repeat retrieve (name = filesys.label)
2141 ## where filesys.owners = @aid {
2142 (*action)(2, rargv, actarg);
2147 ## repeat retrieve (name = capacls.capability)
2148 ## where capacls.list_id = @aid {
2149 (*action)(2, rargv, actarg);
2152 } else if (!strcmp(atype, "USER")) {
2153 rargv[0] = "FILESYS";
2154 ## repeat retrieve (name = filesys.label)
2155 ## where filesys.owner = @aid {
2156 (*action)(2, rargv, actarg);
2162 ## repeat retrieve (name = list.#name)
2163 ## where list.acl_type = @atype and list.acl_id = @aid {
2164 (*action)(2, rargv, actarg);
2168 rargv[0] = "SERVICE";
2169 ## repeat retrieve (name = servers.#name)
2170 ## where servers.acl_type = @atype and servers.acl_id = @aid {
2171 (*action)(2, rargv, actarg);
2175 rargv[0] = "HOSTACCESS";
2176 ## repeat retrieve (name = machine.#name)
2177 ## where machine.mach_id = hostaccess.mach_id and
2178 ## hostaccess.acl_type = @atype and hostaccess.acl_id = @aid {
2179 (*action)(2, rargv, actarg);
2182 rargv[0] = "ZEPHYR";
2183 ## repeat retrieve (name = zephyr.class)
2184 ## where zephyr.xmt_type = @atype and zephyr.xmt_id = @aid or
2185 ## zephyr.sub_type = @atype and zephyr.sub_id = @aid or
2186 ## zephyr.iws_type = @atype and zephyr.iws_id = @aid or
2187 ## zephyr.iui_type = @atype and zephyr.iui_id = @aid {
2188 (*action)(2, rargv, actarg);
2192 if (!found) return(SMS_NO_MATCH);
2193 return(SMS_SUCCESS);
2197 /* get_lists_of_member - given a type and a name, return the name and flags
2198 * of all of the lists of the given member. The member_type is one of
2199 * "LIST", "USER", "STRING", "RLIST", "RUSER", or "RSTRING" in argv[0],
2200 * and argv[1] will contain the ID of the entity in question. The R*
2201 * types mean to recursively look at every containing list, not just
2202 * when the object in question is a direct member.
2205 int get_lists_of_member(q, argv, cl, action, actarg)
2212 int found = 0, direct = 1;
2215 ## int aid, listid, id;
2216 ## char name[33], active[5], public[5], hidden[5], maillist[5], group[5];
2219 aid = *(int *)argv[1];
2220 if (!strcmp(atype, "RLIST")) {
2224 if (!strcmp(atype, "RUSER")) {
2228 if (!strcmp(atype, "RSTRING")) {
2232 if (!strcmp(atype, "RKERBEROS")) {
2241 rargv[4] = maillist;
2244 ## repeat retrieve (name = list.#name, active = text(list.#active),
2245 ## public = text(list.#public), hidden = text(list.#hidden),
2246 ## maillist = text(list.#maillist), group = text(list.#group))
2247 ## where list.list_id = m.list_id and m.direct = 1 and
2248 ## m.member_type = @atype and m.member_id = @aid {
2249 (*action)(6, rargv, actarg);
2253 ## repeat retrieve (name = list.#name, active = text(list.#active),
2254 ## public = text(list.#public), hidden = text(list.#hidden),
2255 ## maillist = text(list.#maillist), group = text(list.#group))
2256 ## where list.list_id = m.list_id and
2257 ## m.member_type = @atype and m.member_id = @aid {
2258 (*action)(6, rargv, actarg);
2263 if (!found) return(SMS_NO_MATCH);
2264 return(SMS_SUCCESS);
2268 /* qualified_get_lists: passed "TRUE", "FALSE", or "DONTCARE" for each of
2269 * the five flags associated with each list. It will return the name of
2270 * each list that meets the quailifications. It does this by building a
2271 * where clause based on the arguments, then doing a retrieve.
2274 static char *lflags[5] = { "active", "public", "hidden", "maillist", "group" };
2276 int qualified_get_lists(q, argv, cl, action, actarg)
2283 return(qualified_get(q, argv, action, actarg, "l.list_id != 0",
2284 "l", "name", lflags));
2288 /** get_members_of_list - optimized query for retrieval of list members
2291 ** argv[0] - list_id
2294 ** - retrieve USER members, then LIST members, then STRING members
2297 get_members_of_list(q, argv, cl, action, actarg)
2305 ## char member_name[129];
2308 list_id = *(int *)argv[0];
2310 targv[1] = member_name;
2312 ## range of m is imembers
2313 ## repeat retrieve (member_name = users.login)
2314 ## where m.#list_id = @list_id and m.member_type = "USER"
2315 ## and m.member_id = users.users_id and m.direct = 1
2316 ## sort by #member_name
2318 (*action)(2, targv, actarg);
2322 ## repeat retrieve (member_name = list.name)
2323 ## where m.#list_id = @list_id and m.member_type = "LIST"
2324 ## and m.member_id = list.#list_id and m.direct = 1
2325 ## sort by #member_name
2327 (*action)(2, targv, actarg);
2330 targv[0] = "STRING";
2331 ## repeat retrieve (member_name = strings.string)
2332 ## where m.#list_id = @list_id and m.member_type = "STRING"
2333 ## and m.member_id = strings.string_id and m.direct = 1
2334 ## sort by #member_name
2336 (*action)(2, targv, actarg);
2339 targv[0] = "KERBEROS";
2340 ## repeat retrieve (member_name = strings.string)
2341 ## where m.#list_id = @list_id and m.member_type = "KERBEROS"
2342 ## and m.member_id = strings.string_id and m.direct = 1
2343 ## sort by #member_name
2345 (*action)(2, targv, actarg);
2348 return(SMS_SUCCESS);
2352 /* count_members_of_list: this is a simple query, but it cannot be done
2353 * through the dispatch table.
2356 int count_members_of_list(q, argv, cl, action, actarg)
2363 ## int list, ct = 0;
2364 char *rargv[1], countbuf[5];
2366 list = *(int *)argv[0];
2367 rargv[0] = countbuf;
2368 ## repeat retrieve (ct = count(imembers.list_id
2369 ## where imembers.list_id = @list and
2370 ## imembers.direct = 1))
2371 sprintf(countbuf, "%d", ct);
2372 (*action)(1, rargv, actarg);
2373 return(SMS_SUCCESS);
2377 /* qualified_get_server: passed "TRUE", "FALSE", or "DONTCARE" for each of
2378 * the three flags associated with each service. It will return the name of
2379 * each service that meets the quailifications. It does this by building a
2380 * where clause based on the arguments, then doing a retrieve.
2383 static char *sflags[3] = { "enable", "inprogress", "harderror" };
2385 int qualified_get_server(q, argv, cl, action, actarg)
2392 return(qualified_get(q, argv, action, actarg, "s.name != \"\"",
2393 "s", "name", sflags));
2397 /* generic qualified get routine, used by qualified_get_lists,
2398 * qualified_get_server, and qualified_get_serverhost.
2400 * start - a simple where clause, must not be empty
2401 * range - the name of the range variable
2402 * field - the field to return
2403 * flags - an array of strings, names of the flag variables
2406 int qualified_get(q, argv, action, actarg, start, range, field, flags)
2416 ## char name[33], qual[256], *rvar, *rtbl, *rfield;
2417 char *rargv[1], buf[32];
2420 strcpy(qual, start);
2421 for (i = 0; i < q->argc; i++) {
2422 if (!strcmp(argv[i], "TRUE")) {
2423 sprintf(buf, " and %s.%s != 0", range, flags[i]);
2424 (void) strcat(qual, buf);
2425 } else if (!strcmp(argv[i], "FALSE")) {
2426 sprintf(buf, " and %s.%s = 0", range, flags[i]);
2427 (void) strcat(qual, buf);
2435 ## range of rvar is rtbl
2436 ## retrieve (name = rvar.rfield) where qual {
2437 (*action)(1, rargv, actarg);
2439 ## inquire_equel(rowcount = "rowcount")
2440 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
2441 ## where tblstats.#table = @rtbl
2443 return(SMS_NO_MATCH);
2444 return(SMS_SUCCESS);
2448 /* qualified_get_serverhost: passed "TRUE", "FALSE", or "DONTCARE" for each of
2449 * the five flags associated with each serverhost. It will return the name of
2450 * each service and host that meets the quailifications. It does this by
2451 * building a where clause based on the arguments, then doing a retrieve.
2454 static char *shflags[6] = { "service", "enable", "override", "success",
2455 "inprogress", "hosterror" };
2457 int qualified_get_serverhost(q, argv, cl, action, actarg)
2464 ## char sname[33], mname[33], qual[256];
2465 char *rargv[2], buf[32];
2468 sprintf(qual, "machine.mach_id = sh.mach_id and sh.service = uppercase(\"%s\")",
2470 for (i = 1; i < q->argc; i++) {
2471 if (!strcmp(argv[i], "TRUE")) {
2472 sprintf(buf, " and sh.%s != 0", shflags[i]);
2474 } else if (!strcmp(argv[i], "FALSE")) {
2475 sprintf(buf, " and sh.%s = 0", shflags[i]);
2482 ## range of sh is serverhosts
2483 ## retrieve (sname = sh.service, mname = machine.name) where qual {
2484 (*action)(2, rargv, actarg);
2486 ## inquire_equel(rowcount = "rowcount")
2487 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
2488 ## where tblstats.#table = "serverhosts"
2490 return(SMS_NO_MATCH);
2491 return(SMS_SUCCESS);
2495 /* register_user - change user's login name and allocate a pobox, group,
2496 * filesystem, and quota for them. The user's status must start out as 0,
2497 * and is left as 2. Arguments are: user's UID, new login name, and user's
2498 * type for filesystem allocation (SMS_FS_STUDENT, SMS_FS_FACULTY,
2499 * SMS_FS_STAFF, SMS_FS_MISC).
2502 register_user(q, argv, cl)
2507 ## char *login, dir[65], *entity, *directory, machname[33];
2508 ## int who, rowcount, mid, uid, users_id, flag, utype, nid, list_id, quota;
2509 ## int size, alloc, pid, m_id;
2510 char buffer[256], *aargv[3];
2513 entity = cl->entity;
2514 who = cl->client_id;
2516 uid = atoi(argv[0]);
2518 utype = atoi(argv[2]);
2520 ## range of u is users
2521 ## range of l is list
2522 ## range of sh is serverhosts
2523 ## range of n is nfsphys
2524 ## range of m is machine
2527 ## repeat retrieve (users_id = u.#users_id)
2528 ## where u.#uid = @uid and (u.status = 0 or u.status = 5)
2529 ## inquire_equel(rowcount = "rowcount");
2531 return(SMS_NO_MATCH);
2533 return(SMS_NOT_UNIQUE);
2535 /* check new login name */
2536 ## repeat retrieve (flag = any(u.#login where u.#login = @login and
2537 ## u.#users_id != users_id))
2538 if (ingres_errno) return(sms_errcode);
2539 if (flag) return(SMS_IN_USE);
2540 ## repeat retrieve (flag = any(l.#name where l.#name = @login))
2541 if (ingres_errno) return(sms_errcode);
2542 if (flag) return(SMS_IN_USE);
2543 ## repeat retrieve (flag = any(filesys.#label where filesys.#label = @login))
2544 if (ingres_errno) return(sms_errcode);
2545 if (flag) return(SMS_IN_USE);
2546 com_err(whoami, 0, "new login name OK");
2548 /* choose place for pobox, put in mid */
2549 ## repeat retrieve (mid = sh.mach_id, machname = m.name)
2550 ## where sh.service = "POP" and m.mach_id = sh.mach_id and
2551 ## sh.value2 - sh.value1 = max(sh.value2-sh.value1 where sh.service="POP")
2552 ## inquire_equel(rowcount = "rowcount");
2554 return(SMS_NO_POBOX);
2556 /* change login name, set pobox */
2557 sprintf(buffer, "u.users_id = %d", users_id);
2558 incremental_before("users", buffer, 0);
2559 ## repeat replace u (#login = @login, status = 2, modtime = "now",
2560 ## modby = @who, modwith = @entity, potype="POP",
2561 ## pop_id = @mid, pmodtime="now", pmodby=@who,
2562 ## pmodwith=@entity)
2563 ## where u.#users_id = @users_id
2564 ## inquire_equel(rowcount = "rowcount");
2566 return(SMS_INTERNAL);
2567 set_pop_usage(mid, 1);
2568 com_err(whoami, 0, "set login name to %s and pobox to %s", login,
2570 incremental_after("users", buffer, 0);
2572 /* create group list */
2573 if (set_next_object_id("gid", "list"))
2575 if (set_next_object_id("list_id", "list"))
2577 ## repeat retrieve (list_id = values.value) where values.name = "list_id"
2578 ## inquire_equel(rowcount = "rowcount");
2580 return(SMS_INTERNAL);
2581 incremental_clear_before();
2582 ## repeat append list (name = @login, #list_id = @list_id, active = 1,
2583 ## public = 0, hidden = 0, maillist = 0, group = 1,
2584 ## #gid = values.value, desc = "User Group",
2585 ## acl_type = "USER", acl_id = @users_id, modtime = "now",
2586 ## modby = @who, modwith = @entity)
2587 ## where values.name = "gid"
2588 ## inquire_equel(rowcount = "rowcount");
2590 return(SMS_INTERNAL);
2591 sprintf(buffer, "l.list_id = %d", list_id);
2592 incremental_after("list", buffer, 0);
2593 aargv[0] = (char *) list_id;
2595 aargv[2] = (char *) users_id;
2596 incremental_clear_before();
2597 ## repeat append imembers (#list_id = @list_id, member_type = "USER",
2598 ## member_id = @users_id, ref_count = 1, direct = 1)
2599 ## inquire_equel(rowcount = "rowcount");
2601 return(SMS_INTERNAL);
2602 incremental_after("members", 0, argv);
2603 com_err(whoami, 0, "group list created");
2605 /* decide where to put filesystem */
2608 ## repeat retrieve (mid = n.mach_id, dir = trim(n.#dir), nid = n.nfsphys_id,
2609 ## flag = n.status, size = n.#size, alloc = n.allocated) {
2610 if ((flag & utype) && (size != 0) && (size - alloc > maxsize)) {
2611 maxsize = size - alloc;
2614 directory = strsave(dir);
2620 return(SMS_NO_FILESYS);
2622 /* create filesystem */
2623 if (set_next_object_id("filsys_id", "filesys"))
2625 incremental_clear_before();
2626 ## repeat append filesys (filsys_id = values.value, phys_id = @pid,
2627 ## label = @login, type = "NFS", mach_id = @m_id,
2628 ## name = @directory + "/" + @login,
2629 ## mount = "/mit/" + @login,
2630 ## access = "w", comments = "User Locker",
2631 ## owner = @users_id, owners = @list_id, createflg = 1,
2632 ## lockertype = "HOMEDIR", modtime = "now",
2633 ## modby = @who, modwith = @entity)
2634 ## where values.name = "filsys_id"
2635 ## inquire_equel(rowcount = "rowcount");
2637 return(SMS_INTERNAL);
2638 incremental_after("filesys",
2639 "fs.filsys_id = values.value and values.name = \"filsys_id\"",
2641 com_err(whoami, 0, "filesys created on mach %d in %s/%s", m_id,
2645 ## repeat retrieve (quota = values.value) where values.name = "def_quota"
2646 ## inquire_equel(rowcount = "rowcount");
2648 return(SMS_NO_QUOTA);
2649 incremental_clear_before();
2650 ## repeat append nfsquota (#users_id = @users_id, filsys_id = values.value,
2651 ## #quota = @quota, phys_id = @pid, modtime = "now",
2652 ## modby = @who, modwith = @entity)
2653 ## where values.name = "filsys_id"
2654 ## inquire_equel(rowcount = "rowcount");
2656 return(SMS_INTERNAL);
2657 ## repeat replace nfsphys (allocated = nfsphys.allocated + @quota)
2658 ## where nfsphys.nfsphys_id = filesys.#phys_id and
2659 ## filesys.filsys_id = values.value and values.name = "filsys_id"
2660 ## inquire_equel(rowcount = "rowcount");
2662 return(SMS_INTERNAL);
2665 sprintf(buffer, "nq.users_id = %d and nq.filsys_id = values.value and values.name = \"filsys_id\"", users_id);
2666 incremental_after("nfsquota", buffer, argv);
2667 com_err(whoami, 0, "quota of %d assigned", quota);
2669 ## repeat replace tblstats (updates = tblstats.updates + 1, modtime = "now")
2670 ## where tblstats.table = "users"
2671 ## repeat replace tblstats (appends = tblstats.appends + 1, modtime = "now")
2672 ## where tblstats.table = "list" or tblstats.table = "filesys" or
2673 ## tblstats.table = "nfsquota"
2674 return(SMS_SUCCESS);
2679 /** set_pop_usage - incr/decr usage count for pop server in serverhosts talbe
2683 ** delta (will be +/- 1)
2686 ** - incr/decr value field in serverhosts table for pop/mach_id
2690 static int set_pop_usage(id, count)
2694 ## int mach_id = id;
2697 ## range of sh is serverhosts
2698 ## repeat replace sh (value1 = sh.value1 + @n)
2699 ## where sh.service = "POP" and sh.#mach_id = @mach_id
2701 return(SMS_SUCCESS);
2706 /* Validation Routines */
2708 validate_row(q, argv, v)
2709 register struct query *q;
2711 register struct validate *v;
2719 /* build where clause */
2720 build_qual(v->qual, v->argc, argv, qual);
2722 /* setup ingres variables */
2727 if (log_flags & LOG_VALID)
2728 /* tell the logfile what we're doing */
2729 com_err(whoami, 0, "validating row: %s", qual);
2731 /* look for the record */
2732 ## range of rvar is table
2733 ## retrieve (rowcount = count(rvar.name where qual))
2734 if (ingres_errno) return(sms_errcode);
2735 if (rowcount == 0) return(SMS_NO_MATCH);
2736 if (rowcount > 1) return(SMS_NOT_UNIQUE);
2740 validate_fields(q, argv, vo, n)
2742 register char *argv[];
2743 register struct valobj *vo;
2746 register int status;
2751 if (log_flags & LOG_VALID)
2752 com_err(whoami, 0, "validating %s in %s: %s",
2753 vo->namefield, vo->table, argv[vo->index]);
2754 status = validate_name(argv, vo);
2758 if (log_flags & LOG_VALID)
2759 com_err(whoami, 0, "validating %s in %s: %s",
2760 vo->idfield, vo->table, argv[vo->index]);
2761 status = validate_id(argv, vo);
2765 if (log_flags & LOG_VALID)
2766 com_err(whoami, 0, "validating date: %s", argv[vo->index]);
2767 status = validate_date(argv, vo);
2771 if (log_flags & LOG_VALID)
2772 com_err(whoami, 0, "validating %s type: %s",
2773 vo->table, argv[vo->index]);
2774 status = validate_type(argv, vo);
2778 if (log_flags & LOG_VALID)
2779 com_err(whoami, 0, "validating typed data (%s): %s",
2780 argv[vo->index - 1], argv[vo->index]);
2781 status = validate_typedata(q, argv, vo);
2785 if (log_flags & LOG_VALID)
2786 com_err(whoami, 0, "validating rename %s in %s",
2787 argv[vo->index], vo->table);
2788 status = validate_rename(argv, vo);
2792 if (log_flags & LOG_VALID)
2793 com_err(whoami, 0, "validating chars: %s", argv[vo->index]);
2794 status = validate_chars(argv[vo->index]);
2798 status = SMS_EXISTS;
2802 status = lock_table(vo);
2806 if (status != SMS_EXISTS) return(status);
2810 return(SMS_SUCCESS);
2814 /* validate_chars: verify that there are no illegal characters in
2815 * the string. Legal characters are printing chars other than
2816 * ", *, ?, \, [ and ].
2818 static int illegalchars[] = {
2819 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
2820 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
2821 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
2822 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
2823 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ - O */
2824 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* P - _ */
2825 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
2826 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
2827 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2828 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2829 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2830 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2831 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2832 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2833 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2834 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2841 if (illegalchars[*s++])
2842 return(SMS_BAD_CHAR);
2847 validate_id(argv, vo)
2849 register struct valobj *vo;
2859 name = argv[vo->index];
2861 /* minor kludge to upcasify machine names */
2862 if (!strcmp(table, "machine"))
2863 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
2864 namefield = vo->namefield;
2865 idfield = vo->idfield;
2866 if (!strcmp(namefield, "uid")) {
2867 ## retrieve (id = table.idfield) where table.namefield = int4(name)
2868 if (ingres_errno) return(sms_errcode);
2869 ## inquire_equel (rowcount = "rowcount")
2871 ## retrieve (id = table.idfield) where table.namefield = name
2872 if (ingres_errno) return(sms_errcode);
2873 ## inquire_equel (rowcount = "rowcount")
2875 if (rowcount != 1) return(vo->error);
2876 *(int *)argv[vo->index] = id;
2880 validate_name(argv, vo)
2882 register struct valobj *vo;
2890 name = argv[vo->index];
2892 namefield = vo->namefield;
2893 if (!strcmp(table, "servers") && !strcmp(namefield, "name")) {
2894 for (c = name; *c; c++)
2898 ## retrieve (rowcount = countu(table.namefield
2899 ## where table.namefield = name))
2900 if (ingres_errno) return(sms_errcode);
2901 return ((rowcount == 1) ? SMS_EXISTS : vo->error);
2904 validate_date(argv, vo)
2912 idate = argv[vo->index];
2914 ## retrieve (dd = interval("years", date(idate) - date("today")))
2915 ## inquire_equel (errorno = "errorno")
2916 if (errorno != 0 || dd > 5.0) return(SMS_DATE);
2921 validate_rename(argv, vo)
2925 ## char *name, *table, *namefield, *idfield;
2929 c = name = argv[vo->index];
2931 if (illegalchars[*c++])
2932 return(SMS_BAD_CHAR);
2934 /* minor kludge to upcasify machine names */
2935 if (!strcmp(table, "machine"))
2936 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
2937 namefield = vo->namefield;
2938 idfield = vo->idfield;
2941 if (!strcmp(argv[vo->index], argv[vo->index - 1]))
2943 ## retrieve (id = any(table.namefield where table.namefield = name))
2944 if (ingres_errno) return(sms_errcode);
2950 ## retrieve (id = table.idfield) where table.namefield = name
2951 if (ingres_errno) return(sms_errcode);
2952 if (id == -1 || id == *(int *)argv[vo->index - 1])
2959 validate_type(argv, vo)
2961 register struct valobj *vo;
2968 typename = vo->table;
2969 c = value = argv[vo->index];
2971 if (illegalchars[*c++])
2972 return(SMS_BAD_CHAR);
2974 /* uppercase type fields */
2975 for (c = value; *c; c++) if (islower(*c)) *c = toupper(*c);
2977 ## range of a is alias
2978 ## repeat retrieve (exists = any(a.trans where a.name = @typename and
2979 ## a.type = "TYPE" and
2980 ## a.trans = @value))
2981 if (ingres_errno) return(sms_errcode);
2982 return (exists ? SMS_EXISTS : vo->error);
2985 /* validate member or type-specific data field */
2987 validate_typedata(q, argv, vo)
2988 register struct query *q;
2989 register char *argv[];
2990 register struct valobj *vo;
2993 ## char *field_type;
2994 ## char data_type[129];
3000 /* get named object */
3001 name = argv[vo->index];
3003 /* get field type string (known to be at index-1) */
3004 field_type = argv[vo->index-1];
3006 /* get corresponding data type associated with field type name */
3007 ## repeat retrieve (data_type = alias.trans)
3008 ## where alias.#name = @field_type and alias.type = "TYPEDATA"
3009 if (ingres_errno) return(sms_errcode);
3010 ## inquire_equel (rowcount = "rowcount")
3011 if (rowcount != 1) return(SMS_TYPE);
3013 /* now retrieve the record id corresponding to the named object */
3014 if (index(data_type, ' '))
3015 *index(data_type, ' ') = 0;
3016 if (!strcmp(data_type, "user")) {
3018 ## repeat retrieve (id = users.users_id) where users.login = @name
3019 ## inquire_equel (rowcount = "rowcount")
3020 if (rowcount != 1) return(SMS_USER);
3022 } else if (!strcmp(data_type, "list")) {
3024 ## repeat retrieve (id = list.list_id) where list.#name = @name
3025 ## inquire_equel (rowcount = "rowcount")
3026 if (rowcount != 1) {
3027 /* if idfield is non-zero, then if argv[0] matches the string
3028 * that we're trying to resolve, we should get the value of
3029 * values.[idfield] for the id.
3031 if (vo->idfield && !strcmp(argv[0], argv[vo->index])) {
3032 set_next_object_id(q->validate->object_id, q->rtable);
3034 ## repeat retrieve (id = values.value) where values.#name = @name
3035 ## inquire_equel(rowcount = "rowcount")
3036 if (rowcount != 1) return(SMS_LIST);
3040 } else if (!strcmp(data_type, "machine")) {
3042 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3043 ## repeat retrieve (id = machine.mach_id) where machine.#name = @name
3044 ## inquire_equel (rowcount = "rowcount")
3045 if (rowcount != 1) return(SMS_MACHINE);
3047 } else if (!strcmp(data_type, "string")) {
3049 ## range of s is strings
3050 ## repeat retrieve (id = s.string_id) where s.string = @name
3051 ## inquire_equel (rowcount = "rowcount")
3052 if (rowcount == 0) {
3053 if (q->type != APPEND) return(SMS_STRING);
3054 ## range of v is values
3055 ## retrieve (id = v.value) where v.#name = "strings_id"
3057 ## replace v (value = id) where v.#name = "strings_id"
3058 ## append to strings (string_id = id, string = name)
3060 } else if (!strcmp(data_type, "none")) {
3066 /* now set value in argv */
3067 *(int *)argv[vo->index] = id;
3069 return (SMS_EXISTS);
3073 /* Lock the table named by the validation object */
3078 ## char *table, *idfield;
3082 idfield = vo->idfield;
3083 ## replace table (modtime = "now") where table.idfield = 0
3084 if (ingres_errno) return(sms_errcode);
3085 ## inquire_equel (rowcount = "rowcount")
3093 /* Check the database at startup time. For now this just resets the
3094 * inprogress flags that the DCM uses.
3097 sanity_check_database()