6 * Copyright (C) 1987 by the Massachusetts Institute of Technology
9 * Revision 1.14 1987-09-04 17:50:03 mike
10 * Renamed delete_list_members to followup_delete_list. New routine removes
11 * list from maillists and groups tables in addition to the members table.
13 * Added routines validate_label and validate_label_2 used in validating
14 * filesys labels for get_filesys and delete_filesys respectively.
16 Revision 1.13 87/09/01 16:24:01 wesommer
17 A list should be considered modified if its acl changes.
19 Revision 1.12 87/08/29 00:05:54 mike
20 Fixed bug in check_nfs.
21 Added code to upcasify machine names in validate_id.
23 Revision 1.11 87/08/28 14:55:45 mike
24 Modified delete_locker to require only one argument, the login name.
25 Modified get_groups_of_all_users and get_all_poboxes to disable INGRES
28 Revision 1.10 87/08/25 15:56:54 mike
29 - Fixed bugs in get_groups_of_all_users
30 - Added tblstats updates to add_user_group
31 - Added routines: add_hostaccess (ashi), delete_hostaccess (dshi),
32 followup_ushp, and followup_usha
34 Revision 1.9 87/08/22 17:41:34 wesommer
35 More of Mike's changes.
37 Revision 1.8 87/08/18 15:05:20 wesommer
38 Fixed definition of add_locker.
40 Revision 1.7 87/08/04 01:49:41 wesommer
43 Revision 1.6 87/08/04 01:10:02 wesommer
44 Changes by mike; checked in prior to my hacking.
46 Revision 1.5 87/07/30 14:54:13 wesommer
47 Added debugging code in an attempt to catch a flakey problem.
49 Revision 1.4 87/07/30 00:30:21 wesommer
50 replaced appends = appends+1 with appends = tbs.appends+1
52 Revision 1.3 87/07/30 00:26:11 wesommer
53 Changes by mike prior to "appends" fix.
55 Revision 1.2 87/07/29 16:00:39 wesommer
58 Revision 1.1 87/07/29 15:13:57 wesommer
64 static char *rcsid_qsupport_qc = "$Header$";
68 #include "sms_server.h"
75 /* Specialized Access Routines */
78 ** access_user - verify that client name equals specified login name
80 ** Used by: update_user_shell
81 ** update_finger_by_login
83 ** - since field validation routines are called first, a users_id is
84 ** now in argv[0] instead of the login name. Therefore, we must
85 ** convert the client name to a users_id.
88 access_user(q, argv, cl)
93 register struct krbname *krb;
98 client_name = cl->kname.name;
99 ## repeat retrieve (client_id = users.users_id)
100 ## where users.login = @client_name
101 ## inquire_equel (rowcount = "rowcount")
102 if (rowcount != 1) return(SMS_PERM);
103 if (client_id != *(int *)argv[0]) return(SMS_PERM);
109 ** access_pop - same as access_user plus verifies that a user has only one
110 ** mailbox of type "POP"
113 ** argv[0] - users_id
119 ** - if q->name = "add_pobox" and type = "POP",
120 ** verify that no POP box already exists for user
121 ** - call access_user
125 access_pop(q, argv, cl)
135 if (!bcmp(q->name, "add_pobox", 10) && !bcmp(argv[1], "POP", 4)) {
136 users_id = *(int *)argv[0];
137 mach_id = *(int *)argv[2];
139 ## range of p is pobox
140 ## repeat retrieve (exists = any(p.#box where p.#users_id = @users_id
141 ## and p.type = "POP"
142 ## and p.#mach_id = @mach_id
143 ## and p.#box = @box))
144 if (exists) return(SMS_EXISTS);
147 return(access_user(q, argv, cl));
151 ** access_list - check access for adding or deleting list members
153 ** Inputs: argv[0] - list_id
154 ** cl->krb.name - client name
156 ** - check that client is a member of the access control list
157 ** - OR, if q->shortname == {amtl | dfml} and
158 ** if list.flags & LF_PUBLIC, allow access if client = member
162 access_list(q, argv, cl)
176 list_id = *(int *)argv[0];
177 ## repeat retrieve (acl_id = list.#acl_id, flags = list.#flags)
178 ## where list.#list_id = @list_id
180 /* parse client structure */
181 status = get_client(cl, &client_type, &client_id);
182 if (status != SMS_SUCCESS) return(status);
184 /* if amtl or dmfl and list is public allow client to add or delete self */
185 if (!bcmp("amtl", q->shortname, 4) || !bcmp("dmfl", q->shortname, 4)) {
186 if ((flags & LF_PUBLIC) && !bcmp("USER", argv[1], 4)) {
187 member_id = *(int *)argv[2];
188 if (member_id == client_id) return(SMS_SUCCESS);
192 /* check for client in access control list */
193 exists = find_member(acl_id, client_type, client_id, 0);
194 if (!exists) return(SMS_PERM);
200 ** access_maillist - access_list + disallow adding user-group to maillists
207 access_maillist(q, argv, cl)
214 ## char list_name[32];
217 status = access_list(q, argv, cl);
218 if (status != SMS_SUCCESS) return(status);
219 if (bcmp(q->name, "add_maillist", 12)) return(status);
221 list_id = *(int *)argv[0];
222 ## range of g is groups
223 ## repeat retrieve (exists = any(g.#list_id where g.#list_id = @list_id))
224 if (!exists) return(SMS_SUCCESS);
225 ## repeat retrieve (list_name = list.name) where list.#list_id = @list_id
226 ## repeat retrieve (exists = any(users.login where users.login = @list_name))
227 return ((exists) ? SMS_USER_GROUP : SMS_SUCCESS);
231 ** Setup routine for add_group
235 ** Description: allocate next gid and store in values table
239 setup_add_group(q, argv, cl, access_check)
249 status = access_list(q, argv, cl);
251 if (status != SMS_SUCCESS || access_check) return(status);
253 ## range of g is groups
254 ## range of v is values
255 ## repeat retrieve (ngid = v.value) where v.name = "gid"
259 ## repeat retrieve (exists = any(g.#gid where g.#gid = @ngid))
262 ## repeat replace v (value = @ngid) where v.name = "gid"
267 ** Setup routine for add_user
269 ** Inputs: argv[0] - login
274 ** - if argv[1] == "#" then set argv[1] = next(uid)
275 ** - if argv[0] == "#" then set argv[0] = "#<uid>"
279 setup_add_user(q, argv, cl, access_check)
281 register char *argv[];
288 if (access_check) return(SMS_SUCCESS);
290 if (!bcmp(argv[1], "#", 2)) {
291 ## range of u is users
292 ## range of v is values
293 ## repeat retrieve (nuid = v.value) where v.name = "uid"
297 ## repeat retrieve (exists = any(u.#uid where u.#uid = @nuid))
299 ## repeat replace v (value = @nuid) where v.name = "uid"
300 sprintf(argv[1], "%d", nuid);
303 if (!bcmp(argv[0], "#", 2)) {
304 sprintf(argv[0], "#%s", argv[1]);
311 ** followup_add_user - add finger entry, set_user_modtime
312 ** followup_delete_user - delete finger entry
315 ** argv[0] - login (add_user)
316 ** argv[0] - users_id (delete_user)
320 followup_add_user(q, argv)
329 ## char fullname[128];
335 /* get user information */
336 ## range of u is users
337 ## repeat retrieve (users_id = u.#users_id, last = u.#last,
338 ## first = u.#first, middle = u.#middle)
339 ## where u.#login = @login
344 while (*cp1) *cp2++ = *cp1++;
347 if (*cp1 == 0) cp2--;
348 while (*cp1) *cp2++ = *cp1++;
351 while (*cp2++ = *cp1++) ;
353 /* create a finger entry */
354 ## repeat append finger (#users_id = @users_id, #fullname = @fullname)
356 /* set modtime (creation time) on user */
357 ## repeat replace u (modtime = "now") where u.#users_id = @users_id
362 followup_delete_user(q, argv)
368 users_id = *(int *)argv[0];
369 ## repeat delete finger where finger.#users_id = @users_id
374 ** setup_add_filesys - verify existance of referenced file systems
375 ** setup_update_filesys - same, except argv[1..5] --> argv[2..6]
377 ** Inputs: Add Update
378 ** argv[0] - label label
379 ** argv[1] - type new label
380 ** argv[2] - mach_id type
381 ** argv[3] - name mach_id
382 ** argv[4] - mount name
383 ** argv[5] - access mount
388 ** * verify mach_id/name in rvdvirt
389 ** * verify access in {r, x, R, X}
391 ** * extract directory prefix from name
392 ** * verify mach_id/dir in nfsphys
393 ** * verify access in {r, w, R, W}
396 ** SMS_RVD - no such rvd
397 ** SMS_NFS - specified directory not exported
398 ** SMS_FILESYS_ACCESS - invalid filesys access
402 setup_add_filesys(q, argv)
412 mach_id = *(int *)argv[2];
416 if (!bcmp(type, "RVD", 3))
417 return (check_rvd(mach_id, name, access));
418 else if (!bcmp(type, "NFS", 3))
419 return (check_nfs(mach_id, name, access));
424 setup_update_filesys(q, argv)
434 mach_id = *(int *)argv[3];
438 if (!bcmp(type, "RVD", 3))
439 return (check_rvd(mach_id, name, access));
440 else if (!bcmp(type, "NFS", 3))
441 return (check_nfs(mach_id, name, access));
446 ##check_rvd(mach_id, name, access)
454 ## range of rv is rvdvirt
455 ## retrieve (rowcount = any(rv.#name where rv.#mach_id = mach_id and
457 if (rowcount == 0) return(SMS_RVD);
459 caccess = (isupper(*access)) ? tolower(*access) : *access;
460 if (caccess != 'r' && caccess != 'x') return(SMS_FILESYS_ACCESS);
465 ##check_nfs(mach_id, name, access)
477 caccess = (isupper(*access)) ? tolower(*access) : *access;
478 if (caccess != 'r' && caccess != 'w') return(SMS_FILESYS_ACCESS);
481 ## range of np is nfsphys
482 ## retrieve (dir = np.#dir) where np.#mach_id = mach_id
487 if (*cp1++ != *cp2) break;
491 status = SMS_SUCCESS;
499 /* Followup Routines */
501 set_user_modtime(q, argv)
508 ## repeat replace u (modtime = "now") where u.#login = @login
512 set_user_modtime_by_id(q, argv)
518 users_id = *(int *)argv[0];
519 ## repeat replace users (modtime = "now") where users.#users_id = @users_id
523 set_list_modtime(q, argv)
530 ## repeat replace list (modtime = "now") where list.name = @list_name
534 set_list_modtime_by_id(q, argv)
540 list_id = *(int *)argv[0];
541 ## repeat replace list (modtime = "now") where list.#list_id = @list_id
542 ## repeat replace list (modtime = "now") where list.#acl_id = @list_id
546 set_finger_modtime(q, argv)
552 users_id = *(int *)argv[0];
553 ## repeat replace f (modtime = "now") where f.#users_id = @users_id
558 ** followup_amtl - followup for amtl and dmfl; when adding a list
559 ** member to a maillist, add list to maillist table,
560 ** unless list is a user-group.
561 ** Then set_list_modtime_by_id.
565 ** argv[1] - member_type
566 ** argv[2] - member_id
570 followup_amtl(q, argv)
577 ## char list_name[33];
579 list_id = *(int *)argv[0];
581 ## repeat replace list (modtime = "now") where list.#list_id = @list_id
582 ## repeat replace list (modtime = "now") where list.#acl_id = @list_id
584 /* if query is not amtl or if member_type is not LIST then return */
585 if (bcmp(q->shortname, "amtl", 4) || bcmp(argv[1], "LIST", 4))
588 member_id = *(int *)argv[2];
589 ## range of l is list
590 ## range of ml is maillists
591 ## range of g is groups
593 /* is parent list a mailing list? */
594 ## repeat retrieve (exists = any(ml.#list_id where ml.#list_id=@list_id))
596 /* if not then return */
597 if (!exists) return(SMS_SUCCESS);
599 /* is member_list a user-group? */
601 ## repeat retrieve (exists = any(g.#list_id where g.#list_id = @member_id))
604 ## repeat retrieve (list_name = l.#name) where l.#list_id = @member_id
605 /* is list_name a username? */
606 ## repeat retrieve (exists = any(users.login
607 ## where users.login = @list_name))
608 /* yes, return error */
609 if (exists) return(SMS_USER_GROUP);
612 /* list is not a user-group; add list to maillist table */
613 ## repeat append maillists (#list_id = @member_id, ltid = l.tid)
614 ## where l.#list_id = @member_id
620 ** followup_add_pobox
621 ** followup_delete_pobox - followup routines for pobox queries
624 ** add_pobox: set pobox creation time
625 ** increment pop usage in serverhosts
627 ** delete_pobox: decrement pop usage in serverhosts
631 followup_add_pobox(q, argv)
635 set_pobox_creation(q, argv);
636 set_pop_usage(q, argv, 1);
640 followup_delete_pobox(q, argv)
644 set_pop_usage(q, argv, -1);
648 set_pobox_creation(q, argv)
657 users_id = *(int *)argv[0];
659 mach_id = *(int *)argv[2];
662 ## range of p is pobox
663 ## repeat replace p (created = "now")
664 ## where p.#users_id = @users_id and p.#type = @type and
665 ## p.#mach_id = @mach_id and p.#box = @box
667 return (SMS_SUCCESS);
671 ** set_pop_usage - incr/decr usage count for pop server in serverhosts talbe
674 ** q->name - "add_pobox" or "delete_pobox"
679 ** - incr/decr value field in serverhosts table for pop/mach_id
683 set_pop_usage(q, argv, count)
690 if (bcmp(argv[1], "POP", 3)) return(SMS_SUCCESS);
692 mach_id = *(int *)argv[2];
695 ## range of sh is serverhosts
696 ## repeat replace sh (value1 = sh.value1 + @n)
697 ## where sh.service = "pop" and sh.#mach_id = @mach_id
703 ** delete_user_poboxes - delete all poboxes for a user
706 ** argv[0] - users_id
710 delete_user_poboxes(q, argv)
720 users_id = *(int *)argv[0];
722 /* get machine ids for pop server(s) on which the user currently exists */
723 ## range of p is pobox
725 ## repeat retrieve (mach_id = p.#mach_id)
726 ## where p.#users_id = @users_id and p.type = "POP"
728 mach_ids[i++] = mach_id;
734 /* decrement counts on serverhost entries */
735 ## range of sh is serverhosts
737 mach_id = mach_ids[i];
738 ## repeat replace sh (value1 = sh.value1 - 1)
739 ## where sh.service = "pop" and sh.#mach_id = @mach_id
742 /* delete user's poboxes */
743 ## repeat delete p where p.#users_id = @users_id
751 ** delete_current_quota - adjust nfsphys values on xxx_quota queries.
756 ** argv[2] - users_id
757 ** argv[3] - quota (add_new_quota only)
760 ** delete_current_quota:
761 ** - find nfsquota entry
762 ** - decrement nfsphys.allocated by nfsquota.quota
764 ** - increment nfsphys.allocated by quota
768 add_new_quota(q, argv)
770 register char *argv[];
776 mach_id = *(int*)argv[0];
778 quota = *(int *)argv[3];
780 ## range of np is nfsphys
781 ## repeat replace np (allocated = np.allocated + @quota)
782 ## where np.#mach_id = @mach_id and np.#device = @device
787 delete_current_quota(q, argv, cl, access_check)
789 register char *argv[];
798 if (access_check) return(SMS_SUCCESS);
800 mach_id = *(int *)argv[0];
802 users_id = *(int *)argv[2];
804 ## range of np is nfsphys
805 ## range of nq is nfsquota
806 ## repeat retrieve (quota = nq.#quota)
807 ## where nq.#mach_id = @mach_id and nq.#device = @device and
808 ## nq.#users_id = @users_id
809 ## repeat replace np (allocated = np.allocated - @quota)
810 ## where np.#mach_id = @mach_id and np.#device = @device
816 ** add_hostaccess - create entry in hostaccess table upon adding a new
817 ** machine to the serverhosts table where service =
826 add_hostaccess(q, argv)
832 /* only work with service = "hostaccess" */
833 if (bcmp(argv[0], "hostaccess", 10)) return(SMS_SUCCESS);
835 mach_id = *(int *)argv[1];
836 ## repeat append hostaccess (#mach_id = @mach_id, status = 0)
837 ## repeat replace tblstats (modtime = "now", appends = tblstats.appends + 1)
838 ## where tblstats.table = "hostaccess"
842 /* followup to delete_server_host_info */
844 delete_hostaccess(q, argv)
850 /* only work with service = "hostaccess" */
851 if (bcmp(argv[0], "hostaccess", 10)) return(SMS_SUCCESS);
853 mach_id = *(int *)argv[1];
854 ## repeat delete hostaccess where hostaccess.#mach_id = @mach_id
855 ## repeat replace tblstats (modtime = "now", deletes = tblstats.deletes + 1)
856 ## where tblstats.table = "hostaccess"
860 followup_ushp(q, argv)
867 mach_id = *(int *)argv[0];
868 ## range of ha is hostaccess
869 ## repeat retrieve (status = ha.#status) where ha.#mach_id = @mach_id
871 ## repeat replace ha (#status = @status) where ha.#mach_id = @mach_id
875 followup_usha(q, argv)
882 mach_id = *(int *)argv[0];
883 ## range of ha is hostaccess
884 ## repeat retrieve (status = ha.#status) where ha.#mach_id = @mach_id
886 ## repeat replace ha (#status = @status) where ha.#mach_id = @mach_id
891 ** followup_delete_list - called after the delete_list query to clean up
892 ** members table; also deletes list from maillist
893 ** and groups tables.
895 ** Inputs: argv[0] - list_id
898 ** - foreach string member: decr string refc; ifzero, delete string
899 ** - delete all members entries for this list_id
903 followup_delete_list(q, argv)
905 register char *argv[];
911 struct save_queue *sq;
912 struct save_queue *sq_create();
914 list_id = *(int *)argv[0];
917 ## range of m is members
918 ## repeat retrieve (string_id = m.member_id)
919 ## where m.#list_id = @list_id and m.member_type = "STRING"
921 sq_save_data(sq, string_id);
924 while (sq_get_data(sq, &string_id)) {
925 ## range of s is strings
926 ## repeat retrieve (refc = s.#refc) where s.#string_id = @string_id
927 ## inquire_equel (rowcount = "rowcount")
928 if (rowcount == 0) continue;
930 ## repeat delete s where s.#string_id = @string_id
932 ## repeat replace s (#refc = @refc) where s.#string_id = @string_id
937 ## repeat delete m where m.#list_id = @list_id
938 ## repeat delete maillists where maillists.#list_id = @list_id
939 ## repeat delete groups where groups.#list_id = @list_id
945 ** followup_grvd - Support routine for get_rvd_servers query
948 ** q - grvd query structure
949 ** sq - save_queue struture: contains list of {machine, oper_acl_id,
950 ** admin_acl_id, shutdown_acl_id} records.
951 ** v - validate structure (not used)
952 ** action - action routine
953 ** actarg - action routine argument
956 ** - translate acl_ids to list names
960 followup_grvd(q, sq, v, action, actarg)
962 struct save_queue *sq;
971 ## char shutdown[33];
978 ## range of l is list
980 while (sq_get_data(sq, &argv)) {
981 sscanf(argv[0], "%d", &list_id);
982 ## repeat retrieve (oper = l.name) where l.#list_id = @list_id
983 sscanf(argv[1], "%d", &list_id);
984 ## repeat retrieve (admin = l.name) where l.#list_id = @list_id
985 sscanf(argv[2], "%d", &list_id);
986 ## repeat retrieve (shutdown = l.name) where l.#list_id = @list_id
988 (*action)(3, targv, actarg);
998 followup_gars(q, sq, v, action, actarg)
1000 struct save_queue *sq;
1009 ## char shutdown[33];
1014 targv[3] = shutdown;
1016 ## range of l is list
1018 while (sq_get_data(sq, &argv)) {
1019 sscanf(argv[1], "%d", &list_id);
1020 ## repeat retrieve (oper = l.name) where l.#list_id = @list_id
1021 sscanf(argv[2], "%d", &list_id);
1022 ## repeat retrieve (admin = l.name) where l.#list_id = @list_id
1023 sscanf(argv[3], "%d", &list_id);
1024 ## repeat retrieve (shutdown = l.name) where l.#list_id = @list_id
1027 (*action)(4, targv, actarg);
1035 return(SMS_SUCCESS);
1039 ** set_next_object_id - set next object id in values table
1041 ** Inputs: object - object name in values table
1043 ** - called before an APPEND operation to set the next object id to
1044 ** be used for the new record
1048 set_next_object_id(object)
1054 ## range of v is values
1055 ## repeat replace v (value = v.value + 1) where v.#name = @name
1056 return(SMS_SUCCESS);
1060 ** get_query_need - check modtime of query's associated table against given
1061 ** time and return true if greater (false if not)
1064 ** argv[0] - query name
1065 ** argv[1] - time to compare against
1069 get_query_need(q, argv, action, actarg)
1071 register char *argv[];
1075 ## char *last_get_time;
1079 struct query *get_query_by_name();
1081 q1 = get_query_by_name(argv[0]);
1083 last_get_time = argv[1];
1086 if (q1->type != RETRIEVE) return(SMS_NO_MATCH);
1088 ## range of tbs is tblstats
1089 ## repeat retrieve (need = any(tbs.modtime where tbs.#table = @table and
1090 ## tbs.modtime > @last_get_time))
1092 result = (need) ? "true" : "false";
1093 (*action)(1, &result, actarg);
1094 return(SMS_SUCCESS);
1098 ** get_list_is_group
1099 ** get_list_is_maillist
1102 ** argv[0] - list_id
1109 get_list_is_group(q, argv, action, actarg)
1119 list_id = *(int *)argv[0];
1121 ## range of g is groups
1122 ## repeat retrieve (exists = any(g.#list_id where g.#list_id = @list_id))
1124 result = (exists) ? "true" : "false";
1125 (*action)(1, &result, actarg);
1126 return(SMS_SUCCESS);
1129 get_list_is_maillist(q, argv, action, actarg)
1139 list_id = *(int *)argv[0];
1141 ## range of ml is maillists
1142 ## repeat retrieve (exists = any(ml.#list_id where ml.#list_id = @list_id))
1144 result = (exists) ? "true" : "false";
1145 (*action)(1, &result, actarg);
1146 return(SMS_SUCCESS);
1151 ** add_locker - special query routine for creating a user locker
1154 ** argv[0] - users_id
1155 ** argv[1] - machine_id
1157 ** argv[3] - initial quota
1160 ** - get prefix directory (dir) for mount point on specified machine/device
1161 ** - create filesys entry (label=<login>, type=NFS, machine=<machine>,
1162 ** mount=<dir>/<login>, access=w, acl=dbadmin)
1163 ** - increment allocated in nfsphys by quota
1164 ** - create nfsquota entry
1167 ** - SMS_NFSPHYS - machine/device does not exist in nfsphys
1168 ** - SMS_FILESYS_EXISTS - file system already exists
1173 register struct query *q;
1188 /* copy arguments */
1189 users_id = *(int *)argv[0];
1190 mach_id = *(int *)argv[1];
1192 sscanf(argv[3], "%d", "a);
1194 ## range of u is users
1195 ## range of f is filesys
1196 ## range of np is nfsphys
1197 ## range of tbs is tblstats
1199 /* get login name */
1200 ## repeat retrieve (login = u.#login) where u.#users_id = @users_id
1202 /* get user's acl id */
1203 ## repeat retrieve (user_acl = list.list_id) where list.name = @login
1205 /* get filesystem directory prefix; give error if machine/device
1206 pair not in nfsphys table */
1207 printf("np.mach_id = %d and np.device = %s\n", mach_id, device);
1209 ## repeat retrieve (dir = np.#dir, allocated = np.#allocated)
1210 ## where np.#mach_id = @mach_id and np.#device = @device
1211 ## inquire_equel (rowcount = "rowcount")
1212 if (rowcount == 0) return(SMS_NFSPHYS);
1214 /* make sure a filesys with user's name does not already exist */
1215 ## repeat retrieve (rowcount = any(f.label where f.label = @login))
1216 if (rowcount != 0) return(SMS_FILESYS_EXISTS);
1218 /* create a new filesys */
1219 sprintf(locker, "%s/%s", dir, login);
1220 sprintf(mount, "/mit/%s", login);
1221 ## repeat append filesys
1222 ## (#label = @login, type = "NFS", #mach_id = @mach_id,
1223 ## name = @locker, access = "w", order = 1, #mount = @mount,
1224 ## acl_id = @user_acl)
1225 ## repeat replace tbs (appends = tbs.appends + 1, modtime = "now")
1226 ## where tbs.table = "filesys"
1228 /* increment usage count in nfsphys table */
1230 ## replace np (#allocated = allocated)
1231 ## where np.#mach_id = mach_id and np.#device = device
1232 ## repeat replace tbs (updates = tbs.updates + 1, modtime = "now")
1233 ## where tbs.table = "nfsphys"
1235 /* create nfsquota entry */
1236 ## append nfsquota (#users_id = users_id, #mach_id = mach_id,
1237 ## #device = device, #quota = quota)
1238 ## repeat replace tbs (appends = tbs.appends + 1, modtime = "now")
1239 ## where tbs.table = "nfsquota"
1241 return(SMS_SUCCESS);
1245 ** delete_locker - special query routine for deleting a user locker
1248 ** argv[0] - users_id
1251 ** - get login name from users_id
1252 ** - get filesys entry from login
1253 ** - use filesys.mach_id and filesys.name to determine machine/device
1254 ** pair for nfsphys and nfsquota
1255 ** - delete filesys entry (label=<login>)
1256 ** - decrement allocated in nfsphys by quota
1257 ** - delete nfsquota entry
1260 ** - SMS_FILESYS - no filesys exists for user
1264 delete_locker(q, argv)
1265 register struct query *q;
1266 register char *argv[];
1277 /* copy arguments */
1278 users_id = *(int *)argv[0];
1280 ## range of u is users
1281 ## range of f is filesys
1282 ## range of np is nfsphys
1283 ## range of nq is nfsquota
1284 ## range of tbs is tblstats
1286 /* get login name */
1287 ## repeat retrieve (login = u.#login) where u.#users_id = @users_id
1289 /* get mach_id and locker name from filesys entry; then delete it */
1290 ## repeat retrieve (mach_id = f.#mach_id, lname = f.#name)
1291 ## where f.#label = @login
1292 ## inquire_equel (rowcount = "rowcount")
1293 if (rowcount == 0) return(SMS_FILESYS);
1294 ## repeat delete f where f.#label = @login
1296 /* get prefix directory */
1297 c = (char *)rindex(lname, '/');
1300 /* get nfs device */
1301 ## repeat retrieve (ndev = np.device)
1302 ## where np.#mach_id = @mach_id and np.dir = @lname
1304 /* get quota from nfsquota entry; then delete entry */
1305 ## repeat retrieve (quota = nq.#quota)
1306 ## where nq.#mach_id = @mach_id and nq.#device = @ndev and
1307 ## nq.#users_id = @users_id
1308 ## repeat delete nq where nq.#mach_id = @mach_id and nq.#device = @ndev and
1309 ## nq.#users_id = @users_id
1311 /* decrement nfsphys.allocated */
1312 ## repeat replace np (allocated = np.allocated - @quota)
1313 ## where np.#mach_id = @mach_id and np.#device = @ndev
1315 /* adjust table statistics */
1316 ## repeat replace tbs (deletes = tbs.deletes + 1, modtime = "now")
1317 ## where tbs.table = "filesys"
1318 ## repeat replace tbs (updates = tbs.updates + 1, modtime = "now")
1319 ## where tbs.table = "nfsphys"
1320 ## repeat replace tbs (deletes = tbs.deletes + 1, modtime = "now")
1321 ## where tbs.table = "nfsquota"
1323 return(SMS_SUCCESS);
1327 ** add_user_group - create a group for a user and add user to group
1333 ** - verify specified user exists
1334 ** - create a list of same name as user
1335 ** - add user as a member of the list
1339 add_user_group(q, argv)
1351 /* verify user exists */
1352 ## repeat retrieve (users_id = users.#users_id) where users.#login = @login
1353 ## inquire_equel (exists = "rowcount")
1354 if (exists != 1) return(SMS_USER);
1356 /* verify list does not exist */
1357 ## repeat retrieve (exists = any(list.name where list.name = @login))
1358 if (exists) return(SMS_LIST);
1360 /* get new list_id */
1361 ## repeat retrieve (list_id = values.value) where values.name = "list_id"
1363 ## repeat replace values (value = @list_id) where values.name = "list_id"
1365 /* create the list */
1366 ## range of tbs is tblstats
1367 ## repeat append list (name = @login, #list_id = @list_id, flags = 1,
1368 ## desc = "User Group", acl_id = @list_id,
1369 ## expdate = "today" + "5 years", modtime = "now")
1370 ## repeat replace tbs (modtime = "now", appends = tbs.appends + 1)
1371 ## where tbs.table = "list"
1373 /* add user to list */
1374 ## repeat append members (#list_id = @list_id, member_type = "USER",
1375 ## member_id = @users_id)
1376 ## repeat replace tbs (modtime = "now", appends = tbs.appends + 1)
1377 ## where tbs.table = "members"
1380 ## range of g is groups
1381 ## range of v is values
1382 ## repeat retrieve (gid = v.value) where v.name = "gid"
1386 ## repeat retrieve (exists = any(g.#gid where g.#gid = @gid))
1388 ## repeat replace v (value = @gid) where v.name = "gid"
1390 /* add list to group table */
1391 ## repeat append groups (#list_id = @list_id, ltid = list.tid, #gid = @gid)
1392 ## where list.#list_id = @list_id
1393 ## repeat replace tbs (modtime = "now", appends = tbs.appends + 1)
1394 ## where tbs.table = "members"
1396 /* and we're done */
1397 return(SMS_SUCCESS);
1402 ** get_members_of_list - optimized query for retrieval of list members
1405 ** argv[0] - list_id
1408 ** - retrieve USER members, then LIST members, then STRING members
1412 get_members_of_list(q, argv, action, actarg)
1419 ## char member_name[129];
1422 list_id = *(int *)argv[0];
1424 targv[1] = member_name;
1426 ## range of m is members
1427 ## repeat retrieve (member_name = users.login)
1428 ## where m.#list_id = @list_id and m.member_type = "USER"
1429 ## and m.member_id = users.users_id
1430 ## sort by #member_name
1432 (*action)(2, targv, actarg);
1436 ## repeat retrieve (member_name = list.name)
1437 ## where m.#list_id = @list_id and m.member_type = "LIST"
1438 ## and m.member_id = list.#list_id
1439 ## sort by #member_name
1441 (*action)(2, targv, actarg);
1444 targv[0] = "STRING";
1445 ## repeat retrieve (member_name = strings.string)
1446 ## where m.#list_id = @list_id and m.member_type = "STRING"
1447 ## and m.member_id = strings.string_id
1448 ## sort by #member_name
1450 (*action)(2, targv, actarg);
1453 return(SMS_SUCCESS);
1457 ** get_groups_of_user - optimized query for retrieval of all groups to
1458 ** which a user belongs
1462 get_groups_of_user(q, argv, action, actarg)
1469 ## char list_name[33];
1474 users_id = *(int *)argv[0];
1475 targv[0] = list_name;
1478 ## range of m is members
1480 ## repeat retrieve (list_name = list.name, gid = text(groups.#gid))
1481 ## where m.member_id = @users_id and m.member_type = "USER" and
1482 ## m.list_id = groups.list_id and groups.ltid = list.tid
1483 ## sort by #list_name
1485 (*action)(2, targv, actarg);
1487 ## inquire_equel (rowcount = "rowcount")
1489 return ((rowcount = 0) ? SMS_NO_MATCH : SMS_SUCCESS);
1492 get_groups_of_all_users(q, argv, action, actarg)
1508 ## range of u is users
1509 ## range of l is list
1510 ## range of m is members
1511 ## range of g is groups
1513 ## set lockmode session where readlock = nolock
1515 ## repeat retrieve (login = u.#login, group = l.name, gid = text(g.#gid))
1516 ## where m.member_type = "USER" and m.member_id = u.users_id and
1517 ## u.status != 0 and m.list_id = g.list_id and
1519 ## sort by #login, #group
1521 (*action)(3, targv, actarg);
1524 ## inquire_equel (errorno = "errorno")
1525 ## set lockmode session where readlock = system
1527 return((errorno) ? SMS_INGRES_ERR : SMS_SUCCESS);
1531 ** get_all_poboxes - optimized query for retrieval of all poboxes
1534 ** - retrieve LOCAL boxes, then POP boxes, then FOREIGN boxes
1538 get_all_poboxes(q, argv, action, actarg)
1545 ## char machine[129];
1555 ## set lockmode session where readlock = nolock
1556 ## range of p is pobox
1557 ## repeat retrieve (login=users.#login, machine = #machine.name, box=p.#box)
1558 ## where p.type = "LOCAL" and p.users_id = users.users_id
1559 ## and p.mach_id = #machine.mach_id
1561 (*action)(4, targv, actarg);
1565 ## repeat retrieve (login=users.#login, machine = #machine.name, box=p.#box)
1566 ## where p.type = "POP" and p.users_id = users.users_id
1567 ## and p.mach_id = #machine.mach_id
1569 (*action)(4, targv, actarg);
1572 targv[1] = "FOREIGN";
1573 ## repeat retrieve (login=users.#login, machine=strings.string, box=p.#box)
1574 ## where p.type = "FOREIGN" and p.users_id = users.users_id
1575 ## and p.mach_id = strings.string_id
1577 (*action)(4, targv, actarg);
1579 ## set lockmode session where readlock = system
1581 return(SMS_SUCCESS);
1584 get_new_poboxes(q, argv, action, actarg)
1592 ## char machine[129];
1603 ## range of p is pobox
1604 ## repeat retrieve (login=users.#login, machine = #machine.name, box=p.#box)
1605 ## where p.type = "LOCAL" and p.users_id = users.users_id
1606 ## and p.mach_id = #machine.mach_id and
1607 ## p.#created > @created
1609 (*action)(4, targv, actarg);
1613 ## repeat retrieve (login=users.#login, machine = #machine.name, box=p.#box)
1614 ## where p.type = "POP" and p.users_id = users.users_id
1615 ## and p.mach_id = #machine.mach_id and
1616 ## p.#created > @created
1618 (*action)(4, targv, actarg);
1621 targv[1] = "FOREIGN";
1622 ## repeat retrieve (login=users.#login, machine=strings.string, box=p.#box)
1623 ## where p.type = "FOREIGN" and p.users_id = users.users_id
1624 ## and p.mach_id = strings.string_id and
1625 ## p.#created > @created
1627 (*action)(4, targv, actarg);
1630 return(SMS_SUCCESS);
1633 /* Validation Routines */
1635 validate_row(q, argv, v)
1636 register struct query *q;
1638 register struct validate *v;
1646 /* build where clause */
1647 build_qual(v->qual, v->argc, argv, qual);
1649 /* setup ingres variables */
1654 if (log_flags & LOG_RES)
1655 /* tell the logfile what we're doing */
1656 com_err(whoami, 0, "validating row: %s", qual);
1658 /* look for the record */
1659 ## range of rvar is table
1660 ## retrieve (rowcount = count(rvar.name where qual))
1661 if (rowcount == 0) return(SMS_NO_MATCH);
1662 if (rowcount > 1) return(SMS_NOT_UNIQUE);
1666 validate_fields(q, argv, vo, n)
1668 register char *argv[];
1669 register struct valobj *vo;
1672 register int status;
1677 if (log_flags & LOG_RES)
1678 com_err(whoami, 0, "validating %s in %s: %s",
1679 vo->namefield, vo->table, argv[vo->index]);
1680 status = validate_name(argv, vo);
1684 if (log_flags & LOG_RES)
1685 com_err(whoami, 0, "validating %s in %s: %s",
1686 vo->idfield, vo->table, argv[vo->index]);
1687 status = validate_id(argv, vo);
1691 if (log_flags & LOG_RES)
1692 com_err(whoami, 0, "validating date: %s", argv[vo->index]);
1693 status = validate_date(argv, vo);
1697 if (log_flags & LOG_RES)
1698 com_err(whoami, 0, "validating %s type: %s",
1699 vo->table, argv[vo->index]);
1700 status = validate_type(argv, vo);
1704 if (log_flags & LOG_RES)
1705 com_err(whoami, 0, "validating typed data (%s): %s",
1706 argv[vo->index - 1], argv[vo->index]);
1707 status = validate_typedata(q, argv, vo);
1711 status = SMS_EXISTS;
1715 status = SMS_EXISTS;
1720 if (status != SMS_EXISTS) return(status);
1724 return(SMS_SUCCESS);
1727 validate_id(argv, vo)
1729 register struct valobj *vo;
1739 name = argv[vo->index];
1741 /* minor kludge to upcasify machine names */
1742 if (!bcmp(table, "machine", 7))
1743 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
1744 namefield = vo->namefield;
1745 idfield = vo->idfield;
1746 ## retrieve (id = table.idfield) where table.namefield = name
1747 ## inquire_equel (rowcount = "rowcount")
1748 if (rowcount != 1) return(vo->error);
1749 *(int *)argv[vo->index] = id;
1753 validate_name(argv, vo)
1755 register struct valobj *vo;
1762 name = argv[vo->index];
1764 namefield = vo->namefield;
1765 ## retrieve (rowcount = countu(table.namefield
1766 ## where table.namefield = name))
1767 return ((rowcount == 1) ? SMS_EXISTS : vo->error);
1770 /* Special validation routine for get_filesys */
1771 validate_label(q, argv)
1775 register char *label;
1779 c = (char *)index(label, '*');
1780 if (c == label) return(SMS_NOT_UNIQUE);
1781 return(SMS_SUCCESS);
1784 /* Special validation routine for delete_filesys */
1785 validate_label_2(q, argv)
1789 if (index(argv[0], '*') != 0) return(SMS_NOT_UNIQUE);
1790 return(SMS_SUCCESS);
1793 validate_date(argv, vo)
1801 idate = argv[vo->index];
1803 ## retrieve (dd = interval("years", date(idate) - date("today")))
1804 ## inquire_equel (errorno = "errorno")
1805 if (errorno != 0 || dd > 5.0) return(SMS_DATE);
1806 return(SMS_SUCCESS);
1809 validate_type(argv, vo)
1811 register struct valobj *vo;
1818 typename = vo->table;
1819 value = argv[vo->index];
1821 /* uppercase type fields */
1822 for (c = value; *c; c++) if (islower(*c)) *c = toupper(*c);
1824 ## range of a is alias
1825 ## repeat retrieve (rowcount = count(a.trans where a.name = @typename and
1826 ## a.type = "TYPE" and
1827 ## a.trans = @value))
1828 return ((rowcount == 1) ? SMS_EXISTS : vo->error);
1831 /* validate member or type-specific data field */
1833 validate_typedata(q, argv, vo)
1834 register struct query *q;
1835 register char *argv[];
1836 register struct valobj *vo;
1839 ## char *field_type;
1840 ## char data_type[17];
1846 /* get named object */
1847 name = argv[vo->index];
1849 /* get field type string (known to be at index-1) */
1850 field_type = argv[vo->index-1];
1852 /* get corresponding data type associated with field type name */
1853 ## repeat retrieve (data_type = alias.trans)
1854 ## where alias.#name = @field_type and alias.type = "TYPEDATA"
1855 ## inquire_equel (rowcount = "rowcount")
1856 if (rowcount != 1) return(SMS_TYPE);
1858 /* now retrieve the record id corresponding to the named object */
1860 if (!strcmp(data_type, "user")) {
1862 ## repeat retrieve (id = users.users_id) where users.login = @name
1863 ## inquire_equel (rowcount = "rowcount")
1864 if (rowcount != 1) return(SMS_USER);
1866 } else if (!strcmp(data_type, "list")) {
1868 ## repeat retrieve (id = list.list_id) where list.#name = @name
1869 ## inquire_equel (rowcount = "rowcount")
1870 if (rowcount != 1) return(SMS_LIST);
1872 } else if (!strcmp(data_type, "machine")) {
1874 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
1875 ## repeat retrieve (id = machine.mach_id) where machine.#name = @name
1876 ## inquire_equel (rowcount = "rowcount")
1877 if (rowcount != 1) return(SMS_MACHINE);
1879 } else if (!strcmp(data_type, "string")) {
1881 ## range of s is strings
1882 ## repeat retrieve (id = s.string_id, refc = s.#refc)
1883 ## where s.string = @name
1884 ## inquire_equel (rowcount = "rowcount")
1885 if (rowcount == 0) {
1886 if (q->type != APPEND) return(SMS_STRING);
1887 ## range of v is values
1888 ## retrieve (id = v.value) where v.#name = "strings_id"
1890 ## replace v (value = id) where v.#name = "strings_id"
1891 ## append to strings (string_id = id, string = name, #refc = 1)
1892 } else if (rowcount == 1) {
1893 if (q->type == APPEND || q->type == DELETE) {
1894 refc += (q->type == APPEND) ? 1 : -1;
1896 ## replace s (#refc = refc) where s.string_id = id
1898 ## delete s where s.string_id = id
1906 /* now set value in argv */
1907 *(int *)argv[vo->index] = id;
1909 return (SMS_EXISTS);
1913 translate_ids(q, sq, v, action, actarg)
1914 register struct query *q;
1915 register struct save_queue *sq;
1916 register struct validate *v;
1917 register int (*action)();
1921 ## char *field_type;
1922 ## char data_type[17];
1929 for (i = 0; i < v->objcnt; i++) {
1931 if (vo->type == V_FOLLOWUP) break;
1935 while (sq_get_data(sq, &argv)) {
1939 sscanf(argv[i], "%d", &id);
1941 name = (char *)malloc(129);
1944 /* get field type string (known to be at index-1) */
1945 field_type = argv[vo->index-1];
1947 /* get corresponding data type associated with field type name */
1948 ## repeat retrieve (data_type = alias.trans)
1949 ## where alias.#name = @field_type and alias.type = "TYPEDATA"
1950 ## inquire_equel (rowcount = "rowcount")
1951 if (rowcount != 1) {
1952 sprintf(name, "%d", id);
1953 (*action)(q->vcnt, argv, actarg);
1957 /* retrieve object name */
1959 if (!strcmp(data_type, "user")) {
1961 ## repeat retrieve (name = users.login) where users.users_id = @id
1962 ## inquire_equel (rowcount = "rowcount")
1964 } else if (!strcmp(data_type, "list")) {
1966 ## repeat retrieve (name = list.#name) where list.list_id = @id
1967 ## inquire_equel (rowcount = "rowcount")
1969 } else if (!strcmp(data_type, "machine")) {
1971 ## repeat retrieve (name = machine.#name) where machine.mach_id = @id
1972 ## inquire_equel (rowcount = "rowcount")
1974 } else if (!strcmp(data_type, "string")) {
1976 ## repeat retrieve (name = strings.string)
1977 ## where strings.string_id = @id
1978 ## inquire_equel (rowcount = "rowcount")
1984 /* if there wasn't a corresponding object name, then use the id */
1985 if (rowcount != 1) sprintf(name, "%d", id);
1988 (*action)(q->vcnt, argv, actarg);
1990 /* free saved data */
1991 for (i = 0; i < q->vcnt; i++)
1997 return (SMS_SUCCESS);
2004 * c-continued-statement-offset: 4
2005 * c-brace-offset: -4
2006 * c-argdecl-indent: 4
2007 * c-label-offset: -4