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"))
395 /* setup_spop: verify that there is already a valid POP machine_id in the
396 * pop_id field. Also take care of keeping track of the post office usage.
398 int setup_spop(q, argv)
402 ## int id, mid, flag;
405 id = *(int *)argv[0];
406 ## repeat retrieve (type = u.potype, mid = u.pop_id,
407 ## flag = any(machine.name where machine.mach_id = u.pop_id
408 ## and u.pop_id != 0 and u.users_id = @id))
409 ## where u.users_id = @id
412 if (strcmp(strtrim(type), "POP"))
413 set_pop_usage(mid, 1);
418 /* setup_dpob: Take care of keeping track of the post office usage.
420 int setup_dpob(q, argv)
427 user = *(int *)argv[0];
428 ## repeat retrieve (type = u.potype, id = u.pop_id)
429 ## where u.users_id = @user
430 if (ingres_errno) return(sms_errcode);
432 if (!strcmp(strtrim(type), "POP"))
433 set_pop_usage(id, -1);
438 /* setup_dmac - verify that the machine is no longer being referenced
439 * and may safely be deleted.
442 int setup_dmac(q, argv)
448 id = *(int *)argv[0];
449 ## repeat retrieve (flag = any(users.login where users.potype = "POP"
450 ## and users.pop_id=@id))
453 ## repeat retrieve (flag = any(serverhosts.mach_id
454 ## where serverhosts.mach_id=@id))
457 ## repeat retrieve (flag = any(nfsphys.mach_id where nfsphys.mach_id=@id))
460 ## repeat retrieve (flag = any(hostaccess.mach_id where hostaccess.mach_id=@id))
463 ## repeat retrieve (flag = any(printcap.mach_id where printcap.mach_id=@id))
466 ## repeat retrieve (flag = any(palladium.mach_id where palladium.mach_id=@id))
470 ## repeat delete mcmap where mcmap.mach_id = @id
471 if (ingres_errno) return(sms_errcode);
476 /* setup_dclu - verify that the cluster is no longer being referenced
477 * and may safely be deleted.
480 int setup_dclu(q, argv)
486 id = *(int *)argv[0];
487 ## repeat retrieve (flag = any(mcmap.mach_id where mcmap.clu_id=@id))
490 ## repeat retrieve (flag = any(svc.clu_id where svc.clu_id=@id))
499 /* setup_alis - if argv[5] is non-zero and argv[6] is UNIQUE_ID, then allocate
500 * a new gid and put it in argv[6]. Otherwise if argv[6] is UNIQUE_ID but
501 * argv[5] is not, then remember that UNIQUE_ID is being stored by putting
502 * a -1 there. Remember that this is also used for ulis, with the indexes
506 int setup_alis(q, argv)
514 if (!strcmp(q->shortname, "alis"))
516 else if (!strcmp(q->shortname, "ulis"))
519 if (!strcmp(argv[idx], UNIQUE_GID) || atoi(argv[idx]) == -1) {
520 if (atoi(argv[idx - 1])) {
521 if (set_next_object_id("gid", "list"))
522 return(SMS_INGRES_ERR);
523 ## repeat retrieve (ngid = values.value) where values.name = "gid"
524 if (ingres_errno) return(sms_errcode);
525 sprintf(argv[idx], "%d", ngid);
527 strcpy(argv[idx], "-1");
535 /* setup_dlist - verify that the list is no longer being referenced
536 * and may safely be deleted.
539 int setup_dlis(q, argv)
545 id = *(int *)argv[0];
546 ## repeat retrieve (flag = any(imembers.member_id where imembers.member_id=@id
547 ## and imembers.member_type = "LIST"))
550 ## repeat retrieve (flag = any(imembers.member_id where imembers.list_id=@id))
553 ## repeat retrieve (flag = any(filesys.label where filesys.owners=@id))
556 ## repeat retrieve (flag = any(capacls.tag where capacls.list_id=@id))
559 ## repeat retrieve (flag = any(list.name where list.acl_id=@id and
560 ## list.acl_type = "LIST" and list.list_id != @id))
563 ## repeat retrieve (flag = any(servers.name where servers.acl_id=@id and
564 ## servers.acl_type = "LIST"))
567 ## repeat retrieve (flag=any(hostaccess.acl_id where hostaccess.acl_id=@id and
568 ## hostaccess.acl_type = "LIST"))
571 ## repeat retrieve (flag = any(zephyr.class
572 ## where zephyr.xmt_type = "LIST" and zephyr.xmt_id = @id or
573 ## zephyr.sub_type = "LIST" and zephyr.sub_id = @id or
574 ## zephyr.iws_type = "LIST" and zephyr.iws_id = @id or
575 ## zephyr.iui_type = "LIST" and zephyr.iui_id = @id))
584 /* setup_dsin - verify that the service is no longer being referenced
585 * and may safely be deleted.
588 int setup_dsin(q, argv)
596 ## repeat retrieve (flag = any(serverhosts.service
597 ## where serverhosts.service=uppercase(@name)))
600 ## repeat retrieve (flag = servers.inprogress) where servers.#name = @name
609 /* setup_dshi - verify that the service-host is no longer being referenced
610 * and may safely be deleted.
613 int setup_dshi(q, argv)
621 id = *(int *)argv[1];
622 ## repeat retrieve (flag=serverhosts.inprogress)
623 ## where serverhosts.service=uppercase(@name) and serverhosts.mach_id=@id
633 ** setup_add_filesys - verify existance of referenced file systems
645 ** * extract directory prefix from name
646 ** * verify mach_id/dir in nfsphys
647 ** * verify access in {r, w, R, W}
649 ** Side effect: sets variable var_phys_id to the ID of the physical
650 ** filesystem (nfsphys_id for NFS, 0 for RVD)
653 ** SMS_NFS - specified directory not exported
654 ** SMS_FILESYS_ACCESS - invalid filesys access
658 ##static int var_phys_id;
670 mach_id = *(int *)argv[2];
675 if (!strcmp(type, "NFS"))
676 return (check_nfs(mach_id, name, access));
682 /* Verify the arguments, depending on the FStype. Also, if this is an
683 * NFS filesystem, then update any quotas for that filesystem to reflect
692 char *type, *name, *access;
696 mach_id = *(int *)argv[3];
701 if (!strcmp(type, "NFS")) {
702 status = check_nfs(mach_id, name, access);
703 fid = *(int *)argv[0];
704 ## replace nfsquota (phys_id = var_phys_id) where nfsquota.filsys_id = fid
705 if (ingres_errno) return(sms_errcode);
712 /* Find the NFS physical partition that the named directory is on.
713 * This is done by comparing the dir against the mount point of the
714 * partition. To make sure we get the correct match when there is
715 * more than one, we sort the query in reverse order by dir name.
718 ##check_nfs(mach_id, name, access)
729 caccess = (isupper(*access)) ? tolower(*access) : *access;
730 if (caccess != 'r' && caccess != 'w') return(SMS_FILESYS_ACCESS);
733 ## range of np is nfsphys
734 ## repeat retrieve (var_phys_id = np.#nfsphys_id, dir = trim(np.#dir))
735 ## where np.#mach_id = @mach_id sort by #dir:d {
739 if (*cp1++ != *cp2) break;
743 status = SMS_SUCCESS;
753 /* setup_dfil: free any quota records and fsgroup info associated with
754 * a filesystem when it is deleted. Also adjust the allocation numbers.
757 setup_dfil(q, argv, cl)
764 id = *(int *)argv[0];
765 ## range of q is nfsquota
766 ## range of fs is filesys
767 ## range of n is nfsphys
768 ## repeat replace n (allocated=n.allocated-sum(q.quota where q.filsys_id=@id))
769 ## where n.nfsphys_id = fs.phys_id and fs.filsys_id = @id
771 ## repeat delete q where q.filsys_id = @id
772 ## repeat delete fsgroup where fsgroup.filsys_id = @id
773 ## repeat delete fsgroup where fsgroup.group_id = @id
774 if (ingres_errno) return(sms_errcode);
779 /* setup_dnfp: check to see that the nfs physical partition does not have
780 * any filesystems assigned to it before allowing it to be deleted.
783 setup_dnfp(q, argv, cl)
790 id = *(int *)argv[0];
791 ## repeat retrieve (exists = any(filesys.label where filesys.phys_id = @id))
800 /* setup_dnfq: Remove allocation from nfsphys before deleting quota.
801 * argv[0] = filsys_id
805 setup_dnfq(q, argv, cl)
810 ## int quota, fs, user;
812 fs = *(int *)argv[0];
813 user = *(int *)argv[1];
815 ## range of q is nfsquota
816 ## repeat retrieve (quota = q.#quota) where q.users_id = @user and
818 ## repeat replace nfsphys (allocated = nfsphys.allocated - @quota)
819 ## where nfsphys.nfsphys_id = filesys.#phys_id and filesys.filsys_id = @fs
820 if (ingres_errno) return(sms_errcode);
825 /* setup_sshi: don't exclusive lock the machine table during
826 * set_server_host_internal.
829 setup_sshi(q, argv, cl)
834 ## set lockmode session where readlock = system
838 /* setup add_kerberos_user_mapping: add the string to the string
839 * table if necessary.
842 setup_akum(q, argv, cl)
851 ## range of s is strings
852 ## repeat retrieve (id = s.string_id) where s.string = @name
853 ## inquire_equel (rowcount = "rowcount")
855 if (q->type != APPEND) return(SMS_STRING);
856 ## range of v is values
857 ## retrieve (id = v.value) where v.#name = "strings_id"
859 ## replace v (value = id) where v.#name = "strings_id"
860 ## append to strings (string_id = id, string = name)
862 if (ingres_errno) return(sms_errcode);
863 *(int *)argv[1] = id;
869 /* FOLLOWUP ROUTINES */
871 /* generic set_modtime routine. This takes the table name from the query,
872 * and will update the modtime, modby, and modwho fields in the entry in
873 * the table whose name field matches argv[0].
876 set_modtime(q, argv, cl)
881 ## char *name, *entity, *table;
889 ## replace table (modtime = "now", modby = who, modwith = entity)
890 ## where table.#name = name
894 /* generic set_modtime_by_id routine. This takes the table name from
895 * the query, and the id name from the validate record,
896 * and will update the modtime, modby, and modwho fields in the entry in
897 * the table whose id matches argv[0].
900 set_modtime_by_id(q, argv, cl)
905 ## char *entity, *table, *id_name;
911 id_name = q->validate->object_id;
913 id = *(int *)argv[0];
914 ## replace table (modtime = "now", modby = who, modwith = entity)
915 ## where table.id_name = id
920 /* Sets the finger modtime on a user record. The users_id will be in argv[0].
923 set_finger_modtime(q, argv, cl)
928 ## int users_id, who;
933 users_id = *(int *)argv[0];
935 ## repeat replace u (fmodtime = "now", fmodby = @who, fmodwith = @entity)
936 ## where u.#users_id = @users_id
941 /* Sets the pobox modtime on a user record. The users_id will be in argv[0].
944 set_pobox_modtime(q, argv, cl)
949 ## int users_id, who;
954 users_id = *(int *)argv[0];
956 ## repeat replace users (pmodtime = "now", pmodby = @who, pmodwith = @entity)
957 ## where users.#users_id = @users_id
962 /* Like set_modtime, but uppercases the name first.
965 set_uppercase_modtime(q, argv, cl)
970 ## char *name, *entity, *table;
978 ## replace table (modtime = "now", modby = who, modwith = entity)
979 ## where table.#name = uppercase(name)
984 /* Sets the modtime on the machine whose mach_id is in argv[0]. This routine
985 * is necessary for add_machine_to_cluster becuase the table that query
986 * operates on is "mcm", not "machine".
989 set_mach_modtime_by_id(q, argv, cl)
1000 id = *(int *)argv[0];
1001 ## range of m is machine
1002 ## repeat replace m (modtime = "now", modby = @who, modwith = @entity)
1003 ## where m.mach_id = @id
1004 return(SMS_SUCCESS);
1008 /* Sets the modtime on the cluster whose mach_id is in argv[0]. This routine
1009 * is necessary for add_cluster_data and delete_cluster_data becuase the
1010 * table that query operates on is "svc", not "cluster".
1013 set_cluster_modtime_by_id(q, argv, cl)
1021 entity = cl->entity;
1022 who = cl->client_id;
1024 id = *(int *)argv[0];
1025 ## range of c is cluster
1026 ## repeat replace c (modtime = "now", modby = @who, modwith = @entity)
1027 ## where c.clu_id = @id
1028 return(SMS_SUCCESS);
1032 /* sets the modtime on the serverhost where the service name is in argv[0]
1033 * and the mach_id is in argv[1].
1036 set_serverhost_modtime(q, argv, cl)
1041 ## char *entity, *serv;
1044 entity = cl->entity;
1045 who = cl->client_id;
1048 id = *(int *)argv[1];
1049 ## repeat replace sh (modtime = "now", modby = @who, modwith = @entity)
1050 ## where sh.service = uppercase(@serv) and sh.mach_id = @id
1051 return(SMS_SUCCESS);
1055 /* sets the modtime on the nfsphys where the mach_id is in argv[0] and the
1056 * directory name is in argv[1].
1059 set_nfsphys_modtime(q, argv, cl)
1064 ## char *entity, *dir;
1067 entity = cl->entity;
1068 who = cl->client_id;
1070 id = *(int *)argv[0];
1072 ## repeat replace np (modtime = "now", modby = @who, modwith = @entity)
1073 ## where np.#dir = @dir and np.mach_id = @id
1074 return(SMS_SUCCESS);
1078 /* sets the modtime on a filesystem, where argv[0] contains the filesys
1082 set_filesys_modtime(q, argv, cl)
1087 ## char *label, *entity;
1090 entity = cl->entity;
1091 who = cl->client_id;
1094 if (!strcmp(q->shortname, "ufil"))
1097 ## repeat replace fs (modtime = "now", modby = @who, modwith = @entity,
1098 ## #phys_id = @var_phys_id) where fs.#label = @label
1099 return(SMS_SUCCESS);
1103 /* sets the modtime on a zephyr class, where argv[0] contains the class
1107 set_zephyr_modtime(q, argv, cl)
1112 ## char *class, *entity;
1115 entity = cl->entity;
1116 who = cl->client_id;
1120 ## repeat replace z (modtime = "now", modby = @who, modwith = @entity)
1121 ## where z.#class = @class
1122 return(SMS_SUCCESS);
1126 /* fixes the modby field. This will be the second to last thing in the
1127 * argv, the argv length is determined from the query structure. It is
1128 * passed as a pointer to an integer. This will either turn it into a
1129 * username, or # + the users_id.
1131 followup_fix_modby(q, sq, v, action, actarg, cl)
1133 register struct save_queue *sq;
1135 register int (*action)();
1136 register int actarg;
1140 char **argv, *malloc();
1141 ## int id, rowcount;
1145 while (sq_get_data(sq, &argv)) {
1148 argv[i] = malloc(256);
1151 ## repeat retrieve (name = users.login) where users.users_id = @id
1154 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1157 ## inquire_equel(rowcount = "rowcount")
1158 if (rowcount != 1) {
1159 sprintf(argv[i], "#%d", id);
1161 (*action)(q->vcnt, argv, actarg);
1162 for (j = 0; j < q->vcnt; j++)
1167 if (ingres_errno) return(sms_errcode);
1168 return(SMS_SUCCESS);
1173 ** followup_ausr - add finger and pobox entries, set_user_modtime
1176 ** argv[0] - login (add_user)
1177 ** argv[3] - last name
1178 ** argv[4] - first name
1179 ** argv[5] - middle name
1183 followup_ausr(q, argv, cl)
1189 ## char *login, *entity;
1190 ## char fullname[129];
1193 who = cl->client_id;
1194 entity = cl->entity;
1196 /* build fullname */
1197 if (strlen(argv[4]) && strlen(argv[5]))
1198 sprintf(fullname, "%s %s %s", argv[4], argv[5], argv[3]);
1199 else if (strlen(argv[4]))
1200 sprintf(fullname, "%s %s", argv[4], argv[3]);
1202 sprintf(fullname, "%s", argv[3]);
1204 /* create finger entry, pobox & set modtime on user */
1205 ## repeat replace u (modtime = "now", modby=@who, modwith=@entity,
1206 ## #fullname=@fullname, mit_affil = u.mit_year,
1207 ## fmodtime="now", fmodby=@who, fmodwith=@entity,
1208 ## potype="NONE", pmodtime="now", pmodby=@who, pmodwith=@entity)
1209 ## where u.#login = @login
1211 return(SMS_SUCCESS);
1215 /* followup_gpob: fixes argv[2] based on the IDs currently there and the
1216 * type in argv[1]. Then completes the upcall to the user.
1218 * argv[2] is of the form "123:234" where the first integer is the machine
1219 * ID if it is a pop box, and the second is the string ID if it is an SMTP
1220 * box. argv[1] should be "POP", "SMTP", or "NONE". Boxes of type NONE
1224 followup_gpob(q, sq, v, action, actarg, cl)
1225 register struct query *q;
1226 register struct save_queue *sq;
1227 register struct validate *v;
1228 register int (*action)();
1232 char **argv, *index();
1234 ## char box[129], *name;
1235 ## int mid, sid, rowcount;
1238 while (sq_get_data(sq, &argv)) {
1239 sms_trim_args(2, argv);
1241 p = index(argv[2], ':');
1243 mid = atoi(argv[2]);
1247 if (!strcmp(ptype, "POP")) {
1248 ## repeat retrieve (box=machine.#name) where machine.mach_id=@mid
1249 ## inquire_equel(rowcount = "rowcount")
1251 return(SMS_MACHINE);
1252 } else if (!strcmp(ptype, "SMTP")) {
1253 ## repeat retrieve (box=strings.string) where strings.string_id=@sid
1254 ## inquire_equel(rowcount = "rowcount")
1257 } else /* ptype == "NONE" */ {
1261 if (!strcmp(q->shortname, "gpob")) {
1262 sid = atoi(argv[4]);
1264 argv[4] = malloc(256);
1267 ## repeat retrieve (name = users.login) where users.users_id = @sid
1270 ## repeat retrieve (name = strings.string)
1271 ## where strings.string_id = @sid
1274 ## inquire_equel(rowcount = "rowcount")
1276 sprintf(name, "#%d", sid);
1280 (*action)(q->vcnt, argv, actarg);
1282 /* free saved data */
1290 return (SMS_SUCCESS);
1294 /* followup_glin: fix the ace_name in argv[8]. argv[7] will contain the
1295 * ace_type: "LIST", "USER", or "NONE". Decode the id in argv[8] into the
1296 * proper name based on the type, and repace that string in the argv.
1297 * Also fixes the modby field by called followup_fix_modby.
1300 followup_glin(q, sq, v, action, actarg, cl)
1301 register struct query *q;
1302 register struct save_queue *sq;
1303 register struct validate *v;
1304 register int (*action)();
1308 char **argv, *malloc(), *realloc(), *type;
1310 ## int id, rowcount;
1314 if (!strcmp(q->shortname, "gsin"))
1317 while (sq_get_data(sq, &argv)) {
1318 sms_trim_args(q->vcnt, argv);
1320 id = atoi(argv[i = q->vcnt - 2]);
1322 name = argv[i] = malloc(256);
1324 ## repeat retrieve (name = users.login) where users.users_id = @id
1327 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1330 ## inquire_equel(rowcount = "rowcount")
1332 sprintf(argv[i], "#%d", id);
1334 id = atoi(argv[idx]);
1335 type = argv[idx - 1];
1336 if ((name = malloc(33)) == NULL)
1339 if (!strcmp(type, "LIST")) {
1340 ## repeat retrieve (name = list.#name) where list.list_id = @id
1341 ## inquire_equel(rowcount = "rowcount")
1343 strcpy(name, "???");
1344 } else if (!strcmp(type, "USER")) {
1345 ## repeat retrieve (name = users.login) where users.users_id = @id
1346 ## inquire_equel(rowcount = "rowcount")
1348 strcpy(name, "???");
1349 } else if (!strcmp(type, "KERBEROS")) {
1350 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1351 ## inquire_equel(rowcount = "rowcount")
1353 strcpy(name, "???");
1354 } else if (!strcmp(type, "NONE")) {
1355 strcpy(name, "NONE");
1357 strcpy(name, "???");
1361 if (!strcmp(q->shortname, "glin") && atoi(argv[6]) == -1) {
1362 argv[6] = realloc(argv[6], strlen(UNIQUE_GID) + 1);
1363 strcpy(argv[6], UNIQUE_GID);
1367 (*action)(q->vcnt, argv, actarg);
1369 /* free saved data */
1370 for (i = 0; i < q->vcnt; i++)
1376 return (SMS_SUCCESS);
1380 /* followup_gnfq: Fix the directory name & modby fields
1381 * argv[0] = filsys_id
1382 * argv[2] = ascii(quota)
1385 followup_gnfq(q, sq, v, action, actarg, cl)
1387 register struct save_queue *sq;
1389 register int (*action)();
1390 register int actarg;
1394 char **argv, *malloc();
1395 ## int id, rowcount;
1396 ## char *name, *label;
1398 while (sq_get_data(sq, &argv)) {
1401 argv[3] = malloc(256);
1405 ## repeat retrieve (name = filesys.#name) where filesys.#label = @label
1407 ## repeat retrieve (name = nfsphys.dir) where nfsphys.nfsphys_id = @id
1409 ## inquire_equel(rowcount = "rowcount")
1410 if (rowcount != 1) {
1411 sprintf(argv[3], "#%d", id);
1416 argv[6] = malloc(256);
1419 ## repeat retrieve (name = users.login) where users.users_id = @id
1422 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1425 ## inquire_equel(rowcount = "rowcount")
1426 if (rowcount != 1) {
1427 sprintf(argv[6], "#%d", id);
1429 (*action)(q->vcnt, argv, actarg);
1430 for (j = 0; j < q->vcnt; j++)
1435 return(SMS_SUCCESS);
1439 /* followup_anfq: Add allocation to nfsphys after creating quota.
1440 * argv[0] = filsys_id
1441 * argv[2] = ascii(quota)
1444 followup_anfq(q, argv, cl)
1449 ## int quota, user, fs, who;
1452 fs = *(int *)argv[0];
1453 user = *(int *)argv[1];
1454 quota = atoi(argv[2]);
1455 who = cl->client_id;
1456 entity = cl->entity;
1458 ## repeat replace nq (modtime = "now", modby = @who, modwith = @entity)
1459 ## where nq.filsys_id = @fs and nq.users_id = @user
1460 ## repeat replace nfsphys (allocated = nfsphys.allocated + @quota)
1461 ## where nfsphys.nfsphys_id = filesys.#phys_id and filesys.filsys_id = @fs
1462 if (ingres_errno) return(sms_errcode);
1463 return(SMS_SUCCESS);
1470 followup_gzcl(q, sq, v, action, actarg, cl)
1471 register struct query *q;
1472 register struct save_queue *sq;
1473 register struct validate *v;
1474 register int (*action)();
1479 ## int rowcount, id;
1483 while (sq_get_data(sq, &argv)) {
1484 sms_trim_args(q->vcnt, argv);
1486 id = atoi(argv[i = q->vcnt - 2]);
1488 name = argv[i] = malloc(256);
1490 ## repeat retrieve (name = users.login) where users.users_id = @id
1493 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1496 ## inquire_equel(rowcount = "rowcount")
1498 sprintf(argv[i], "#%d", id);
1500 for (i = 1; i < 8; i+=2) {
1501 id = atoi(argv[i+1]);
1503 if ((name = argv[i+1] = malloc(33)) == NULL)
1505 if (!strcmp(argv[i], "LIST")) {
1506 ## repeat retrieve (name = list.#name) where list.list_id = @id
1507 ## inquire_equel(rowcount = "rowcount")
1509 strcpy(name, "???");
1510 } else if (!strcmp(argv[i], "USER")) {
1511 ## repeat retrieve (name = users.login) where users.users_id = @id
1512 ## inquire_equel(rowcount = "rowcount")
1514 strcpy(name, "???");
1515 } else if (!strcmp(argv[i], "KERBEROS")) {
1516 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1517 ## inquire_equel(rowcount = "rowcount")
1519 strcpy(name, "???");
1520 } else if (!strcmp(argv[i], "NONE")) {
1521 strcpy(name, "NONE");
1523 strcpy(name, "???");
1528 (*action)(q->vcnt, argv, actarg);
1530 /* free saved data */
1531 for (i = 0; i < q->vcnt; i++)
1536 return(SMS_SUCCESS);
1543 followup_gsha(q, sq, v, action, actarg, cl)
1544 register struct query *q;
1545 register struct save_queue *sq;
1546 register struct validate *v;
1547 register int (*action)();
1552 ## int rowcount, id;
1556 while (sq_get_data(sq, &argv)) {
1557 sms_trim_args(q->vcnt, argv);
1561 name = argv[4] = malloc(256);
1563 ## repeat retrieve (name = users.login) where users.users_id = @id
1566 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1569 ## inquire_equel(rowcount = "rowcount")
1571 sprintf(argv[4], "#%d", id);
1575 if ((name = argv[2] = malloc(33)) == NULL)
1577 if (!strcmp(argv[1], "LIST")) {
1578 ## repeat retrieve (name = list.#name) where list.list_id = @id
1579 ## inquire_equel(rowcount = "rowcount")
1581 strcpy(name, "???");
1582 } else if (!strcmp(argv[1], "USER")) {
1583 ## repeat retrieve (name = users.login) where users.users_id = @id
1584 ## inquire_equel(rowcount = "rowcount")
1586 strcpy(name, "???");
1587 } else if (!strcmp(argv[1], "KERBEROS")) {
1588 ## repeat retrieve (name = strings.string) where strings.string_id = @id
1589 ## inquire_equel(rowcount = "rowcount")
1591 strcpy(name, "???");
1592 } else if (!strcmp(argv[1], "NONE")) {
1593 strcpy(name, "NONE");
1595 strcpy(name, "???");
1599 (*action)(q->vcnt, argv, actarg);
1601 /* free saved data */
1602 for (i = 0; i < q->vcnt; i++)
1607 return(SMS_SUCCESS);
1612 /* Special query routines */
1614 /* set_pobox - this does all of the real work.
1615 * argv = user_id, type, box
1616 * if type is POP, then box should be a machine, and its ID should be put in
1617 * pop_id. If type is SMTP, then box should be a string and its ID should
1618 * be put in box_id. If type is NONE, then box doesn't matter.
1621 int set_pobox(q, argv, cl)
1626 ## int user, id, rowcount;
1627 ## char *box, potype[9];
1630 user = *(int *)argv[0];
1632 ## repeat retrieve (id = users.pop_id, potype = users.#potype)
1633 ## where users.users_id = @user
1634 if (ingres_errno) return(sms_errcode);
1635 if (!strcmp(strtrim(potype), "POP"))
1636 set_pop_usage(id, -1);
1638 if (!strcmp(argv[1], "POP")) {
1639 ## repeat retrieve (id=machine.mach_id) where machine.name=uppercase(@box)
1640 ## inquire_equel(rowcount = "rowcount")
1642 return(SMS_MACHINE);
1643 ## repeat replace users (#potype = "POP", pop_id = @id)
1644 ## where users.users_id = @user
1645 set_pop_usage(id, 1);
1646 } else if (!strcmp(argv[1], "SMTP")) {
1647 if (index(box, '/') || index(box, '|'))
1648 return(SMS_BAD_CHAR);
1649 ## range of s is strings
1650 ## repeat retrieve (id = s.string_id) where s.string = @box
1651 ## inquire_equel (rowcount = "rowcount")
1652 if (rowcount == 0) {
1653 ## range of v is values
1654 ## repeat retrieve (id = v.value) where v.name = "strings_id"
1656 ## repeat replace v (value = @id) where v.name = "strings_id"
1657 ## append to strings (string_id = id, string = box)
1659 ## repeat replace users (#potype = "SMTP", box_id = @id)
1660 ## where users.users_id = @user
1661 } else /* argv[1] == "NONE" */ {
1662 ## repeat replace users (#potype = "NONE") where users.users_id = @user
1665 set_pobox_modtime(q, argv, cl);
1666 ## repeat replace tblstats (updates = tblstats.updates + 1, modtime = "now")
1667 ## where tblstats.#table = "users"
1668 if (ingres_errno) return(sms_errcode);
1669 return(SMS_SUCCESS);
1673 /* get_list_info: passed a wildcard list name, returns lots of stuff about
1674 * each list. This is tricky: first build a queue of all requested
1675 * data. Rest of processing consists of fixing gid, ace_name, and modby.
1678 get_list_info(q, aargv, cl, action, actarg)
1679 register struct query *q;
1682 register int (*action)();
1685 char *argv[13], *malloc(), *realloc();
1686 ## char *name, acl_type[9], listname[33], active[5], public[5], hidden[5];
1687 ## char maillist[5], group[5], gid[6], acl_name[33], desc[256], modtime[27];
1688 ## char modby[256], modwith[9];
1689 ## int id, rowcount, acl_id, hid, modby_id;
1691 struct save_queue *sq, *sq_create();
1693 returned = rowcount = 0;
1697 ## range of l is list
1698 ## repeat retrieve (id = l.list_id) where l.#name = @name {
1699 sq_save_data(sq, id);
1702 if (ingres_errno) return(sms_errcode);
1704 return(SMS_NO_MATCH);
1706 argv[0] = listname; argv[1] = active; argv[2] = public; argv[3] = hidden;
1707 argv[4] = maillist; argv[5] = group; argv[6] = gid; argv[7] = acl_type;
1708 argv[8] = acl_name; argv[9] = desc; argv[10] = modtime; argv[11] = modby;
1711 while (sq_get_data(sq, &id)) {
1715 ## repeat retrieve (listname = l.#name, active = text(l.#active),
1716 ## public = text(l.#public), hidden = text(l.#hidden),
1717 ## hid = l.#hidden, maillist = text(l.#maillist),
1718 ## group = text(l.#group), gid = text(l.#gid),
1719 ## acl_type = trim(l.#acl_type), acl_id = l.#acl_id,
1720 ## desc = l.#desc, modtime = l.#modtime, modby_id = l.#modby,
1721 ## modwith =l.#modwith)
1722 ## where l.list_id = @id
1723 if (ingres_errno) return(sms_errcode);
1725 if (atoi(gid) == -1)
1726 argv[6] = UNIQUE_GID;
1728 if (!strcmp(acl_type, "LIST")) {
1729 ## repeat retrieve (acl_name = l.#name) where l.list_id = @acl_id
1730 ## inquire_equel(rowcount = "rowcount")
1732 strcpy(acl_name, "???");
1733 } else if (!strcmp(acl_type, "USER")) {
1734 ## repeat retrieve (acl_name = users.#login)
1735 ## where users.users_id = @acl_id
1736 ## inquire_equel(rowcount = "rowcount")
1738 strcpy(acl_name, "???");
1739 } else if (!strcmp(acl_type, "KERBEROS")) {
1740 ## repeat retrieve (acl_name = strings.string)
1741 ## where strings.string_id = @acl_id
1742 ## inquire_equel(rowcount = "rowcount")
1744 strcpy(acl_name, "???");
1745 } else if (!strcmp(acl_type, "NONE")) {
1746 strcpy(acl_name, "NONE");
1748 strcpy(acl_name, "???");
1751 ## repeat retrieve (modby = users.login) where users.users_id = @modby_id
1753 modby_id = -modby_id;
1754 ## repeat retrieve (modby = strings.string)
1755 ## where strings.string_id = @modby_id
1756 modby_id = -modby_id;
1758 ## inquire_equel(rowcount = "rowcount")
1760 sprintf(modby, "#%d", modby_id);
1761 if (ingres_errno) return(sms_errcode);
1763 sms_trim_args(q->vcnt, argv);
1765 (*action)(q->vcnt, argv, actarg);
1769 if (ingres_errno) return(sms_errcode);
1770 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
1771 ## where tblstats.#table = "list"
1773 return (SMS_SUCCESS);
1777 /* Add_member_to_list: do list flattening as we go! MAXLISTDEPTH is
1778 * how many different ancestors a member is allowed to have.
1781 #define MAXLISTDEPTH 100
1783 int add_member_to_list(q, argv, cl)
1788 ## int id, lid, mid, exists, error, who;
1789 ## char *mtype, dtype[9], buf[256], *entity;
1790 int ancestors[MAXLISTDEPTH], acount, a;
1791 int descendants[MAXLISTDEPTH], dcount, d;
1792 char *dtypes[MAXLISTDEPTH];
1795 ## range of m is imembers
1796 lid = *(int *)argv[0];
1798 mid = *(int *)argv[2];
1799 ## repeat retrieve (exists = any(m.list_id where m.list_id=@lid and
1800 ## m.member_id = @mid and m.member_type = @mtype
1801 ## and m.direct = 1))
1804 if (!strcasecmp(mtype, "STRING")) {
1805 ## repeat retrieve (buf = strings.string) where strings.string_id = @mid
1806 if (index(buf, '/') || index(buf, '|'))
1807 return(SMS_BAD_CHAR);
1812 ## repeat retrieve (id = m.list_id)
1813 ## where m.member_id = @lid and m.member_type = "LIST" {
1814 ancestors[acount++] = id;
1815 if (acount >= MAXLISTDEPTH) {
1819 if (ingres_errno) return(sms_errcode);
1820 if (acount >= MAXLISTDEPTH) {
1821 return(SMS_INTERNAL);
1823 descendants[0] = mid;
1827 if (!strcmp(mtype, "LIST")) {
1828 ## repeat retrieve (id = m.member_id, dtype = m.member_type)
1829 ## where m.list_id = @mid {
1832 dtypes[dcount] = "LIST";
1835 dtypes[dcount] = "USER";
1838 dtypes[dcount] = "STRING";
1841 dtypes[dcount] = "KERBEROS";
1847 descendants[dcount++] = id;
1848 if (dcount >= MAXLISTDEPTH) {
1853 if (ingres_errno) return(sms_errcode);
1855 return(SMS_INTERNAL);
1857 for (a = 0; a < acount; a++) {
1859 for (d = 0; d < dcount; d++) {
1860 mid = descendants[d];
1862 if (mid == lid && !strcmp(mtype, "LIST")) {
1863 return(SMS_LISTLOOP);
1865 ## repeat retrieve (exists = any(m.ref_count where m.list_id = @lid
1866 ## and m.member_id = @mid
1867 ## and m.member_type = @mtype))
1869 if (a == 0 && d == 0)
1870 ## replace m (ref_count = m.ref_count+1, direct = 1)
1871 ## where m.list_id = lid and m.member_id = mid and
1872 ## m.member_type = mtype
1874 ## replace m (ref_count = m.ref_count+1)
1875 ## where m.list_id = lid and m.member_id = mid and
1876 ## m.member_type = mtype
1878 incremental_clear_before();
1879 if (a == 0 && d == 0)
1880 ## append imembers (list_id=lid, member_id = mid, direct = 1,
1881 ## member_type=mtype, ref_count = 1)
1883 ## append imembers (list_id=lid, member_id = mid,
1884 ## member_type=mtype, ref_count = 1)
1885 iargv[0] = (char *)lid;
1887 iargv[2] = (char *)mid;
1888 incremental_after("members", 0, iargv);
1892 lid = *(int *)argv[0];
1893 entity = cl->entity;
1894 who = cl->client_id;
1895 ## repeat replace list (modtime = "now", modby = @who, modwith = @entity)
1896 ## where list.#list_id = @lid
1897 if (ingres_errno) return(sms_errcode);
1898 return(SMS_SUCCESS);
1902 /* Delete_member_from_list: do list flattening as we go!
1905 int delete_member_from_list(q, argv, cl)
1910 ## int id, lid, mid, cnt, exists, error, who;
1911 ## char *mtype, dtype[9], *entity;
1912 int ancestors[MAXLISTDEPTH], acount, a;
1913 int descendants[MAXLISTDEPTH], dcount, d;
1914 char *dtypes[MAXLISTDEPTH];
1917 ## range of m is imembers
1918 lid = *(int *)argv[0];
1920 mid = *(int *)argv[2];
1921 ## repeat retrieve (exists = any(m.list_id where m.list_id=@lid and
1922 ## m.member_id = @mid and m.member_type = @mtype
1923 ## and m.direct = 1))
1924 if (ingres_errno) return(sms_errcode);
1926 return(SMS_NO_MATCH);
1929 ## repeat retrieve (id = m.list_id)
1930 ## where m.member_id = @lid and m.member_type = "LIST" {
1931 ancestors[acount++] = id;
1932 if (acount >= MAXLISTDEPTH)
1935 if (ingres_errno) return(sms_errcode);
1936 if (acount >= MAXLISTDEPTH)
1937 return(SMS_INTERNAL);
1938 descendants[0] = mid;
1942 if (!strcmp(mtype, "LIST")) {
1943 ## repeat retrieve (id = m.member_id, dtype = m.member_type)
1944 ## where m.list_id = @mid {
1947 dtypes[dcount] = "LIST";
1950 dtypes[dcount] = "USER";
1953 dtypes[dcount] = "STRING";
1956 dtypes[dcount] = "KERBEROS";
1962 descendants[dcount++] = id;
1963 if (dcount >= MAXLISTDEPTH)
1966 if (ingres_errno) return(sms_errcode);
1968 return(SMS_INTERNAL);
1970 for (a = 0; a < acount; a++) {
1972 for (d = 0; d < dcount; d++) {
1973 mid = descendants[d];
1975 if (mid == lid && !strcmp(mtype, "LIST")) {
1976 return(SMS_LISTLOOP);
1978 ## repeat retrieve (cnt = m.ref_count)
1979 ## where m.list_id = @lid and m.member_id = @mid
1980 ## and m.member_type = @mtype
1982 iargv[0] = (char *)lid;
1984 iargv[2] = (char *)mid;
1985 incremental_before("members", 0, iargv);
1986 ## delete m where m.list_id = lid and m.member_id = mid and
1987 ## m.member_type = mtype
1988 incremental_clear_after();
1989 } else if (a == 0 && d == 0) {
1990 ## replace m (ref_count = m.ref_count-1, direct = 0)
1991 ## where m.list_id = lid and m.member_id = mid and
1992 ## m.member_type = mtype
1994 ## replace m (ref_count = m.ref_count-1)
1995 ## where m.list_id = lid and m.member_id = mid and
1996 ## m.member_type = mtype
2000 lid = *(int *)argv[0];
2001 entity = cl->entity;
2002 who = cl->client_id;
2003 ## repeat replace list (modtime = "now", modby = @who, modwith = @entity)
2004 ## where list.#list_id = @lid
2005 if (ingres_errno) return(sms_errcode);
2006 return(SMS_SUCCESS);
2010 /* get_ace_use - given a type and a name, return a type and a name.
2011 * The ace_type is one of "LIST", "USER", "RLIST", or "RUSER" in argv[0],
2012 * and argv[1] will contain the ID of the entity in question. The R*
2013 * types mean to recursively look at every containing list, not just
2014 * when the object in question is a direct member. On return, the
2015 * usage type will be one of LIST, SERVICE, FILESYS, QUOTA, QUERY, or ZEPHYR.
2018 int get_ace_use(q, argv, cl, action, actarg)
2027 ## int aid, listid, id;
2028 struct save_queue *sq, *sq_create();
2030 ## range of m is imembers
2032 aid = *(int *)argv[1];
2033 if (!strcmp(atype, "LIST") || !strcmp(atype, "USER") ||
2034 !strcmp(atype, "KERBEROS")) {
2035 return(get_ace_internal(atype, aid, action, actarg));
2039 if (!strcmp(atype, "RLIST")) {
2040 sq_save_data(sq, aid);
2041 /* get all the list_id's of containing lists */
2042 ## range of m is imembers
2043 ## repeat retrieve (listid = m.list_id)
2044 ## where m.member_type = "LIST" and m.member_id = @id {
2045 sq_save_unique_data(sq, listid);
2047 /* now process each one */
2048 while (sq_get_data(sq, &id)) {
2049 if (get_ace_internal("LIST", id, action, actarg) == SMS_SUCCESS)
2054 if (!strcmp(atype, "RUSER")) {
2055 ## repeat retrieve (listid = m.list_id)
2056 ## where m.member_type = "USER" and m.member_id = @aid {
2057 sq_save_data(sq, listid);
2059 /* now process each one */
2060 while (sq_get_data(sq, &id)) {
2061 if (get_ace_internal("LIST", id, action, actarg) == SMS_SUCCESS)
2064 if (get_ace_internal("USER", aid, action, actarg) == SMS_SUCCESS)
2068 if (!strcmp(atype, "RKERBERO")) {
2069 ## repeat retrieve (listid = m.list_id)
2070 ## where m.member_type = "KERBEROS" and m.member_id = @aid {
2071 sq_save_data(sq, listid);
2073 /* now process each one */
2074 while (sq_get_data(sq, &id)) {
2075 if (get_ace_internal("LIST", id, action, actarg) == SMS_SUCCESS)
2078 if (get_ace_internal("KERBEROS", aid, action, actarg) == SMS_SUCCESS)
2083 if (ingres_errno) return(sms_errcode);
2084 if (!found) return(SMS_NO_MATCH);
2085 return(SMS_SUCCESS);
2089 /* This looks up a single list or user for ace use. atype must be "USER"
2090 * or "LIST", and aid is the ID of the corresponding object. This is used
2091 * by get_ace_use above.
2094 ##get_ace_internal(atype, aid, action, actarg)
2105 if (!strcmp(atype, "LIST")) {
2106 rargv[0] = "FILESYS";
2107 ## repeat retrieve (name = filesys.label)
2108 ## where filesys.owners = @aid {
2109 (*action)(2, rargv, actarg);
2114 ## repeat retrieve (name = capacls.capability)
2115 ## where capacls.list_id = @aid {
2116 (*action)(2, rargv, actarg);
2119 } else if (!strcmp(atype, "USER")) {
2120 rargv[0] = "FILESYS";
2121 ## repeat retrieve (name = filesys.label)
2122 ## where filesys.owner = @aid {
2123 (*action)(2, rargv, actarg);
2129 ## repeat retrieve (name = list.#name)
2130 ## where list.acl_type = @atype and list.acl_id = @aid {
2131 (*action)(2, rargv, actarg);
2135 rargv[0] = "SERVICE";
2136 ## repeat retrieve (name = servers.#name)
2137 ## where servers.acl_type = @atype and servers.acl_id = @aid {
2138 (*action)(2, rargv, actarg);
2142 rargv[0] = "HOSTACCESS";
2143 ## repeat retrieve (name = machine.#name)
2144 ## where machine.mach_id = hostaccess.mach_id and
2145 ## hostaccess.acl_type = @atype and hostaccess.acl_id = @aid {
2146 (*action)(2, rargv, actarg);
2149 rargv[0] = "ZEPHYR";
2150 ## repeat retrieve (name = zephyr.class)
2151 ## where zephyr.xmt_type = @atype and zephyr.xmt_id = @aid or
2152 ## zephyr.sub_type = @atype and zephyr.sub_id = @aid or
2153 ## zephyr.iws_type = @atype and zephyr.iws_id = @aid or
2154 ## zephyr.iui_type = @atype and zephyr.iui_id = @aid {
2155 (*action)(2, rargv, actarg);
2159 if (!found) return(SMS_NO_MATCH);
2160 return(SMS_SUCCESS);
2164 /* get_lists_of_member - given a type and a name, return the name and flags
2165 * of all of the lists of the given member. The member_type is one of
2166 * "LIST", "USER", "STRING", "RLIST", "RUSER", or "RSTRING" in argv[0],
2167 * and argv[1] will contain the ID of the entity in question. The R*
2168 * types mean to recursively look at every containing list, not just
2169 * when the object in question is a direct member.
2172 int get_lists_of_member(q, argv, cl, action, actarg)
2179 int found = 0, direct = 1;
2182 ## int aid, listid, id;
2183 ## char name[33], active[5], public[5], hidden[5], maillist[5], group[5];
2186 aid = *(int *)argv[1];
2187 if (!strcmp(atype, "RLIST")) {
2191 if (!strcmp(atype, "RUSER")) {
2195 if (!strcmp(atype, "RSTRING")) {
2199 if (!strcmp(atype, "RKERBEROS")) {
2208 rargv[4] = maillist;
2211 ## repeat retrieve (name = list.#name, active = text(list.#active),
2212 ## public = text(list.#public), hidden = text(list.#hidden),
2213 ## maillist = text(list.#maillist), group = text(list.#group))
2214 ## where list.list_id = m.list_id and m.direct = 1 and
2215 ## m.member_type = @atype and m.member_id = @aid {
2216 (*action)(6, rargv, actarg);
2220 ## repeat retrieve (name = list.#name, active = text(list.#active),
2221 ## public = text(list.#public), hidden = text(list.#hidden),
2222 ## maillist = text(list.#maillist), group = text(list.#group))
2223 ## where list.list_id = m.list_id and
2224 ## m.member_type = @atype and m.member_id = @aid {
2225 (*action)(6, rargv, actarg);
2230 if (ingres_errno) return(sms_errcode);
2231 if (!found) return(SMS_NO_MATCH);
2232 return(SMS_SUCCESS);
2236 /* qualified_get_lists: passed "TRUE", "FALSE", or "DONTCARE" for each of
2237 * the five flags associated with each list. It will return the name of
2238 * each list that meets the quailifications. It does this by building a
2239 * where clause based on the arguments, then doing a retrieve.
2242 static char *lflags[5] = { "active", "public", "hidden", "maillist", "group" };
2244 int qualified_get_lists(q, argv, cl, action, actarg)
2251 return(qualified_get(q, argv, action, actarg, "l.list_id != 0",
2252 "l", "name", lflags));
2256 /** get_members_of_list - optimized query for retrieval of list members
2259 ** argv[0] - list_id
2262 ** - retrieve USER members, then LIST members, then STRING members
2265 get_members_of_list(q, argv, cl, action, actarg)
2273 ## char member_name[129];
2276 list_id = *(int *)argv[0];
2278 targv[1] = member_name;
2280 ## range of m is imembers
2281 ## repeat retrieve (member_name = users.login)
2282 ## where m.#list_id = @list_id and m.member_type = "USER"
2283 ## and m.member_id = users.users_id and m.direct = 1
2284 ## sort by #member_name
2286 (*action)(2, targv, actarg);
2288 if (ingres_errno) return(sms_errcode);
2291 ## repeat retrieve (member_name = list.name)
2292 ## where m.#list_id = @list_id and m.member_type = "LIST"
2293 ## and m.member_id = list.#list_id and m.direct = 1
2294 ## sort by #member_name
2296 (*action)(2, targv, actarg);
2298 if (ingres_errno) return(sms_errcode);
2300 targv[0] = "STRING";
2301 ## repeat retrieve (member_name = strings.string)
2302 ## where m.#list_id = @list_id and m.member_type = "STRING"
2303 ## and m.member_id = strings.string_id and m.direct = 1
2304 ## sort by #member_name
2306 (*action)(2, targv, actarg);
2308 if (ingres_errno) return(sms_errcode);
2310 targv[0] = "KERBEROS";
2311 ## repeat retrieve (member_name = strings.string)
2312 ## where m.#list_id = @list_id and m.member_type = "KERBEROS"
2313 ## and m.member_id = strings.string_id and m.direct = 1
2314 ## sort by #member_name
2316 (*action)(2, targv, actarg);
2318 if (ingres_errno) return(sms_errcode);
2320 return(SMS_SUCCESS);
2324 /* count_members_of_list: this is a simple query, but it cannot be done
2325 * through the dispatch table.
2328 int count_members_of_list(q, argv, cl, action, actarg)
2335 ## int list, ct = 0;
2336 char *rargv[1], countbuf[5];
2338 list = *(int *)argv[0];
2339 rargv[0] = countbuf;
2340 ## repeat retrieve (ct = count(imembers.list_id
2341 ## where imembers.list_id = @list and
2342 ## imembers.direct = 1))
2343 if (ingres_errno) return(sms_errcode);
2344 sprintf(countbuf, "%d", ct);
2345 (*action)(1, rargv, actarg);
2346 return(SMS_SUCCESS);
2350 /* qualified_get_server: passed "TRUE", "FALSE", or "DONTCARE" for each of
2351 * the three flags associated with each service. It will return the name of
2352 * each service that meets the quailifications. It does this by building a
2353 * where clause based on the arguments, then doing a retrieve.
2356 static char *sflags[3] = { "enable", "inprogress", "harderror" };
2358 int qualified_get_server(q, argv, cl, action, actarg)
2365 return(qualified_get(q, argv, action, actarg, "s.name != \"\"",
2366 "s", "name", sflags));
2370 /* generic qualified get routine, used by qualified_get_lists,
2371 * qualified_get_server, and qualified_get_serverhost.
2373 * start - a simple where clause, must not be empty
2374 * range - the name of the range variable
2375 * field - the field to return
2376 * flags - an array of strings, names of the flag variables
2379 int qualified_get(q, argv, action, actarg, start, range, field, flags)
2389 ## char name[33], qual[256], *rvar, *rtbl, *rfield;
2390 char *rargv[1], buf[32];
2393 strcpy(qual, start);
2394 for (i = 0; i < q->argc; i++) {
2395 if (!strcmp(argv[i], "TRUE")) {
2396 sprintf(buf, " and %s.%s != 0", range, flags[i]);
2397 (void) strcat(qual, buf);
2398 } else if (!strcmp(argv[i], "FALSE")) {
2399 sprintf(buf, " and %s.%s = 0", range, flags[i]);
2400 (void) strcat(qual, buf);
2408 ## range of rvar is rtbl
2409 ## retrieve (name = rvar.rfield) where qual {
2410 (*action)(1, rargv, actarg);
2412 if (ingres_errno) return(sms_errcode);
2413 ## inquire_equel(rowcount = "rowcount")
2414 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
2415 ## where tblstats.#table = @rtbl
2417 return(SMS_NO_MATCH);
2418 return(SMS_SUCCESS);
2422 /* qualified_get_serverhost: passed "TRUE", "FALSE", or "DONTCARE" for each of
2423 * the five flags associated with each serverhost. It will return the name of
2424 * each service and host that meets the quailifications. It does this by
2425 * building a where clause based on the arguments, then doing a retrieve.
2428 static char *shflags[6] = { "service", "enable", "override", "success",
2429 "inprogress", "hosterror" };
2431 int qualified_get_serverhost(q, argv, cl, action, actarg)
2438 ## char sname[33], mname[33], qual[256];
2439 char *rargv[2], buf[32];
2442 sprintf(qual, "machine.mach_id = sh.mach_id and sh.service = uppercase(\"%s\")",
2444 for (i = 1; i < q->argc; i++) {
2445 if (!strcmp(argv[i], "TRUE")) {
2446 sprintf(buf, " and sh.%s != 0", shflags[i]);
2448 } else if (!strcmp(argv[i], "FALSE")) {
2449 sprintf(buf, " and sh.%s = 0", shflags[i]);
2456 ## range of sh is serverhosts
2457 ## retrieve (sname = sh.service, mname = machine.name) where qual {
2458 (*action)(2, rargv, actarg);
2460 if (ingres_errno) return(sms_errcode);
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 if (ingres_errno) return(sms_errcode);
2528 ## inquire_equel(rowcount = "rowcount");
2530 return(SMS_NO_POBOX);
2532 /* change login name, set pobox */
2533 sprintf(buffer, "u.users_id = %d", users_id);
2534 incremental_before("users", buffer, 0);
2535 ## repeat replace u (#login = @login, status = 2, modtime = "now",
2536 ## modby = @who, modwith = @entity, potype="POP",
2537 ## pop_id = @mid, pmodtime="now", pmodby=@who,
2538 ## pmodwith=@entity)
2539 ## where u.#users_id = @users_id
2540 ## inquire_equel(rowcount = "rowcount");
2541 if (ingres_errno) return(sms_errcode);
2543 return(SMS_INTERNAL);
2544 set_pop_usage(mid, 1);
2545 com_err(whoami, 0, "set login name to %s and pobox to %s", login,
2547 incremental_after("users", buffer, 0);
2549 /* create group list */
2550 if (set_next_object_id("gid", "list"))
2552 if (set_next_object_id("list_id", "list"))
2554 ## repeat retrieve (list_id = values.value) where values.name = "list_id"
2555 if (ingres_errno) return(sms_errcode);
2556 ## inquire_equel(rowcount = "rowcount");
2558 return(SMS_INTERNAL);
2559 incremental_clear_before();
2560 ## repeat append list (name = @login, #list_id = @list_id, active = 1,
2561 ## public = 0, hidden = 0, maillist = 0, group = 1,
2562 ## #gid = values.value, desc = "User Group",
2563 ## acl_type = "USER", acl_id = @users_id, modtime = "now",
2564 ## modby = @who, modwith = @entity)
2565 ## where values.name = "gid"
2566 if (ingres_errno) return(sms_errcode);
2567 ## inquire_equel(rowcount = "rowcount");
2569 return(SMS_INTERNAL);
2570 sprintf(buffer, "l.list_id = %d", list_id);
2571 incremental_after("list", buffer, 0);
2572 aargv[0] = (char *) list_id;
2574 aargv[2] = (char *) users_id;
2575 incremental_clear_before();
2576 ## repeat append imembers (#list_id = @list_id, member_type = "USER",
2577 ## member_id = @users_id, ref_count = 1, direct = 1)
2578 if (ingres_errno) return(sms_errcode);
2579 ## inquire_equel(rowcount = "rowcount");
2581 return(SMS_INTERNAL);
2582 incremental_after("members", 0, aargv);
2583 com_err(whoami, 0, "group list created");
2585 /* decide where to put filesystem */
2588 ## repeat retrieve (mid = n.mach_id, dir = trim(n.#dir), nid = n.nfsphys_id,
2589 ## flag = n.status, size = n.#size, alloc = n.allocated) {
2590 if ((flag & utype) && (size != 0) && (size - alloc > maxsize)) {
2591 maxsize = size - alloc;
2594 directory = strsave(dir);
2599 if (ingres_errno) return(sms_errcode);
2601 return(SMS_NO_FILESYS);
2603 /* create filesystem */
2604 if (set_next_object_id("filsys_id", "filesys"))
2606 incremental_clear_before();
2607 ## repeat append filesys (filsys_id = values.value, phys_id = @pid,
2608 ## label = @login, type = "NFS", mach_id = @m_id,
2609 ## name = @directory + "/" + @login,
2610 ## mount = "/mit/" + @login,
2611 ## access = "w", comments = "User Locker",
2612 ## owner = @users_id, owners = @list_id, createflg = 1,
2613 ## lockertype = "HOMEDIR", modtime = "now",
2614 ## modby = @who, modwith = @entity)
2615 ## where values.name = "filsys_id"
2616 if (ingres_errno) return(sms_errcode);
2617 ## inquire_equel(rowcount = "rowcount");
2619 return(SMS_INTERNAL);
2620 incremental_after("filesys",
2621 "fs.filsys_id = values.value and values.name = \"filsys_id\"",
2623 com_err(whoami, 0, "filesys created on mach %d in %s/%s", m_id,
2627 ## repeat retrieve (quota = values.value) where values.name = "def_quota"
2628 if (ingres_errno) return(sms_errcode);
2629 ## inquire_equel(rowcount = "rowcount");
2631 return(SMS_NO_QUOTA);
2632 incremental_clear_before();
2633 ## repeat append nfsquota (#users_id = @users_id, filsys_id = values.value,
2634 ## #quota = @quota, phys_id = @pid, modtime = "now",
2635 ## modby = @who, modwith = @entity)
2636 ## where values.name = "filsys_id"
2637 if (ingres_errno) return(sms_errcode);
2638 ## inquire_equel(rowcount = "rowcount");
2640 return(SMS_INTERNAL);
2641 ## repeat replace nfsphys (allocated = nfsphys.allocated + @quota)
2642 ## where nfsphys.nfsphys_id = filesys.#phys_id and
2643 ## filesys.filsys_id = values.value and values.name = "filsys_id"
2644 if (ingres_errno) return(sms_errcode);
2645 ## inquire_equel(rowcount = "rowcount");
2647 return(SMS_INTERNAL);
2650 sprintf(buffer, "nq.users_id = %d and nq.filsys_id = values.value and values.name = \"filsys_id\"", users_id);
2651 incremental_after("nfsquota", buffer, aargv);
2652 com_err(whoami, 0, "quota of %d assigned", quota);
2653 if (ingres_errno) return(sms_errcode);
2655 ## repeat replace tblstats (updates = tblstats.updates + 1, modtime = "now")
2656 ## where tblstats.table = "users"
2657 ## repeat replace tblstats (appends = tblstats.appends + 1, modtime = "now")
2658 ## where tblstats.table = "list" or tblstats.table = "filesys" or
2659 ## tblstats.table = "nfsquota"
2660 if (ingres_errno) return(sms_errcode);
2661 return(SMS_SUCCESS);
2666 /** set_pop_usage - incr/decr usage count for pop server in serverhosts talbe
2670 ** delta (will be +/- 1)
2673 ** - incr/decr value field in serverhosts table for pop/mach_id
2677 static int set_pop_usage(id, count)
2681 ## int mach_id = id;
2684 ## range of sh is serverhosts
2685 ## repeat replace sh (value1 = sh.value1 + @n)
2686 ## where sh.service = "POP" and sh.#mach_id = @mach_id
2688 if (ingres_errno) return(sms_errcode);
2689 return(SMS_SUCCESS);
2694 /* Validation Routines */
2696 validate_row(q, argv, v)
2697 register struct query *q;
2699 register struct validate *v;
2707 /* build where clause */
2708 build_qual(v->qual, v->argc, argv, qual);
2710 /* setup ingres variables */
2715 if (log_flags & LOG_VALID)
2716 /* tell the logfile what we're doing */
2717 com_err(whoami, 0, "validating row: %s", qual);
2719 /* look for the record */
2720 ## range of rvar is table
2721 ## retrieve (rowcount = count(rvar.name where qual))
2722 if (ingres_errno) return(sms_errcode);
2723 if (rowcount == 0) return(SMS_NO_MATCH);
2724 if (rowcount > 1) return(SMS_NOT_UNIQUE);
2728 validate_fields(q, argv, vo, n)
2730 register char *argv[];
2731 register struct valobj *vo;
2734 register int status;
2739 if (log_flags & LOG_VALID)
2740 com_err(whoami, 0, "validating %s in %s: %s",
2741 vo->namefield, vo->table, argv[vo->index]);
2742 status = validate_name(argv, vo);
2746 if (log_flags & LOG_VALID)
2747 com_err(whoami, 0, "validating %s in %s: %s",
2748 vo->idfield, vo->table, argv[vo->index]);
2749 status = validate_id(argv, vo);
2753 if (log_flags & LOG_VALID)
2754 com_err(whoami, 0, "validating date: %s", argv[vo->index]);
2755 status = validate_date(argv, vo);
2759 if (log_flags & LOG_VALID)
2760 com_err(whoami, 0, "validating %s type: %s",
2761 vo->table, argv[vo->index]);
2762 status = validate_type(argv, vo);
2766 if (log_flags & LOG_VALID)
2767 com_err(whoami, 0, "validating typed data (%s): %s",
2768 argv[vo->index - 1], argv[vo->index]);
2769 status = validate_typedata(q, argv, vo);
2773 if (log_flags & LOG_VALID)
2774 com_err(whoami, 0, "validating rename %s in %s",
2775 argv[vo->index], vo->table);
2776 status = validate_rename(argv, vo);
2780 if (log_flags & LOG_VALID)
2781 com_err(whoami, 0, "validating chars: %s", argv[vo->index]);
2782 status = validate_chars(argv[vo->index]);
2786 status = SMS_EXISTS;
2790 status = lock_table(vo);
2794 if (status != SMS_EXISTS) return(status);
2798 if (ingres_errno) return(sms_errcode);
2799 return(SMS_SUCCESS);
2803 /* validate_chars: verify that there are no illegal characters in
2804 * the string. Legal characters are printing chars other than
2805 * ", *, ?, \, [ and ].
2807 static int illegalchars[] = {
2808 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
2809 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
2810 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
2811 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
2812 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ - O */
2813 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* P - _ */
2814 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
2815 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
2816 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2817 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2818 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2819 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2820 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2821 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2822 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2823 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2830 if (illegalchars[*s++])
2831 return(SMS_BAD_CHAR);
2836 validate_id(argv, vo)
2838 register struct valobj *vo;
2848 name = argv[vo->index];
2850 /* minor kludge to upcasify machine names */
2851 if (!strcmp(table, "machine"))
2852 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
2853 namefield = vo->namefield;
2854 idfield = vo->idfield;
2855 if (!strcmp(namefield, "uid")) {
2856 ## retrieve (id = table.idfield) where table.namefield = int4(name)
2857 if (ingres_errno) return(sms_errcode);
2858 ## inquire_equel (rowcount = "rowcount")
2860 ## retrieve (id = table.idfield) where table.namefield = name
2861 if (ingres_errno) return(sms_errcode);
2862 ## inquire_equel (rowcount = "rowcount")
2864 if (rowcount != 1) return(vo->error);
2865 *(int *)argv[vo->index] = id;
2869 validate_name(argv, vo)
2871 register struct valobj *vo;
2879 name = argv[vo->index];
2881 namefield = vo->namefield;
2882 if (!strcmp(table, "servers") && !strcmp(namefield, "name")) {
2883 for (c = name; *c; c++)
2887 ## retrieve (rowcount = countu(table.namefield
2888 ## where table.namefield = name))
2889 if (ingres_errno) return(sms_errcode);
2890 return ((rowcount == 1) ? SMS_EXISTS : vo->error);
2893 validate_date(argv, vo)
2901 idate = argv[vo->index];
2903 ## retrieve (dd = interval("years", date(idate) - date("today")))
2904 ## inquire_equel (errorno = "errorno")
2905 if (errorno != 0 || dd > 5.0) return(SMS_DATE);
2910 validate_rename(argv, vo)
2914 ## char *name, *table, *namefield, *idfield;
2918 c = name = argv[vo->index];
2920 if (illegalchars[*c++])
2921 return(SMS_BAD_CHAR);
2923 /* minor kludge to upcasify machine names */
2924 if (!strcmp(table, "machine"))
2925 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
2926 namefield = vo->namefield;
2927 idfield = vo->idfield;
2930 if (!strcmp(argv[vo->index], argv[vo->index - 1]))
2932 ## retrieve (id = any(table.namefield where table.namefield = name))
2933 if (ingres_errno) return(sms_errcode);
2939 ## retrieve (id = table.idfield) where table.namefield = name
2940 if (ingres_errno) return(sms_errcode);
2941 if (id == -1 || id == *(int *)argv[vo->index - 1])
2948 validate_type(argv, vo)
2950 register struct valobj *vo;
2957 typename = vo->table;
2958 c = value = argv[vo->index];
2960 if (illegalchars[*c++])
2961 return(SMS_BAD_CHAR);
2963 /* uppercase type fields */
2964 for (c = value; *c; c++) if (islower(*c)) *c = toupper(*c);
2966 ## range of a is alias
2967 ## repeat retrieve (exists = any(a.trans where a.name = @typename and
2968 ## a.type = "TYPE" and
2969 ## a.trans = @value))
2970 if (ingres_errno) return(sms_errcode);
2971 return (exists ? SMS_EXISTS : vo->error);
2974 /* validate member or type-specific data field */
2976 validate_typedata(q, argv, vo)
2977 register struct query *q;
2978 register char *argv[];
2979 register struct valobj *vo;
2982 ## char *field_type;
2983 ## char data_type[129];
2989 /* get named object */
2990 name = argv[vo->index];
2992 /* get field type string (known to be at index-1) */
2993 field_type = argv[vo->index-1];
2995 /* get corresponding data type associated with field type name */
2996 ## repeat retrieve (data_type = alias.trans)
2997 ## where alias.#name = @field_type and alias.type = "TYPEDATA"
2998 if (ingres_errno) return(sms_errcode);
2999 ## inquire_equel (rowcount = "rowcount")
3000 if (rowcount != 1) return(SMS_TYPE);
3002 /* now retrieve the record id corresponding to the named object */
3003 if (index(data_type, ' '))
3004 *index(data_type, ' ') = 0;
3005 if (!strcmp(data_type, "user")) {
3007 ## repeat retrieve (id = users.users_id) where users.login = @name
3008 ## inquire_equel (rowcount = "rowcount")
3009 if (rowcount != 1) return(SMS_USER);
3011 } else if (!strcmp(data_type, "list")) {
3013 ## repeat retrieve (id = list.list_id) where list.#name = @name
3014 ## inquire_equel (rowcount = "rowcount")
3015 if (rowcount != 1) {
3016 /* if idfield is non-zero, then if argv[0] matches the string
3017 * that we're trying to resolve, we should get the value of
3018 * values.[idfield] for the id.
3020 if (vo->idfield && !strcmp(argv[0], argv[vo->index])) {
3021 set_next_object_id(q->validate->object_id, q->rtable);
3023 ## repeat retrieve (id = values.value) where values.#name = @name
3024 ## inquire_equel(rowcount = "rowcount")
3025 if (rowcount != 1) return(SMS_LIST);
3029 } else if (!strcmp(data_type, "machine")) {
3031 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3032 ## repeat retrieve (id = machine.mach_id) where machine.#name = @name
3033 ## inquire_equel (rowcount = "rowcount")
3034 if (rowcount != 1) return(SMS_MACHINE);
3036 } else if (!strcmp(data_type, "string")) {
3038 ## range of s is strings
3039 ## repeat retrieve (id = s.string_id) where s.string = @name
3040 ## inquire_equel (rowcount = "rowcount")
3041 if (rowcount == 0) {
3042 if (q->type != APPEND) return(SMS_STRING);
3043 ## range of v is values
3044 ## retrieve (id = v.value) where v.#name = "strings_id"
3046 ## replace v (value = id) where v.#name = "strings_id"
3047 ## append to strings (string_id = id, string = name)
3049 } else if (!strcmp(data_type, "none")) {
3055 /* now set value in argv */
3056 *(int *)argv[vo->index] = id;
3058 return (SMS_EXISTS);
3062 /* Lock the table named by the validation object */
3067 ## char *table, *idfield;
3071 idfield = vo->idfield;
3072 ## replace table (modtime = "now") where table.idfield = 0
3073 if (ingres_errno) return(sms_errcode);
3074 ## inquire_equel (rowcount = "rowcount")
3082 /* Check the database at startup time. For now this just resets the
3083 * inprogress flags that the DCM uses.
3086 sanity_check_database()