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 /* check for client in access control list */
120 status = find_member(acl_type, acl_id, client_type, client_id, 0);
121 if (!status) return(SMS_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")
149 return(SMS_INTERNAL);
154 /* parse client structure */
155 if ((status = get_client(cl, &client_type, &client_id)) != SMS_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");
189 return(SMS_WILDCARD);
191 return(SMS_NO_MATCH);
195 /* parse client structure */
196 if ((status = get_client(cl, &client_type, &client_id)) != SMS_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)) != SMS_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(SMS_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)) != SMS_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;
333 if (!strcmp(argv[1], UNIQUE_UID) || atoi(argv[1]) == -1) {
334 if (set_next_object_id("uid", "users"))
335 return(SMS_INGRES_ERR);
336 ## repeat retrieve (nuid = values.value) where values.name = "uid"
337 ## inquire_equel(rowcount = "rowcount")
339 return(SMS_INTERNAL);
340 sprintf(argv[1], "%d", nuid);
343 if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[1]) == -1) {
344 sprintf(argv[0], "#%s", argv[1]);
351 /* setup_dusr - verify that the user is no longer being referenced
352 * and may safely be deleted.
355 int setup_dusr(q, argv)
361 id = *(int *)argv[0];
363 /* For now, only allow users to be deleted if their status is 0 */
364 ## repeat retrieve (flag = u.status) where u.users_id = @id
365 if (flag != 0 && flag != 4)
368 ## repeat delete nfsquota where nfsquota.users_id = @id
369 ## repeat delete krbmap where krbmap.users_id = @id
370 ## repeat retrieve (flag = any(imembers.member_id where imembers.member_id=@id
371 ## and imembers.member_type = "USER"))
374 ## repeat retrieve (flag = any(filesys.label where filesys.owner=@id))
377 ## repeat retrieve (flag = any(list.name where list.acl_id=@id and
378 ## list.acl_type = "USER"))
381 ## repeat retrieve (flag = any(servers.name where servers.acl_id=@id and
382 ## servers.acl_type = "USER"))
385 ## repeat retrieve (flag=any(hostaccess.acl_id where hostaccess.acl_id=@id and
386 ## hostaccess.acl_type = "USER"))
394 /* setup_spop: verify that there is already a valid POP machine_id in the
395 * pop_id field. Also take care of keeping track of the post office usage.
397 int setup_spop(q, argv)
401 ## int id, mid, flag;
404 id = *(int *)argv[0];
405 ## repeat retrieve (type = u.potype, mid = u.pop_id,
406 ## flag = any(machine.name where machine.mach_id = u.pop_id
407 ## and u.pop_id != 0 and u.users_id = @id))
408 ## where u.users_id = @id
411 if (strcmp(strtrim(type), "POP"))
412 set_pop_usage(mid, 1);
417 /* setup_dpob: Take care of keeping track of the post office usage.
419 int setup_dpob(q, argv)
426 user = *(int *)argv[0];
427 ## repeat retrieve (type = u.potype, id = u.pop_id)
428 ## where u.users_id = @user
430 if (!strcmp(strtrim(type), "POP"))
431 set_pop_usage(id, -1);
436 /* setup_dmac - verify that the machine is no longer being referenced
437 * and may safely be deleted.
440 int setup_dmac(q, argv)
446 id = *(int *)argv[0];
447 ## repeat retrieve (flag = any(users.login where users.potype = "POP"
448 ## and users.pop_id=@id))
451 ## repeat retrieve (flag = any(serverhosts.mach_id
452 ## where serverhosts.mach_id=@id))
455 ## repeat retrieve (flag = any(nfsphys.mach_id where nfsphys.mach_id=@id))
458 ## repeat retrieve (flag = any(hostaccess.mach_id where hostaccess.mach_id=@id))
461 ## repeat retrieve (flag = any(printcap.mach_id where printcap.mach_id=@id))
464 ## repeat retrieve (flag = any(palladium.mach_id where palladium.mach_id=@id))
468 ## repeat delete mcmap where mcmap.mach_id = @id
473 /* setup_dclu - verify that the cluster is no longer being referenced
474 * and may safely be deleted.
477 int setup_dclu(q, argv)
483 id = *(int *)argv[0];
484 ## repeat retrieve (flag = any(mcmap.mach_id where mcmap.clu_id=@id))
487 ## repeat retrieve (flag = any(svc.clu_id where svc.clu_id=@id))
495 /* setup_alis - if argv[5] is non-zero and argv[6] is UNIQUE_ID, then allocate
496 * a new gid and put it in argv[6]. Otherwise if argv[6] is UNIQUE_ID but
497 * argv[5] is not, then remember that UNIQUE_ID is being stored by putting
498 * a -1 there. Remember that this is also used for ulis, with the indexes
502 int setup_alis(q, argv)
510 if (!strcmp(q->shortname, "alis"))
512 else if (!strcmp(q->shortname, "ulis"))
515 if (!strcmp(argv[idx], UNIQUE_GID) || atoi(argv[idx]) == -1) {
516 if (atoi(argv[idx - 1])) {
517 if (set_next_object_id("gid", "list"))
518 return(SMS_INGRES_ERR);
519 ## repeat retrieve (ngid = values.value) where values.name = "gid"
520 sprintf(argv[idx], "%d", ngid);
522 strcpy(argv[idx], "-1");
530 /* setup_dlist - verify that the list is no longer being referenced
531 * and may safely be deleted.
534 int setup_dlis(q, argv)
540 id = *(int *)argv[0];
541 ## repeat retrieve (flag = any(imembers.member_id where imembers.member_id=@id
542 ## and imembers.member_type = "LIST"))
545 ## repeat retrieve (flag = any(imembers.member_id where imembers.list_id=@id))
548 ## repeat retrieve (flag = any(filesys.label where filesys.owners=@id))
551 ## repeat retrieve (flag = any(capacls.tag where capacls.list_id=@id))
554 ## repeat retrieve (flag = any(list.name where list.acl_id=@id and
555 ## list.acl_type = "LIST" and list.list_id != @id))
558 ## repeat retrieve (flag = any(servers.name where servers.acl_id=@id and
559 ## servers.acl_type = "LIST"))
562 ## repeat retrieve (flag=any(hostaccess.acl_id where hostaccess.acl_id=@id and
563 ## hostaccess.acl_type = "LIST"))
566 ## repeat retrieve (flag = any(zephyr.class
567 ## where zephyr.xmt_type = "LIST" and zephyr.xmt_id = @id or
568 ## zephyr.sub_type = "LIST" and zephyr.sub_id = @id or
569 ## zephyr.iws_type = "LIST" and zephyr.iws_id = @id or
570 ## zephyr.iui_type = "LIST" and zephyr.iui_id = @id))
578 /* setup_dsin - verify that the service is no longer being referenced
579 * and may safely be deleted.
582 int setup_dsin(q, argv)
590 ## repeat retrieve (flag = any(serverhosts.service
591 ## where serverhosts.service=uppercase(@name)))
594 ## repeat retrieve (flag = servers.inprogress) where servers.#name = @name
602 /* setup_dshi - verify that the service-host is no longer being referenced
603 * and may safely be deleted.
606 int setup_dshi(q, argv)
614 id = *(int *)argv[1];
615 ## repeat retrieve (flag=serverhosts.inprogress)
616 ## where serverhosts.service=uppercase(@name) and serverhosts.mach_id=@id
625 ** setup_add_filesys - verify existance of referenced file systems
637 ** * extract directory prefix from name
638 ** * verify mach_id/dir in nfsphys
639 ** * verify access in {r, w, R, W}
641 ** Side effect: sets variable var_phys_id to the ID of the physical
642 ** filesystem (nfsphys_id for NFS, 0 for RVD)
645 ** SMS_NFS - specified directory not exported
646 ** SMS_FILESYS_ACCESS - invalid filesys access
650 ##static int var_phys_id;
662 mach_id = *(int *)argv[2];
667 if (!strcmp(type, "NFS"))
668 return (check_nfs(mach_id, name, access));
674 /* Verify the arguments, depending on the FStype. Also, if this is an
675 * NFS filesystem, then update any quotas for that filesystem to reflect
684 char *type, *name, *access;
688 mach_id = *(int *)argv[3];
693 if (!strcmp(type, "NFS")) {
694 status = check_nfs(mach_id, name, access);
695 fid = *(int *)argv[0];
696 ## replace nfsquota (phys_id = var_phys_id) where nfsquota.filsys_id = fid
703 /* Find the NFS physical partition that the named directory is on.
704 * This is done by comparing the dir against the mount point of the
705 * partition. To make sure we get the correct match when there is
706 * more than one, we sort the query in reverse order by dir name.
709 ##check_nfs(mach_id, name, access)
720 caccess = (isupper(*access)) ? tolower(*access) : *access;
721 if (caccess != 'r' && caccess != 'w') return(SMS_FILESYS_ACCESS);
724 ## range of np is nfsphys
725 ## repeat retrieve (var_phys_id = np.#nfsphys_id, dir = trim(np.#dir))
726 ## where np.#mach_id = @mach_id sort by #dir:d {
730 if (*cp1++ != *cp2) break;
734 status = SMS_SUCCESS;
743 /* setup_dfil: free any quota records and fsgroup info associated with
744 * a filesystem when it is deleted. Also adjust the allocation numbers.
747 setup_dfil(q, argv, cl)
754 id = *(int *)argv[0];
755 ## range of q is nfsquota
756 ## range of fs is filesys
757 ## range of n is nfsphys
758 ## repeat replace n (allocated=n.allocated-sum(q.quota where q.filsys_id=@id))
759 ## where n.nfsphys_id = fs.phys_id and fs.filsys_id = @id
761 ## repeat delete q where q.filsys_id = @id
762 ## repeat delete fsgroup where fsgroup.filsys_id = @id
763 ## repeat delete fsgroup where fsgroup.group_id = @id
768 /* setup_dnfp: check to see that the nfs physical partition does not have
769 * any filesystems assigned to it before allowing it to be deleted.
772 setup_dnfp(q, argv, cl)
779 id = *(int *)argv[0];
780 ## repeat retrieve (exists = any(filesys.label where filesys.phys_id = @id))
787 /* setup_dnfq: Remove allocation from nfsphys before deleting quota.
788 * argv[0] = filsys_id
792 setup_dnfq(q, argv, cl)
797 ## int quota, fs, user;
799 fs = *(int *)argv[0];
800 user = *(int *)argv[1];
802 ## range of q is nfsquota
803 ## repeat retrieve (quota = q.#quota) where q.users_id = @user and
805 ## repeat replace nfsphys (allocated = nfsphys.allocated - @quota)
806 ## where nfsphys.nfsphys_id = filesys.#phys_id and filesys.filsys_id = @fs
811 /* setup_sshi: don't exclusive lock the machine table during
812 * set_server_host_internal.
815 setup_sshi(q, argv, cl)
820 ## set lockmode session where readlock = system
824 /* setup add_kerberos_user_mapping: add the string to the string
825 * table if necessary.
828 setup_akum(q, argv, cl)
837 ## range of s is strings
838 ## repeat retrieve (id = s.string_id) where s.string = @name
839 ## inquire_equel (rowcount = "rowcount")
841 if (q->type != APPEND) return(SMS_STRING);
842 ## range of v is values
843 ## retrieve (id = v.value) where v.#name = "strings_id"
845 ## replace v (value = id) where v.#name = "strings_id"
846 ## append to strings (string_id = id, string = name)
848 *(int *)argv[1] = id;
854 /* FOLLOWUP ROUTINES */
856 /* generic set_modtime routine. This takes the table name from the query,
857 * and will update the modtime, modby, and modwho fields in the entry in
858 * the table whose name field matches argv[0].
861 set_modtime(q, argv, cl)
866 ## char *name, *entity, *table;
874 ## replace table (modtime = "now", modby = who, modwith = entity)
875 ## where table.#name = name
879 /* generic set_modtime_by_id routine. This takes the table name from
880 * the query, and the id name from the validate record,
881 * and will update the modtime, modby, and modwho fields in the entry in
882 * the table whose id matches argv[0].
885 set_modtime_by_id(q, argv, cl)
890 ## char *entity, *table, *id_name;
896 id_name = q->validate->object_id;
898 id = *(int *)argv[0];
899 ## replace table (modtime = "now", modby = who, modwith = entity)
900 ## where table.id_name = id
905 /* Sets the finger modtime on a user record. The users_id will be in argv[0].
908 set_finger_modtime(q, argv, cl)
913 ## int users_id, who;
918 users_id = *(int *)argv[0];
920 ## repeat replace u (fmodtime = "now", fmodby = @who, fmodwith = @entity)
921 ## where u.#users_id = @users_id
926 /* Sets the pobox modtime on a user record. The users_id will be in argv[0].
929 set_pobox_modtime(q, argv, cl)
934 ## int users_id, who;
939 users_id = *(int *)argv[0];
941 ## repeat replace users (pmodtime = "now", pmodby = @who, pmodwith = @entity)
942 ## where users.#users_id = @users_id
947 /* Like set_modtime, but uppercases the name first.
950 set_uppercase_modtime(q, argv, cl)
955 ## char *name, *entity, *table;
963 ## replace table (modtime = "now", modby = who, modwith = entity)
964 ## where table.#name = uppercase(name)
969 /* Sets the modtime on the machine whose mach_id is in argv[0]. This routine
970 * is necessary for add_machine_to_cluster becuase the table that query
971 * operates on is "mcm", not "machine".
974 set_mach_modtime_by_id(q, argv, cl)
985 id = *(int *)argv[0];
986 ## range of m is machine
987 ## repeat replace m (modtime = "now", modby = @who, modwith = @entity)
988 ## where m.mach_id = @id
993 /* Sets the modtime on the cluster whose mach_id is in argv[0]. This routine
994 * is necessary for add_cluster_data and delete_cluster_data becuase the
995 * table that query operates on is "svc", not "cluster".
998 set_cluster_modtime_by_id(q, argv, cl)
1006 entity = cl->entity;
1007 who = cl->client_id;
1009 id = *(int *)argv[0];
1010 ## range of c is cluster
1011 ## repeat replace c (modtime = "now", modby = @who, modwith = @entity)
1012 ## where c.clu_id = @id
1013 return(SMS_SUCCESS);
1017 /* sets the modtime on the serverhost where the service name is in argv[0]
1018 * and the mach_id is in argv[1].
1021 set_serverhost_modtime(q, argv, cl)
1026 ## char *entity, *serv;
1029 entity = cl->entity;
1030 who = cl->client_id;
1033 id = *(int *)argv[1];
1034 ## repeat replace sh (modtime = "now", modby = @who, modwith = @entity)
1035 ## where sh.service = uppercase(@serv) and sh.mach_id = @id
1036 return(SMS_SUCCESS);
1040 /* sets the modtime on the nfsphys where the mach_id is in argv[0] and the
1041 * directory name is in argv[1].
1044 set_nfsphys_modtime(q, argv, cl)
1049 ## char *entity, *dir;
1052 entity = cl->entity;
1053 who = cl->client_id;
1055 id = *(int *)argv[0];
1057 ## repeat replace np (modtime = "now", modby = @who, modwith = @entity)
1058 ## where np.#dir = @dir and np.mach_id = @id
1059 return(SMS_SUCCESS);
1063 /* sets the modtime on a filesystem, where argv[0] contains the filesys
1067 set_filesys_modtime(q, argv, cl)
1072 ## char *label, *entity;
1075 entity = cl->entity;
1076 who = cl->client_id;
1079 if (!strcmp(q->shortname, "ufil"))
1082 ## repeat replace fs (modtime = "now", modby = @who, modwith = @entity,
1083 ## #phys_id = @var_phys_id) where fs.#label = @label
1084 return(SMS_SUCCESS);
1088 /* sets the modtime on a zephyr class, where argv[0] contains the class
1092 set_zephyr_modtime(q, argv, cl)
1097 ## char *class, *entity;
1100 entity = cl->entity;
1101 who = cl->client_id;
1105 ## repeat replace z (modtime = "now", modby = @who, modwith = @entity)
1106 ## where z.#class = @class
1107 return(SMS_SUCCESS);
1111 /* fixes the modby field. This will be the second to last thing in the
1112 * argv, the argv length is determined from the query structure. It is
1113 * passed as a pointer to an integer. This will either turn it into a
1114 * username, or # + the users_id.
1116 followup_fix_modby(q, sq, v, action, actarg, cl)
1118 register struct save_queue *sq;
1120 register int (*action)();
1121 register int actarg;
1125 char **argv, *malloc();
1126 ## int id, rowcount;
1130 while (sq_get_data(sq, &argv)) {
1133 argv[i] = malloc(256);
1136 ## repeat retrieve (name = users.login) where users.users_id = @id
1139 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1142 ## inquire_equel(rowcount = "rowcount")
1143 if (rowcount != 1) {
1144 sprintf(argv[i], "#%d", id);
1146 (*action)(q->vcnt, argv, actarg);
1147 for (j = 0; j < q->vcnt; j++)
1152 return(SMS_SUCCESS);
1157 ** followup_ausr - add finger and pobox entries, set_user_modtime
1160 ** argv[0] - login (add_user)
1161 ** argv[3] - last name
1162 ** argv[4] - first name
1163 ** argv[5] - middle name
1167 followup_ausr(q, argv, cl)
1173 ## char *login, *entity;
1174 ## char fullname[129];
1177 who = cl->client_id;
1178 entity = cl->entity;
1180 /* build fullname */
1181 if (strlen(argv[4]) && strlen(argv[5]))
1182 sprintf(fullname, "%s %s %s", argv[4], argv[5], argv[3]);
1183 else if (strlen(argv[4]))
1184 sprintf(fullname, "%s %s", argv[4], argv[3]);
1186 sprintf(fullname, "%s", argv[3]);
1188 /* create finger entry, pobox & set modtime on user */
1189 ## repeat replace u (modtime = "now", modby=@who, modwith=@entity,
1190 ## #fullname=@fullname, mit_affil = u.mit_year,
1191 ## fmodtime="now", fmodby=@who, fmodwith=@entity,
1192 ## potype="NONE", pmodtime="now", pmodby=@who, pmodwith=@entity)
1193 ## where u.#login = @login
1195 return(SMS_SUCCESS);
1199 /* followup_gpob: fixes argv[2] based on the IDs currently there and the
1200 * type in argv[1]. Then completes the upcall to the user.
1202 * argv[2] is of the form "123:234" where the first integer is the machine
1203 * ID if it is a pop box, and the second is the string ID if it is an SMTP
1204 * box. argv[1] should be "POP", "SMTP", or "NONE". Boxes of type NONE
1208 followup_gpob(q, sq, v, action, actarg, cl)
1209 register struct query *q;
1210 register struct save_queue *sq;
1211 register struct validate *v;
1212 register int (*action)();
1216 char **argv, *index();
1218 ## char box[129], *name;
1219 ## int mid, sid, rowcount;
1222 while (sq_get_data(sq, &argv)) {
1223 sms_trim_args(2, argv);
1225 p = index(argv[2], ':');
1227 mid = atoi(argv[2]);
1231 if (!strcmp(ptype, "POP")) {
1232 ## repeat retrieve (box=machine.#name) where machine.mach_id=@mid
1233 ## inquire_equel(rowcount = "rowcount")
1235 return(SMS_MACHINE);
1236 } else if (!strcmp(ptype, "SMTP")) {
1237 ## repeat retrieve (box=strings.string) where strings.string_id=@sid
1238 ## inquire_equel(rowcount = "rowcount")
1241 } else /* ptype == "NONE" */ {
1245 if (!strcmp(q->shortname, "gpob")) {
1246 sid = atoi(argv[4]);
1248 argv[4] = malloc(256);
1251 ## repeat retrieve (name = users.login) where users.users_id = @sid
1254 ## repeat retrieve (name = strings.string)
1255 ## where strings.string_id = @sid
1258 ## inquire_equel(rowcount = "rowcount")
1260 sprintf(name, "#%d", sid);
1264 (*action)(q->vcnt, argv, actarg);
1266 /* free saved data */
1274 return (SMS_SUCCESS);
1278 /* followup_glin: fix the ace_name in argv[8]. argv[7] will contain the
1279 * ace_type: "LIST", "USER", or "NONE". Decode the id in argv[8] into the
1280 * proper name based on the type, and repace that string in the argv.
1281 * Also fixes the modby field by called followup_fix_modby.
1284 followup_glin(q, sq, v, action, actarg, cl)
1285 register struct query *q;
1286 register struct save_queue *sq;
1287 register struct validate *v;
1288 register int (*action)();
1292 char **argv, *malloc(), *realloc(), *type;
1294 ## int id, rowcount;
1298 if (!strcmp(q->shortname, "gsin"))
1301 while (sq_get_data(sq, &argv)) {
1302 sms_trim_args(q->vcnt, argv);
1304 id = atoi(argv[i = q->vcnt - 2]);
1306 name = argv[i] = malloc(256);
1308 ## repeat retrieve (name = users.login) where users.users_id = @id
1311 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1314 ## inquire_equel(rowcount = "rowcount")
1316 sprintf(argv[i], "#%d", id);
1318 id = atoi(argv[idx]);
1319 type = argv[idx - 1];
1320 if ((name = malloc(33)) == NULL)
1323 if (!strcmp(type, "LIST")) {
1324 ## repeat retrieve (name = list.#name) where list.list_id = @id
1325 ## inquire_equel(rowcount = "rowcount")
1327 strcpy(name, "???");
1328 } else if (!strcmp(type, "USER")) {
1329 ## repeat retrieve (name = users.login) where users.users_id = @id
1330 ## inquire_equel(rowcount = "rowcount")
1332 strcpy(name, "???");
1333 } else if (!strcmp(type, "KERBEROS")) {
1334 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1335 ## inquire_equel(rowcount = "rowcount")
1337 strcpy(name, "???");
1338 } else if (!strcmp(type, "NONE")) {
1339 strcpy(name, "NONE");
1341 strcpy(name, "???");
1345 if (!strcmp(q->shortname, "glin") && atoi(argv[6]) == -1) {
1346 argv[6] = realloc(argv[6], strlen(UNIQUE_GID) + 1);
1347 strcpy(argv[6], UNIQUE_GID);
1351 (*action)(q->vcnt, argv, actarg);
1353 /* free saved data */
1354 for (i = 0; i < q->vcnt; i++)
1360 return (SMS_SUCCESS);
1364 /** followup_amtl - followup for amtl and dmfl; when adding a list
1365 ** member to a maillist, make member list a maillist also
1366 ** unless list is a user-group.
1367 ** Then set_list_modtime_by_id.
1370 ** argv[0] - list_id
1371 ** argv[1] - member_type
1372 ** argv[2] - member_id
1376 followup_amtl(q, argv, cl)
1386 list_id = *(int *)argv[0];
1387 entity = cl->entity;
1388 who = cl->client_id;
1390 ## range of l is list
1391 ## repeat replace l (modtime = "now", modby = @who, modwith = @entity)
1392 ## where l.#list_id = @list_id
1394 /* if query is not amtl or if member_type is not LIST then return */
1395 if (bcmp(q->shortname, "amtl", 4) || bcmp(argv[1], "LIST", 4))
1396 return(SMS_SUCCESS);
1398 member_id = *(int *)argv[2];
1400 /* is parent list a mailing list? */
1401 ## repeat retrieve (exists = l.maillist) where l.#list_id=@list_id
1403 return(SMS_SUCCESS);
1405 /* list is not a user-group; add list to maillist table */
1406 ## repeat replace l (maillist = 1) where l.#list_id = @member_id
1407 return(SMS_SUCCESS);
1411 /* followup_gnfq: Fix the directory name & modby fields
1412 * argv[0] = filsys_id
1413 * argv[2] = ascii(quota)
1416 followup_gnfq(q, sq, v, action, actarg, cl)
1418 register struct save_queue *sq;
1420 register int (*action)();
1421 register int actarg;
1425 char **argv, *malloc();
1426 ## int id, rowcount;
1427 ## char *name, *label;
1429 while (sq_get_data(sq, &argv)) {
1432 argv[3] = malloc(256);
1436 ## repeat retrieve (name = filesys.#name) where filesys.#label = @label
1438 ## repeat retrieve (name = nfsphys.dir) where nfsphys.nfsphys_id = @id
1440 ## inquire_equel(rowcount = "rowcount")
1441 if (rowcount != 1) {
1442 sprintf(argv[3], "#%d", id);
1447 argv[6] = malloc(256);
1450 ## repeat retrieve (name = users.login) where users.users_id = @id
1453 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1456 ## inquire_equel(rowcount = "rowcount")
1457 if (rowcount != 1) {
1458 sprintf(argv[6], "#%d", id);
1460 (*action)(q->vcnt, argv, actarg);
1461 for (j = 0; j < q->vcnt; j++)
1466 return(SMS_SUCCESS);
1470 /* followup_anfq: Add allocation to nfsphys after creating quota.
1471 * argv[0] = filsys_id
1472 * argv[2] = ascii(quota)
1475 followup_anfq(q, argv, cl)
1480 ## int quota, user, fs, who;
1483 fs = *(int *)argv[0];
1484 user = *(int *)argv[1];
1485 quota = atoi(argv[2]);
1486 who = cl->client_id;
1487 entity = cl->entity;
1489 ## repeat replace nq (modtime = "now", modby = @who, modwith = @entity)
1490 ## where nq.filsys_id = @fs and nq.users_id = @user
1491 ## repeat replace nfsphys (allocated = nfsphys.allocated + @quota)
1492 ## where nfsphys.nfsphys_id = filesys.#phys_id and filesys.filsys_id = @fs
1493 return(SMS_SUCCESS);
1500 followup_gzcl(q, sq, v, action, actarg, cl)
1501 register struct query *q;
1502 register struct save_queue *sq;
1503 register struct validate *v;
1504 register int (*action)();
1509 ## int rowcount, id;
1513 while (sq_get_data(sq, &argv)) {
1514 sms_trim_args(q->vcnt, argv);
1516 id = atoi(argv[i = q->vcnt - 2]);
1518 name = argv[i] = malloc(256);
1520 ## repeat retrieve (name = users.login) where users.users_id = @id
1523 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1526 ## inquire_equel(rowcount = "rowcount")
1528 sprintf(argv[i], "#%d", id);
1530 for (i = 1; i < 8; i+=2) {
1531 id = atoi(argv[i+1]);
1533 if ((name = argv[i+1] = malloc(33)) == NULL)
1535 if (!strcmp(argv[i], "LIST")) {
1536 ## repeat retrieve (name = list.#name) where list.list_id = @id
1537 ## inquire_equel(rowcount = "rowcount")
1539 strcpy(name, "???");
1540 } else if (!strcmp(argv[i], "USER")) {
1541 ## repeat retrieve (name = users.login) where users.users_id = @id
1542 ## inquire_equel(rowcount = "rowcount")
1544 strcpy(name, "???");
1545 } else if (!strcmp(argv[i], "KERBEROS")) {
1546 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1547 ## inquire_equel(rowcount = "rowcount")
1549 strcpy(name, "???");
1550 } else if (!strcmp(argv[i], "NONE")) {
1551 strcpy(name, "NONE");
1553 strcpy(name, "???");
1558 (*action)(q->vcnt, argv, actarg);
1560 /* free saved data */
1561 for (i = 0; i < q->vcnt; i++)
1566 return(SMS_SUCCESS);
1573 followup_gsha(q, sq, v, action, actarg, cl)
1574 register struct query *q;
1575 register struct save_queue *sq;
1576 register struct validate *v;
1577 register int (*action)();
1582 ## int rowcount, id;
1586 while (sq_get_data(sq, &argv)) {
1587 sms_trim_args(q->vcnt, argv);
1591 name = argv[4] = malloc(256);
1593 ## repeat retrieve (name = users.login) where users.users_id = @id
1596 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1599 ## inquire_equel(rowcount = "rowcount")
1601 sprintf(argv[4], "#%d", id);
1605 if ((name = argv[2] = malloc(33)) == NULL)
1607 if (!strcmp(argv[1], "LIST")) {
1608 ## repeat retrieve (name = list.#name) where list.list_id = @id
1609 ## inquire_equel(rowcount = "rowcount")
1611 strcpy(name, "???");
1612 } else if (!strcmp(argv[1], "USER")) {
1613 ## repeat retrieve (name = users.login) where users.users_id = @id
1614 ## inquire_equel(rowcount = "rowcount")
1616 strcpy(name, "???");
1617 } else if (!strcmp(argv[1], "KERBEROS")) {
1618 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1619 ## inquire_equel(rowcount = "rowcount")
1621 strcpy(name, "???");
1622 } else if (!strcmp(argv[1], "NONE")) {
1623 strcpy(name, "NONE");
1625 strcpy(name, "???");
1629 (*action)(q->vcnt, argv, actarg);
1631 /* free saved data */
1632 for (i = 0; i < q->vcnt; i++)
1637 return(SMS_SUCCESS);
1642 /* Special query routines */
1644 /* set_pobox - this does all of the real work.
1645 * argv = user_id, type, box
1646 * if type is POP, then box should be a machine, and its ID should be put in
1647 * pop_id. If type is SMTP, then box should be a string and its ID should
1648 * be put in box_id. If type is NONE, then box doesn't matter.
1651 int set_pobox(q, argv, cl)
1656 ## int user, id, rowcount;
1657 ## char *box, potype[9];
1660 user = *(int *)argv[0];
1662 ## repeat retrieve (id = users.pop_id, potype = users.#potype)
1663 ## where users.users_id = @user
1664 if (!strcmp(strtrim(potype), "POP"))
1665 set_pop_usage(id, -1);
1667 if (!strcmp(argv[1], "POP")) {
1668 ## repeat retrieve (id=machine.mach_id) where machine.name=uppercase(@box)
1669 ## inquire_equel(rowcount = "rowcount")
1671 return(SMS_MACHINE);
1672 ## repeat replace users (#potype = "POP", pop_id = @id)
1673 ## where users.users_id = @user
1674 set_pop_usage(id, 1);
1675 } else if (!strcmp(argv[1], "SMTP")) {
1676 ## range of s is strings
1677 ## repeat retrieve (id = s.string_id) where s.string = @box
1678 ## inquire_equel (rowcount = "rowcount")
1679 if (rowcount == 0) {
1680 ## range of v is values
1681 ## repeat retrieve (id = v.value) where v.name = "strings_id"
1683 ## repeat replace v (value = @id) where v.name = "strings_id"
1684 ## append to strings (string_id = id, string = box)
1686 ## repeat replace users (#potype = "SMTP", box_id = @id)
1687 ## where users.users_id = @user
1688 } else /* argv[1] == "NONE" */ {
1689 ## repeat replace users (#potype = "NONE") where users.users_id = @user
1692 set_pobox_modtime(q, argv, cl);
1693 ## repeat replace tblstats (updates = tblstats.updates + 1, modtime = "now")
1694 ## where tblstats.#table = "users"
1695 return(SMS_SUCCESS);
1699 /* get_list_info: passed a wildcard list name, returns lots of stuff about
1700 * each list. This is tricky: first build a queue of all requested
1701 * data. Rest of processing consists of fixing gid, ace_name, and modby.
1704 get_list_info(q, aargv, cl, action, actarg)
1705 register struct query *q;
1708 register int (*action)();
1711 char *argv[13], *malloc(), *realloc();
1712 ## char *name, acl_type[9], listname[33], active[5], public[5], hidden[5];
1713 ## char maillist[5], group[5], gid[6], acl_name[33], desc[256], modtime[27];
1714 ## char modby[256], modwith[9];
1715 ## int id, rowcount, acl_id, hid, modby_id;
1717 struct save_queue *sq, *sq_create();
1719 returned = rowcount = 0;
1723 ## range of l is list
1724 ## repeat retrieve (id = l.list_id) where l.#name = @name {
1725 sq_save_data(sq, id);
1728 if (ingres_errno) return(sms_errcode);
1730 return(SMS_NO_MATCH);
1732 argv[0] = listname; argv[1] = active; argv[2] = public; argv[3] = hidden;
1733 argv[4] = maillist; argv[5] = group; argv[6] = gid; argv[7] = acl_type;
1734 argv[8] = acl_name; argv[9] = desc; argv[10] = modtime; argv[11] = modby;
1737 while (sq_get_data(sq, &id)) {
1741 ## repeat retrieve (listname = l.#name, active = text(l.#active),
1742 ## public = text(l.#public), hidden = text(l.#hidden),
1743 ## hid = l.#hidden, maillist = text(l.#maillist),
1744 ## group = text(l.#group), gid = text(l.#gid),
1745 ## acl_type = trim(l.#acl_type), acl_id = l.#acl_id,
1746 ## desc = l.#desc, modtime = l.#modtime, modby_id = l.#modby,
1747 ## modwith =l.#modwith)
1748 ## where l.list_id = @id
1749 if (ingres_errno) return(sms_errcode);
1751 if (atoi(gid) == -1)
1752 argv[6] = UNIQUE_GID;
1754 if (!strcmp(acl_type, "LIST")) {
1755 ## repeat retrieve (acl_name = l.#name) where l.list_id = @acl_id
1756 ## inquire_equel(rowcount = "rowcount")
1758 strcpy(acl_name, "???");
1759 } else if (!strcmp(acl_type, "USER")) {
1760 ## repeat retrieve (acl_name = users.#login)
1761 ## where users.users_id = @acl_id
1762 ## inquire_equel(rowcount = "rowcount")
1764 strcpy(acl_name, "???");
1765 } else if (!strcmp(acl_type, "KERBEROS")) {
1766 ## repeat retrieve (acl_name = strings.string)
1767 ## where strings.string_id = @acl_id
1768 ## inquire_equel(rowcount = "rowcount")
1770 strcpy(acl_name, "???");
1771 } else if (!strcmp(acl_type, "NONE")) {
1772 strcpy(acl_name, "NONE");
1774 strcpy(acl_name, "???");
1777 ## repeat retrieve (modby = users.login) where users.users_id = @modby_id
1779 modby_id = -modby_id;
1780 ## repeat retrieve (modby = strings.string)
1781 ## where strings.string_id = @modby_id
1782 modby_id = -modby_id;
1784 ## inquire_equel(rowcount = "rowcount")
1786 sprintf(modby, "#%d", modby_id);
1787 if (ingres_errno) return(sms_errcode);
1789 sms_trim_args(q->vcnt, argv);
1791 (*action)(q->vcnt, argv, actarg);
1795 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
1796 ## where tblstats.#table = "list"
1798 return (SMS_SUCCESS);
1802 /* Add_member_to_list: do list flattening as we go! MAXLISTDEPTH is
1803 * how many different ancestors a member is allowed to have.
1806 #define MAXLISTDEPTH 100
1808 int add_member_to_list(q, argv, cl)
1813 ## int id, lid, mid, exists, error;
1814 ## char *mtype, dtype[9];
1815 int ancestors[MAXLISTDEPTH], acount, a;
1816 int descendants[MAXLISTDEPTH], dcount, d;
1817 char *dtypes[MAXLISTDEPTH];
1820 ## range of m is imembers
1821 lid = *(int *)argv[0];
1823 mid = *(int *)argv[2];
1824 ## repeat retrieve (exists = any(m.list_id where m.list_id=@lid and
1825 ## m.member_id = @mid and m.member_type = @mtype
1826 ## and m.direct = 1))
1831 ## repeat retrieve (id = m.list_id)
1832 ## where m.member_id = @lid and m.member_type = "LIST" {
1833 ancestors[acount++] = id;
1834 if (acount >= MAXLISTDEPTH) {
1838 if (ingres_errno) return(sms_errcode);
1839 if (acount >= MAXLISTDEPTH) {
1840 return(SMS_INTERNAL);
1842 descendants[0] = mid;
1846 if (!strcmp(mtype, "LIST")) {
1847 ## repeat retrieve (id = m.member_id, dtype = m.member_type)
1848 ## where m.list_id = @mid {
1851 dtypes[dcount] = "LIST";
1854 dtypes[dcount] = "USER";
1857 dtypes[dcount] = "STRING";
1860 dtypes[dcount] = "KERBEROS";
1866 descendants[dcount++] = id;
1867 if (dcount >= MAXLISTDEPTH) {
1872 if (ingres_errno) return(sms_errcode);
1874 return(SMS_INTERNAL);
1876 for (a = 0; a < acount; a++) {
1878 for (d = 0; d < dcount; d++) {
1879 mid = descendants[d];
1881 if (mid == lid && !strcmp(mtype, "LIST")) {
1882 return(SMS_LISTLOOP);
1884 ## repeat retrieve (exists = any(m.ref_count where m.list_id = @lid
1885 ## and m.member_id = @mid
1886 ## and m.member_type = @mtype))
1888 if (a == 0 && d == 0)
1889 ## replace m (ref_count = m.ref_count+1, direct = 1)
1890 ## where m.list_id = lid and m.member_id = mid and
1891 ## m.member_type = mtype
1893 ## replace m (ref_count = m.ref_count+1)
1894 ## where m.list_id = lid and m.member_id = mid and
1895 ## m.member_type = mtype
1897 incremental_clear_before();
1898 if (a == 0 && d == 0)
1899 ## append imembers (list_id=lid, member_id = mid, direct = 1,
1900 ## member_type=mtype, ref_count = 1)
1902 ## append imembers (list_id=lid, member_id = mid,
1903 ## member_type=mtype, ref_count = 1)
1904 iargv[0] = (char *)lid;
1906 iargv[2] = (char *)mid;
1907 incremental_after("members", 0, iargv);
1911 if (ingres_errno) return(sms_errcode);
1912 return(SMS_SUCCESS);
1916 /* Delete_member_from_list: do list flattening as we go!
1919 int delete_member_from_list(q, argv, cl)
1924 ## int id, lid, mid, cnt, exists, error;
1925 ## char *mtype, dtype[9];
1926 int ancestors[MAXLISTDEPTH], acount, a;
1927 int descendants[MAXLISTDEPTH], dcount, d;
1928 char *dtypes[MAXLISTDEPTH];
1931 ## range of m is imembers
1932 lid = *(int *)argv[0];
1934 mid = *(int *)argv[2];
1935 ## repeat retrieve (exists = any(m.list_id where m.list_id=@lid and
1936 ## m.member_id = @mid and m.member_type = @mtype
1937 ## and m.direct = 1))
1938 if (ingres_errno) return(sms_errcode);
1940 return(SMS_NO_MATCH);
1943 ## repeat retrieve (id = m.list_id)
1944 ## where m.member_id = @lid and m.member_type = "LIST" {
1945 ancestors[acount++] = id;
1946 if (acount >= MAXLISTDEPTH)
1949 if (ingres_errno) return(sms_errcode);
1950 if (acount >= MAXLISTDEPTH)
1951 return(SMS_INTERNAL);
1952 descendants[0] = mid;
1956 if (!strcmp(mtype, "LIST")) {
1957 ## repeat retrieve (id = m.member_id, dtype = m.member_type)
1958 ## where m.list_id = @mid {
1961 dtypes[dcount] = "LIST";
1964 dtypes[dcount] = "USER";
1967 dtypes[dcount] = "STRING";
1970 dtypes[dcount] = "KERBEROS";
1976 descendants[dcount++] = id;
1977 if (dcount >= MAXLISTDEPTH)
1980 if (ingres_errno) return(sms_errcode);
1982 return(SMS_INTERNAL);
1984 for (a = 0; a < acount; a++) {
1986 for (d = 0; d < dcount; d++) {
1987 mid = descendants[d];
1989 if (mid == lid && !strcmp(mtype, "LIST")) {
1990 return(SMS_LISTLOOP);
1992 ## repeat retrieve (cnt = m.ref_count)
1993 ## where m.list_id = @lid and m.member_id = @mid
1994 ## and m.member_type = @mtype
1996 iargv[0] = (char *)lid;
1998 iargv[2] = (char *)mid;
1999 incremental_before("members", 0, iargv);
2000 ## delete m where m.list_id = lid and m.member_id = mid and
2001 ## m.member_type = mtype
2002 incremental_clear_after();
2003 } else if (a == 0 && d == 0) {
2004 ## replace m (ref_count = m.ref_count-1, direct = 0)
2005 ## where m.list_id = lid and m.member_id = mid and
2006 ## m.member_type = mtype
2008 ## replace m (ref_count = m.ref_count-1)
2009 ## where m.list_id = lid and m.member_idn = mid and
2010 ## m.member_type = mtype
2014 if (ingres_errno) return(sms_errcode);
2015 return(SMS_SUCCESS);
2019 /* get_ace_use - given a type and a name, return a type and a name.
2020 * The ace_type is one of "LIST", "USER", "RLIST", or "RUSER" in argv[0],
2021 * and argv[1] will contain the ID of the entity in question. The R*
2022 * types mean to recursively look at every containing list, not just
2023 * when the object in question is a direct member. On return, the
2024 * usage type will be one of LIST, SERVICE, FILESYS, QUOTA, QUERY, or ZEPHYR.
2027 int get_ace_use(q, argv, cl, action, actarg)
2036 ## int aid, listid, id;
2037 struct save_queue *sq, *sq_create();
2039 ## range of m is imembers
2041 aid = *(int *)argv[1];
2042 if (!strcmp(atype, "LIST") || !strcmp(atype, "USER") ||
2043 !strcmp(atype, "KERBEROS")) {
2044 return(get_ace_internal(atype, aid, action, actarg));
2048 if (!strcmp(atype, "RLIST")) {
2049 sq_save_data(sq, aid);
2050 /* get all the list_id's of containing lists */
2051 ## range of m is imembers
2052 ## repeat retrieve (listid = m.list_id)
2053 ## where m.member_type = "LIST" and m.member_id = @id {
2054 sq_save_unique_data(sq, listid);
2056 /* now process each one */
2057 while (sq_get_data(sq, &id)) {
2058 if (get_ace_internal("LIST", id, action, actarg) == SMS_SUCCESS)
2063 if (!strcmp(atype, "RUSER")) {
2064 ## repeat retrieve (listid = m.list_id)
2065 ## where m.member_type = "USER" and m.member_id = @aid {
2066 sq_save_data(sq, listid);
2068 /* now process each one */
2069 while (sq_get_data(sq, &id)) {
2070 if (get_ace_internal("LIST", id, action, actarg) == SMS_SUCCESS)
2073 if (get_ace_internal("USER", aid, action, actarg) == SMS_SUCCESS)
2077 if (!strcmp(atype, "RKERBERO")) {
2078 ## repeat retrieve (listid = m.list_id)
2079 ## where m.member_type = "KERBEROS" and m.member_id = @aid {
2080 sq_save_data(sq, listid);
2082 /* now process each one */
2083 while (sq_get_data(sq, &id)) {
2084 if (get_ace_internal("LIST", id, action, actarg) == SMS_SUCCESS)
2087 if (get_ace_internal("KERBEROS", aid, action, actarg) == SMS_SUCCESS)
2092 if (!found) return(SMS_NO_MATCH);
2093 return(SMS_SUCCESS);
2097 /* This looks up a single list or user for ace use. atype must be "USER"
2098 * or "LIST", and aid is the ID of the corresponding object. This is used
2099 * by get_ace_use above.
2102 ##get_ace_internal(atype, aid, action, actarg)
2113 if (!strcmp(atype, "LIST")) {
2114 rargv[0] = "FILESYS";
2115 ## repeat retrieve (name = filesys.label)
2116 ## where filesys.owners = @aid {
2117 (*action)(2, rargv, actarg);
2122 ## repeat retrieve (name = capacls.capability)
2123 ## where capacls.list_id = @aid {
2124 (*action)(2, rargv, actarg);
2127 } else if (!strcmp(atype, "USER")) {
2128 rargv[0] = "FILESYS";
2129 ## repeat retrieve (name = filesys.label)
2130 ## where filesys.owner = @aid {
2131 (*action)(2, rargv, actarg);
2137 ## repeat retrieve (name = list.#name)
2138 ## where list.acl_type = @atype and list.acl_id = @aid {
2139 (*action)(2, rargv, actarg);
2143 rargv[0] = "SERVICE";
2144 ## repeat retrieve (name = servers.#name)
2145 ## where servers.acl_type = @atype and servers.acl_id = @aid {
2146 (*action)(2, rargv, actarg);
2150 rargv[0] = "HOSTACCESS";
2151 ## repeat retrieve (name = machine.#name)
2152 ## where machine.mach_id = hostaccess.mach_id and
2153 ## hostaccess.acl_type = @atype and hostaccess.acl_id = @aid {
2154 (*action)(2, rargv, actarg);
2157 rargv[0] = "ZEPHYR";
2158 ## repeat retrieve (name = zephyr.class)
2159 ## where zephyr.xmt_type = @atype and zephyr.xmt_id = @aid or
2160 ## zephyr.sub_type = @atype and zephyr.sub_id = @aid or
2161 ## zephyr.iws_type = @atype and zephyr.iws_id = @aid or
2162 ## zephyr.iui_type = @atype and zephyr.iui_id = @aid {
2163 (*action)(2, rargv, actarg);
2167 if (!found) return(SMS_NO_MATCH);
2168 return(SMS_SUCCESS);
2172 /* get_lists_of_member - given a type and a name, return the name and flags
2173 * of all of the lists of the given member. The member_type is one of
2174 * "LIST", "USER", "STRING", "RLIST", "RUSER", or "RSTRING" in argv[0],
2175 * and argv[1] will contain the ID of the entity in question. The R*
2176 * types mean to recursively look at every containing list, not just
2177 * when the object in question is a direct member.
2180 int get_lists_of_member(q, argv, cl, action, actarg)
2187 int found = 0, direct = 1;
2190 ## int aid, listid, id;
2191 ## char name[33], active[5], public[5], hidden[5], maillist[5], group[5];
2194 aid = *(int *)argv[1];
2195 if (!strcmp(atype, "RLIST")) {
2199 if (!strcmp(atype, "RUSER")) {
2203 if (!strcmp(atype, "RSTRING")) {
2207 if (!strcmp(atype, "RKERBEROS")) {
2216 rargv[4] = maillist;
2219 ## repeat retrieve (name = list.#name, active = text(list.#active),
2220 ## public = text(list.#public), hidden = text(list.#hidden),
2221 ## maillist = text(list.#maillist), group = text(list.#group))
2222 ## where list.list_id = m.list_id and m.direct = 1 and
2223 ## m.member_type = @atype and m.member_id = @aid {
2224 (*action)(6, rargv, actarg);
2228 ## repeat retrieve (name = list.#name, active = text(list.#active),
2229 ## public = text(list.#public), hidden = text(list.#hidden),
2230 ## maillist = text(list.#maillist), group = text(list.#group))
2231 ## where list.list_id = m.list_id and
2232 ## m.member_type = @atype and m.member_id = @aid {
2233 (*action)(6, rargv, actarg);
2238 if (!found) return(SMS_NO_MATCH);
2239 return(SMS_SUCCESS);
2243 /* qualified_get_lists: passed "TRUE", "FALSE", or "DONTCARE" for each of
2244 * the five flags associated with each list. It will return the name of
2245 * each list that meets the quailifications. It does this by building a
2246 * where clause based on the arguments, then doing a retrieve.
2249 static char *lflags[5] = { "active", "public", "hidden", "maillist", "group" };
2251 int qualified_get_lists(q, argv, cl, action, actarg)
2258 return(qualified_get(q, argv, action, actarg, "l.list_id != 0",
2259 "l", "name", lflags));
2263 /** get_members_of_list - optimized query for retrieval of list members
2266 ** argv[0] - list_id
2269 ** - retrieve USER members, then LIST members, then STRING members
2272 get_members_of_list(q, argv, cl, action, actarg)
2280 ## char member_name[129];
2283 list_id = *(int *)argv[0];
2285 targv[1] = member_name;
2287 ## range of m is imembers
2288 ## repeat retrieve (member_name = users.login)
2289 ## where m.#list_id = @list_id and m.member_type = "USER"
2290 ## and m.member_id = users.users_id and m.direct = 1
2291 ## sort by #member_name
2293 (*action)(2, targv, actarg);
2297 ## repeat retrieve (member_name = list.name)
2298 ## where m.#list_id = @list_id and m.member_type = "LIST"
2299 ## and m.member_id = list.#list_id and m.direct = 1
2300 ## sort by #member_name
2302 (*action)(2, targv, actarg);
2305 targv[0] = "STRING";
2306 ## repeat retrieve (member_name = strings.string)
2307 ## where m.#list_id = @list_id and m.member_type = "STRING"
2308 ## and m.member_id = strings.string_id and m.direct = 1
2309 ## sort by #member_name
2311 (*action)(2, targv, actarg);
2314 targv[0] = "KERBEROS";
2315 ## repeat retrieve (member_name = strings.string)
2316 ## where m.#list_id = @list_id and m.member_type = "KERBEROS"
2317 ## and m.member_id = strings.string_id and m.direct = 1
2318 ## sort by #member_name
2320 (*action)(2, targv, actarg);
2323 return(SMS_SUCCESS);
2327 /* count_members_of_list: this is a simple query, but it cannot be done
2328 * through the dispatch table.
2331 int count_members_of_list(q, argv, cl, action, actarg)
2338 ## int list, ct = 0;
2339 char *rargv[1], countbuf[5];
2341 list = *(int *)argv[0];
2342 rargv[0] = countbuf;
2343 ## repeat retrieve (ct = count(imembers.list_id
2344 ## where imembers.list_id = @list and
2345 ## imembers.direct = 1))
2346 sprintf(countbuf, "%d", ct);
2347 (*action)(1, rargv, actarg);
2348 return(SMS_SUCCESS);
2352 /* qualified_get_server: passed "TRUE", "FALSE", or "DONTCARE" for each of
2353 * the three flags associated with each service. It will return the name of
2354 * each service that meets the quailifications. It does this by building a
2355 * where clause based on the arguments, then doing a retrieve.
2358 static char *sflags[3] = { "enable", "inprogress", "harderror" };
2360 int qualified_get_server(q, argv, cl, action, actarg)
2367 return(qualified_get(q, argv, action, actarg, "s.name != \"\"",
2368 "s", "name", sflags));
2372 /* generic qualified get routine, used by qualified_get_lists,
2373 * qualified_get_server, and qualified_get_serverhost.
2375 * start - a simple where clause, must not be empty
2376 * range - the name of the range variable
2377 * field - the field to return
2378 * flags - an array of strings, names of the flag variables
2381 int qualified_get(q, argv, action, actarg, start, range, field, flags)
2391 ## char name[33], qual[256], *rvar, *rtbl, *rfield;
2392 char *rargv[1], buf[32];
2395 strcpy(qual, start);
2396 for (i = 0; i < q->argc; i++) {
2397 if (!strcmp(argv[i], "TRUE")) {
2398 sprintf(buf, " and %s.%s != 0", range, flags[i]);
2399 (void) strcat(qual, buf);
2400 } else if (!strcmp(argv[i], "FALSE")) {
2401 sprintf(buf, " and %s.%s = 0", range, flags[i]);
2402 (void) strcat(qual, buf);
2410 ## range of rvar is rtbl
2411 ## retrieve (name = rvar.rfield) where qual {
2412 (*action)(1, rargv, actarg);
2414 ## inquire_equel(rowcount = "rowcount")
2415 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
2416 ## where tblstats.#table = @rtbl
2418 return(SMS_NO_MATCH);
2419 return(SMS_SUCCESS);
2423 /* qualified_get_serverhost: passed "TRUE", "FALSE", or "DONTCARE" for each of
2424 * the five flags associated with each serverhost. It will return the name of
2425 * each service and host that meets the quailifications. It does this by
2426 * building a where clause based on the arguments, then doing a retrieve.
2429 static char *shflags[6] = { "service", "enable", "override", "success",
2430 "inprogress", "hosterror" };
2432 int qualified_get_serverhost(q, argv, cl, action, actarg)
2439 ## char sname[33], mname[33], qual[256];
2440 char *rargv[2], buf[32];
2443 sprintf(qual, "machine.mach_id = sh.mach_id and sh.service = uppercase(\"%s\")",
2445 for (i = 1; i < q->argc; i++) {
2446 if (!strcmp(argv[i], "TRUE")) {
2447 sprintf(buf, " and sh.%s != 0", shflags[i]);
2449 } else if (!strcmp(argv[i], "FALSE")) {
2450 sprintf(buf, " and sh.%s = 0", shflags[i]);
2457 ## range of sh is serverhosts
2458 ## retrieve (sname = sh.service, mname = machine.name) where qual {
2459 (*action)(2, rargv, actarg);
2461 ## inquire_equel(rowcount = "rowcount")
2462 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
2463 ## where tblstats.#table = "serverhosts"
2465 return(SMS_NO_MATCH);
2466 return(SMS_SUCCESS);
2470 /* register_user - change user's login name and allocate a pobox, group,
2471 * filesystem, and quota for them. The user's status must start out as 0,
2472 * and is left as 2. Arguments are: user's UID, new login name, and user's
2473 * type for filesystem allocation (SMS_FS_STUDENT, SMS_FS_FACULTY,
2474 * SMS_FS_STAFF, SMS_FS_MISC).
2477 register_user(q, argv, cl)
2482 ## char *login, dir[65], *entity, *directory, machname[33];
2483 ## int who, rowcount, mid, uid, users_id, flag, utype, nid, list_id, quota;
2484 ## int size, alloc, pid, m_id;
2485 char buffer[256], *aargv[3];
2488 entity = cl->entity;
2489 who = cl->client_id;
2491 uid = atoi(argv[0]);
2493 utype = atoi(argv[2]);
2495 ## range of u is users
2496 ## range of l is list
2497 ## range of sh is serverhosts
2498 ## range of n is nfsphys
2499 ## range of m is machine
2502 ## repeat retrieve (users_id = u.#users_id)
2503 ## where u.#uid = @uid and (u.status = 0 or u.status = 5)
2504 ## inquire_equel(rowcount = "rowcount");
2506 return(SMS_NO_MATCH);
2508 return(SMS_NOT_UNIQUE);
2510 /* check new login name */
2511 ## repeat retrieve (flag = any(u.#login where u.#login = @login and
2512 ## u.#users_id != users_id))
2513 if (ingres_errno) return(sms_errcode);
2514 if (flag) return(SMS_IN_USE);
2515 ## repeat retrieve (flag = any(l.#name where l.#name = @login))
2516 if (ingres_errno) return(sms_errcode);
2517 if (flag) return(SMS_IN_USE);
2518 ## repeat retrieve (flag = any(filesys.#label where filesys.#label = @login))
2519 if (ingres_errno) return(sms_errcode);
2520 if (flag) return(SMS_IN_USE);
2521 com_err(whoami, 0, "new login name OK");
2523 /* choose place for pobox, put in mid */
2524 ## repeat retrieve (mid = sh.mach_id, machname = m.name)
2525 ## where sh.service = "POP" and m.mach_id = sh.mach_id and
2526 ## sh.value2 - sh.value1 = max(sh.value2-sh.value1 where sh.service="POP")
2527 ## inquire_equel(rowcount = "rowcount");
2529 return(SMS_NO_POBOX);
2531 /* change login name, set pobox */
2532 sprintf(buffer, "u.users_id = %d", users_id);
2533 incremental_before("users", buffer, 0);
2534 ## repeat replace u (#login = @login, status = 2, modtime = "now",
2535 ## modby = @who, modwith = @entity, potype="POP",
2536 ## pop_id = @mid, pmodtime="now", pmodby=@who,
2537 ## pmodwith=@entity)
2538 ## where u.#users_id = @users_id
2539 ## inquire_equel(rowcount = "rowcount");
2541 return(SMS_INTERNAL);
2542 set_pop_usage(mid, 1);
2543 com_err(whoami, 0, "set login name to %s and pobox to %s", login,
2545 incremental_after("users", buffer, 0);
2547 /* create group list */
2548 if (set_next_object_id("gid", "list"))
2550 if (set_next_object_id("list_id", "list"))
2552 ## repeat retrieve (list_id = values.value) where values.name = "list_id"
2553 ## inquire_equel(rowcount = "rowcount");
2555 return(SMS_INTERNAL);
2556 incremental_clear_before();
2557 ## repeat append list (name = @login, #list_id = @list_id, active = 1,
2558 ## public = 0, hidden = 0, maillist = 0, group = 1,
2559 ## #gid = values.value, desc = "User Group",
2560 ## acl_type = "USER", acl_id = @users_id, modtime = "now",
2561 ## modby = @who, modwith = @entity)
2562 ## where values.name = "gid"
2563 ## inquire_equel(rowcount = "rowcount");
2565 return(SMS_INTERNAL);
2566 sprintf(buffer, "l.list_id = %d", list_id);
2567 incremental_after("list", buffer, 0);
2568 aargv[0] = (char *) list_id;
2570 aargv[2] = (char *) users_id;
2571 incremental_clear_before();
2572 ## repeat append imembers (#list_id = @list_id, member_type = "USER",
2573 ## member_id = @users_id, ref_count = 1, direct = 1)
2574 ## inquire_equel(rowcount = "rowcount");
2576 return(SMS_INTERNAL);
2577 incremental_after("members", 0, argv);
2578 com_err(whoami, 0, "group list created");
2580 /* decide where to put filesystem */
2583 ## repeat retrieve (mid = n.mach_id, dir = trim(n.#dir), nid = n.nfsphys_id,
2584 ## flag = n.status, size = n.#size, alloc = n.allocated) {
2585 if ((flag & utype) && (size != 0) && (size - alloc > maxsize)) {
2586 maxsize = size - alloc;
2589 directory = strsave(dir);
2595 return(SMS_NO_FILESYS);
2597 /* create filesystem */
2598 if (set_next_object_id("filsys_id", "filesys"))
2600 incremental_clear_before();
2601 ## repeat append filesys (filsys_id = values.value, phys_id = @pid,
2602 ## label = @login, type = "NFS", mach_id = @m_id,
2603 ## name = @directory + "/" + @login,
2604 ## mount = "/mit/" + @login,
2605 ## access = "w", comments = "User Locker",
2606 ## owner = @users_id, owners = @list_id, createflg = 1,
2607 ## lockertype = "HOMEDIR", modtime = "now",
2608 ## modby = @who, modwith = @entity)
2609 ## where values.name = "filsys_id"
2610 ## inquire_equel(rowcount = "rowcount");
2612 return(SMS_INTERNAL);
2613 incremental_after("filesys",
2614 "fs.filsys_id = values.value and values.name = \"filsys_id\"",
2616 com_err(whoami, 0, "filesys created on mach %d in %s/%s", m_id,
2620 ## repeat retrieve (quota = values.value) where values.name = "def_quota"
2621 ## inquire_equel(rowcount = "rowcount");
2623 return(SMS_NO_QUOTA);
2624 incremental_clear_before();
2625 ## repeat append nfsquota (#users_id = @users_id, filsys_id = values.value,
2626 ## #quota = @quota, phys_id = @pid, modtime = "now",
2627 ## modby = @who, modwith = @entity)
2628 ## where values.name = "filsys_id"
2629 ## inquire_equel(rowcount = "rowcount");
2631 return(SMS_INTERNAL);
2632 ## repeat replace nfsphys (allocated = nfsphys.allocated + @quota)
2633 ## where nfsphys.nfsphys_id = filesys.#phys_id and
2634 ## filesys.filsys_id = values.value and values.name = "filsys_id"
2635 ## inquire_equel(rowcount = "rowcount");
2637 return(SMS_INTERNAL);
2640 sprintf(buffer, "nq.users_id = %d and nq.filsys_id = values.value and values.name = \"filsys_id\"", users_id);
2641 incremental_after("nfsquota", buffer, argv);
2642 com_err(whoami, 0, "quota of %d assigned", quota);
2644 ## repeat replace tblstats (updates = tblstats.updates + 1, modtime = "now")
2645 ## where tblstats.table = "users"
2646 ## repeat replace tblstats (appends = tblstats.appends + 1, modtime = "now")
2647 ## where tblstats.table = "list" or tblstats.table = "filesys" or
2648 ## tblstats.table = "nfsquota"
2649 return(SMS_SUCCESS);
2654 /** set_pop_usage - incr/decr usage count for pop server in serverhosts talbe
2658 ** delta (will be +/- 1)
2661 ** - incr/decr value field in serverhosts table for pop/mach_id
2665 static int set_pop_usage(id, count)
2669 ## int mach_id = id;
2672 ## range of sh is serverhosts
2673 ## repeat replace sh (value1 = sh.value1 + @n)
2674 ## where sh.service = "POP" and sh.#mach_id = @mach_id
2676 return(SMS_SUCCESS);
2681 /* Validation Routines */
2683 validate_row(q, argv, v)
2684 register struct query *q;
2686 register struct validate *v;
2694 /* build where clause */
2695 build_qual(v->qual, v->argc, argv, qual);
2697 /* setup ingres variables */
2702 if (log_flags & LOG_VALID)
2703 /* tell the logfile what we're doing */
2704 com_err(whoami, 0, "validating row: %s", qual);
2706 /* look for the record */
2707 ## range of rvar is table
2708 ## retrieve (rowcount = count(rvar.name where qual))
2709 if (ingres_errno) return(sms_errcode);
2710 if (rowcount == 0) return(SMS_NO_MATCH);
2711 if (rowcount > 1) return(SMS_NOT_UNIQUE);
2715 validate_fields(q, argv, vo, n)
2717 register char *argv[];
2718 register struct valobj *vo;
2721 register int status;
2726 if (log_flags & LOG_VALID)
2727 com_err(whoami, 0, "validating %s in %s: %s",
2728 vo->namefield, vo->table, argv[vo->index]);
2729 status = validate_name(argv, vo);
2733 if (log_flags & LOG_VALID)
2734 com_err(whoami, 0, "validating %s in %s: %s",
2735 vo->idfield, vo->table, argv[vo->index]);
2736 status = validate_id(argv, vo);
2740 if (log_flags & LOG_VALID)
2741 com_err(whoami, 0, "validating date: %s", argv[vo->index]);
2742 status = validate_date(argv, vo);
2746 if (log_flags & LOG_VALID)
2747 com_err(whoami, 0, "validating %s type: %s",
2748 vo->table, argv[vo->index]);
2749 status = validate_type(argv, vo);
2753 if (log_flags & LOG_VALID)
2754 com_err(whoami, 0, "validating typed data (%s): %s",
2755 argv[vo->index - 1], argv[vo->index]);
2756 status = validate_typedata(q, argv, vo);
2760 if (log_flags & LOG_VALID)
2761 com_err(whoami, 0, "validating rename %s in %s",
2762 argv[vo->index], vo->table);
2763 status = validate_rename(argv, vo);
2767 if (log_flags & LOG_VALID)
2768 com_err(whoami, 0, "validating chars: %s", argv[vo->index]);
2769 status = validate_chars(argv[vo->index]);
2773 status = SMS_EXISTS;
2777 status = lock_table(vo);
2781 if (status != SMS_EXISTS) return(status);
2785 return(SMS_SUCCESS);
2789 /* validate_chars: verify that there are no illegal characters in
2790 * the string. Legal characters are printing chars other than
2791 * ", *, ?, \, [ and ].
2793 static int illegalchars[] = {
2794 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
2795 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
2796 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
2797 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
2798 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ - O */
2799 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* P - _ */
2800 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
2801 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
2802 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2803 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2804 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2805 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2806 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2807 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2808 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2809 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2816 if (illegalchars[*s++])
2817 return(SMS_BAD_CHAR);
2822 validate_id(argv, vo)
2824 register struct valobj *vo;
2834 name = argv[vo->index];
2836 /* minor kludge to upcasify machine names */
2837 if (!strcmp(table, "machine"))
2838 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
2839 namefield = vo->namefield;
2840 idfield = vo->idfield;
2841 if (!strcmp(namefield, "uid")) {
2842 ## retrieve (id = table.idfield) where table.namefield = int4(name)
2843 if (ingres_errno) return(sms_errcode);
2844 ## inquire_equel (rowcount = "rowcount")
2846 ## retrieve (id = table.idfield) where table.namefield = name
2847 if (ingres_errno) return(sms_errcode);
2848 ## inquire_equel (rowcount = "rowcount")
2850 if (rowcount != 1) return(vo->error);
2851 *(int *)argv[vo->index] = id;
2855 validate_name(argv, vo)
2857 register struct valobj *vo;
2865 name = argv[vo->index];
2867 namefield = vo->namefield;
2868 if (!strcmp(table, "servers") && !strcmp(namefield, "name")) {
2869 for (c = name; *c; c++)
2873 ## retrieve (rowcount = countu(table.namefield
2874 ## where table.namefield = name))
2875 if (ingres_errno) return(sms_errcode);
2876 return ((rowcount == 1) ? SMS_EXISTS : vo->error);
2879 validate_date(argv, vo)
2887 idate = argv[vo->index];
2889 ## retrieve (dd = interval("years", date(idate) - date("today")))
2890 ## inquire_equel (errorno = "errorno")
2891 if (errorno != 0 || dd > 5.0) return(SMS_DATE);
2896 validate_rename(argv, vo)
2900 ## char *name, *table, *namefield, *idfield;
2904 c = name = argv[vo->index];
2906 if (illegalchars[*c++])
2907 return(SMS_BAD_CHAR);
2909 /* minor kludge to upcasify machine names */
2910 if (!strcmp(table, "machine"))
2911 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
2912 namefield = vo->namefield;
2913 idfield = vo->idfield;
2916 if (!strcmp(argv[vo->index], argv[vo->index - 1]))
2918 ## retrieve (id = any(table.namefield where table.namefield = name))
2919 if (ingres_errno) return(sms_errcode);
2925 ## retrieve (id = table.idfield) where table.namefield = name
2926 if (ingres_errno) return(sms_errcode);
2927 if (id == -1 || id == *(int *)argv[vo->index - 1])
2934 validate_type(argv, vo)
2936 register struct valobj *vo;
2943 typename = vo->table;
2944 c = value = argv[vo->index];
2946 if (illegalchars[*c++])
2947 return(SMS_BAD_CHAR);
2949 /* uppercase type fields */
2950 for (c = value; *c; c++) if (islower(*c)) *c = toupper(*c);
2952 ## range of a is alias
2953 ## repeat retrieve (exists = any(a.trans where a.name = @typename and
2954 ## a.type = "TYPE" and
2955 ## a.trans = @value))
2956 if (ingres_errno) return(sms_errcode);
2957 return (exists ? SMS_EXISTS : vo->error);
2960 /* validate member or type-specific data field */
2962 validate_typedata(q, argv, vo)
2963 register struct query *q;
2964 register char *argv[];
2965 register struct valobj *vo;
2968 ## char *field_type;
2969 ## char data_type[129];
2975 /* get named object */
2976 name = argv[vo->index];
2978 /* get field type string (known to be at index-1) */
2979 field_type = argv[vo->index-1];
2981 /* get corresponding data type associated with field type name */
2982 ## repeat retrieve (data_type = alias.trans)
2983 ## where alias.#name = @field_type and alias.type = "TYPEDATA"
2984 if (ingres_errno) return(sms_errcode);
2985 ## inquire_equel (rowcount = "rowcount")
2986 if (rowcount != 1) return(SMS_TYPE);
2988 /* now retrieve the record id corresponding to the named object */
2989 if (index(data_type, ' '))
2990 *index(data_type, ' ') = 0;
2991 if (!strcmp(data_type, "user")) {
2993 ## repeat retrieve (id = users.users_id) where users.login = @name
2994 ## inquire_equel (rowcount = "rowcount")
2995 if (rowcount != 1) return(SMS_USER);
2997 } else if (!strcmp(data_type, "list")) {
2999 ## repeat retrieve (id = list.list_id) where list.#name = @name
3000 ## inquire_equel (rowcount = "rowcount")
3001 if (rowcount != 1) {
3002 /* if idfield is non-zero, then if argv[0] matches the string
3003 * that we're trying to resolve, we should get the value of
3004 * values.[idfield] for the id.
3006 if (vo->idfield && !strcmp(argv[0], argv[vo->index])) {
3007 set_next_object_id(q->validate->object_id, q->rtable);
3009 ## repeat retrieve (id = values.value) where values.#name = @name
3010 ## inquire_equel(rowcount = "rowcount")
3011 if (rowcount != 1) return(SMS_LIST);
3015 } else if (!strcmp(data_type, "machine")) {
3017 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3018 ## repeat retrieve (id = machine.mach_id) where machine.#name = @name
3019 ## inquire_equel (rowcount = "rowcount")
3020 if (rowcount != 1) return(SMS_MACHINE);
3022 } else if (!strcmp(data_type, "string")) {
3024 ## range of s is strings
3025 ## repeat retrieve (id = s.string_id) where s.string = @name
3026 ## inquire_equel (rowcount = "rowcount")
3027 if (rowcount == 0) {
3028 if (q->type != APPEND) return(SMS_STRING);
3029 ## range of v is values
3030 ## retrieve (id = v.value) where v.#name = "strings_id"
3032 ## replace v (value = id) where v.#name = "strings_id"
3033 ## append to strings (string_id = id, string = name)
3035 } else if (!strcmp(data_type, "none")) {
3041 /* now set value in argv */
3042 *(int *)argv[vo->index] = id;
3044 return (SMS_EXISTS);
3048 /* Lock the table named by the validation object */
3053 ## char *table, *idfield;
3057 idfield = vo->idfield;
3058 ## replace table (modtime = "now") where table.idfield = 0
3059 if (ingres_errno) return(sms_errcode);
3060 ## inquire_equel (rowcount = "rowcount")
3068 /* Check the database at startup time. For now this just resets the
3069 * inprogress flags that the DCM uses.
3072 sanity_check_database()