6 * Copyright (C) 1987 by the Massachusetts Institute of Technology
9 * Revision 1.15 1987-09-11 15:31:58 wesommer
10 * add_user_group modified to side-effect the time for tbs for groups as
11 * well as the other things.
13 Revision 1.15 87/09/10 22:44:49 wesommer
14 One more table needs to be modified when adding the user-group.
16 Revision 1.14 87/09/04 17:50:03 mike
17 Renamed delete_list_members to followup_delete_list. New routine removes
18 list from maillists and groups tables in addition to the members table.
20 Added routines validate_label and validate_label_2 used in validating
21 filesys labels for get_filesys and delete_filesys respectively.
23 Revision 1.13 87/09/01 16:24:01 wesommer
24 A list should be considered modified if its acl changes.
26 Revision 1.12 87/08/29 00:05:54 mike
27 Fixed bug in check_nfs.
28 Added code to upcasify machine names in validate_id.
30 Revision 1.11 87/08/28 14:55:45 mike
31 Modified delete_locker to require only one argument, the login name.
32 Modified get_groups_of_all_users and get_all_poboxes to disable INGRES
35 Revision 1.10 87/08/25 15:56:54 mike
36 - Fixed bugs in get_groups_of_all_users
37 - Added tblstats updates to add_user_group
38 - Added routines: add_hostaccess (ashi), delete_hostaccess (dshi),
39 followup_ushp, and followup_usha
41 Revision 1.9 87/08/22 17:41:34 wesommer
42 More of Mike's changes.
44 Revision 1.8 87/08/18 15:05:20 wesommer
45 Fixed definition of add_locker.
47 Revision 1.7 87/08/04 01:49:41 wesommer
50 Revision 1.6 87/08/04 01:10:02 wesommer
51 Changes by mike; checked in prior to my hacking.
53 Revision 1.5 87/07/30 14:54:13 wesommer
54 Added debugging code in an attempt to catch a flakey problem.
56 Revision 1.4 87/07/30 00:30:21 wesommer
57 replaced appends = appends+1 with appends = tbs.appends+1
59 Revision 1.3 87/07/30 00:26:11 wesommer
60 Changes by mike prior to "appends" fix.
62 Revision 1.2 87/07/29 16:00:39 wesommer
65 Revision 1.1 87/07/29 15:13:57 wesommer
71 static char *rcsid_qsupport_qc = "$Header$";
75 #include "sms_server.h"
82 /* Specialized Access Routines */
85 ** access_user - verify that client name equals specified login name
87 ** Used by: update_user_shell
88 ** update_finger_by_login
90 ** - since field validation routines are called first, a users_id is
91 ** now in argv[0] instead of the login name. Therefore, we must
92 ** convert the client name to a users_id.
95 access_user(q, argv, cl)
100 register struct krbname *krb;
102 ## char *client_name;
105 client_name = cl->kname.name;
106 ## repeat retrieve (client_id = users.users_id)
107 ## where users.login = @client_name
108 ## inquire_equel (rowcount = "rowcount")
109 if (rowcount != 1) return(SMS_PERM);
110 if (client_id != *(int *)argv[0]) return(SMS_PERM);
116 ** access_pop - same as access_user plus verifies that a user has only one
117 ** mailbox of type "POP"
120 ** argv[0] - users_id
126 ** - if q->name = "add_pobox" and type = "POP",
127 ** verify that no POP box already exists for user
128 ** - call access_user
132 access_pop(q, argv, cl)
142 if (!bcmp(q->name, "add_pobox", 10) && !bcmp(argv[1], "POP", 4)) {
143 users_id = *(int *)argv[0];
144 mach_id = *(int *)argv[2];
146 ## range of p is pobox
147 ## repeat retrieve (exists = any(p.#box where p.#users_id = @users_id
148 ## and p.type = "POP"
149 ## and p.#mach_id = @mach_id
150 ## and p.#box = @box))
151 if (exists) return(SMS_EXISTS);
154 return(access_user(q, argv, cl));
158 ** access_list - check access for adding or deleting list members
160 ** Inputs: argv[0] - list_id
161 ** cl->krb.name - client name
163 ** - check that client is a member of the access control list
164 ** - OR, if q->shortname == {amtl | dfml} and
165 ** if list.flags & LF_PUBLIC, allow access if client = member
169 access_list(q, argv, cl)
183 list_id = *(int *)argv[0];
184 ## repeat retrieve (acl_id = list.#acl_id, flags = list.#flags)
185 ## where list.#list_id = @list_id
187 /* parse client structure */
188 status = get_client(cl, &client_type, &client_id);
189 if (status != SMS_SUCCESS) return(status);
191 /* if amtl or dmfl and list is public allow client to add or delete self */
192 if (!bcmp("amtl", q->shortname, 4) || !bcmp("dmfl", q->shortname, 4)) {
193 if ((flags & LF_PUBLIC) && !bcmp("USER", argv[1], 4)) {
194 member_id = *(int *)argv[2];
195 if (member_id == client_id) return(SMS_SUCCESS);
199 /* check for client in access control list */
200 exists = find_member(acl_id, client_type, client_id, 0);
201 if (!exists) return(SMS_PERM);
207 ** access_maillist - access_list + disallow adding user-group to maillists
214 access_maillist(q, argv, cl)
221 ## char list_name[32];
224 status = access_list(q, argv, cl);
225 if (status != SMS_SUCCESS) return(status);
226 if (bcmp(q->name, "add_maillist", 12)) return(status);
228 list_id = *(int *)argv[0];
229 ## range of g is groups
230 ## repeat retrieve (exists = any(g.#list_id where g.#list_id = @list_id))
231 if (!exists) return(SMS_SUCCESS);
232 ## repeat retrieve (list_name = list.name) where list.#list_id = @list_id
233 ## repeat retrieve (exists = any(users.login where users.login = @list_name))
234 return ((exists) ? SMS_USER_GROUP : SMS_SUCCESS);
238 ** Setup routine for add_group
242 ** Description: allocate next gid and store in values table
246 setup_add_group(q, argv, cl, access_check)
256 status = access_list(q, argv, cl);
258 if (status != SMS_SUCCESS || access_check) return(status);
260 ## range of g is groups
261 ## range of v is values
262 ## repeat retrieve (ngid = v.value) where v.name = "gid"
266 ## repeat retrieve (exists = any(g.#gid where g.#gid = @ngid))
269 ## repeat replace v (value = @ngid) where v.name = "gid"
274 ** Setup routine for add_user
276 ** Inputs: argv[0] - login
281 ** - if argv[1] == "#" then set argv[1] = next(uid)
282 ** - if argv[0] == "#" then set argv[0] = "#<uid>"
286 setup_add_user(q, argv, cl, access_check)
288 register char *argv[];
295 if (access_check) return(SMS_SUCCESS);
297 if (!bcmp(argv[1], "#", 2)) {
298 ## range of u is users
299 ## range of v is values
300 ## repeat retrieve (nuid = v.value) where v.name = "uid"
304 ## repeat retrieve (exists = any(u.#uid where u.#uid = @nuid))
306 ## repeat replace v (value = @nuid) where v.name = "uid"
307 sprintf(argv[1], "%d", nuid);
310 if (!bcmp(argv[0], "#", 2)) {
311 sprintf(argv[0], "#%s", argv[1]);
318 ** followup_add_user - add finger entry, set_user_modtime
319 ** followup_delete_user - delete finger entry
322 ** argv[0] - login (add_user)
323 ** argv[0] - users_id (delete_user)
327 followup_add_user(q, argv)
336 ## char fullname[128];
342 /* get user information */
343 ## range of u is users
344 ## repeat retrieve (users_id = u.#users_id, last = u.#last,
345 ## first = u.#first, middle = u.#middle)
346 ## where u.#login = @login
351 while (*cp1) *cp2++ = *cp1++;
354 if (*cp1 == 0) cp2--;
355 while (*cp1) *cp2++ = *cp1++;
358 while (*cp2++ = *cp1++) ;
360 /* create a finger entry */
361 ## repeat append finger (#users_id = @users_id, #fullname = @fullname)
363 /* set modtime (creation time) on user */
364 ## repeat replace u (modtime = "now") where u.#users_id = @users_id
369 followup_delete_user(q, argv)
375 users_id = *(int *)argv[0];
376 ## repeat delete finger where finger.#users_id = @users_id
381 ** setup_add_filesys - verify existance of referenced file systems
382 ** setup_update_filesys - same, except argv[1..5] --> argv[2..6]
384 ** Inputs: Add Update
385 ** argv[0] - label label
386 ** argv[1] - type new label
387 ** argv[2] - mach_id type
388 ** argv[3] - name mach_id
389 ** argv[4] - mount name
390 ** argv[5] - access mount
395 ** * verify mach_id/name in rvdvirt
396 ** * verify access in {r, x, R, X}
398 ** * extract directory prefix from name
399 ** * verify mach_id/dir in nfsphys
400 ** * verify access in {r, w, R, W}
403 ** SMS_RVD - no such rvd
404 ** SMS_NFS - specified directory not exported
405 ** SMS_FILESYS_ACCESS - invalid filesys access
409 setup_add_filesys(q, argv)
419 mach_id = *(int *)argv[2];
423 if (!bcmp(type, "RVD", 3))
424 return (check_rvd(mach_id, name, access));
425 else if (!bcmp(type, "NFS", 3))
426 return (check_nfs(mach_id, name, access));
431 setup_update_filesys(q, argv)
441 mach_id = *(int *)argv[3];
445 if (!bcmp(type, "RVD", 3))
446 return (check_rvd(mach_id, name, access));
447 else if (!bcmp(type, "NFS", 3))
448 return (check_nfs(mach_id, name, access));
453 ##check_rvd(mach_id, name, access)
461 ## range of rv is rvdvirt
462 ## retrieve (rowcount = any(rv.#name where rv.#mach_id = mach_id and
464 if (rowcount == 0) return(SMS_RVD);
466 caccess = (isupper(*access)) ? tolower(*access) : *access;
467 if (caccess != 'r' && caccess != 'x') return(SMS_FILESYS_ACCESS);
472 ##check_nfs(mach_id, name, access)
484 caccess = (isupper(*access)) ? tolower(*access) : *access;
485 if (caccess != 'r' && caccess != 'w') return(SMS_FILESYS_ACCESS);
488 ## range of np is nfsphys
489 ## retrieve (dir = np.#dir) where np.#mach_id = mach_id
494 if (*cp1++ != *cp2) break;
498 status = SMS_SUCCESS;
506 /* Followup Routines */
508 set_user_modtime(q, argv)
515 ## repeat replace u (modtime = "now") where u.#login = @login
519 set_user_modtime_by_id(q, argv)
525 users_id = *(int *)argv[0];
526 ## repeat replace users (modtime = "now") where users.#users_id = @users_id
530 set_list_modtime(q, argv)
537 ## repeat replace list (modtime = "now") where list.name = @list_name
541 set_list_modtime_by_id(q, argv)
547 list_id = *(int *)argv[0];
548 ## repeat replace list (modtime = "now") where list.#list_id = @list_id
549 ## repeat replace list (modtime = "now") where list.#acl_id = @list_id
553 set_finger_modtime(q, argv)
559 users_id = *(int *)argv[0];
560 ## repeat replace f (modtime = "now") where f.#users_id = @users_id
565 ** followup_amtl - followup for amtl and dmfl; when adding a list
566 ** member to a maillist, add list to maillist table,
567 ** unless list is a user-group.
568 ** Then set_list_modtime_by_id.
572 ** argv[1] - member_type
573 ** argv[2] - member_id
577 followup_amtl(q, argv)
584 ## char list_name[33];
586 list_id = *(int *)argv[0];
588 ## repeat replace list (modtime = "now") where list.#list_id = @list_id
589 ## repeat replace list (modtime = "now") where list.#acl_id = @list_id
591 /* if query is not amtl or if member_type is not LIST then return */
592 if (bcmp(q->shortname, "amtl", 4) || bcmp(argv[1], "LIST", 4))
595 member_id = *(int *)argv[2];
596 ## range of l is list
597 ## range of ml is maillists
598 ## range of g is groups
600 /* is parent list a mailing list? */
601 ## repeat retrieve (exists = any(ml.#list_id where ml.#list_id=@list_id))
603 /* if not then return */
604 if (!exists) return(SMS_SUCCESS);
606 /* is member_list a user-group? */
608 ## repeat retrieve (exists = any(g.#list_id where g.#list_id = @member_id))
611 ## repeat retrieve (list_name = l.#name) where l.#list_id = @member_id
612 /* is list_name a username? */
613 ## repeat retrieve (exists = any(users.login
614 ## where users.login = @list_name))
615 /* yes, return error */
616 if (exists) return(SMS_USER_GROUP);
619 /* list is not a user-group; add list to maillist table */
620 ## repeat append maillists (#list_id = @member_id, ltid = l.tid)
621 ## where l.#list_id = @member_id
627 ** followup_add_pobox
628 ** followup_delete_pobox - followup routines for pobox queries
631 ** add_pobox: set pobox creation time
632 ** increment pop usage in serverhosts
634 ** delete_pobox: decrement pop usage in serverhosts
638 followup_add_pobox(q, argv)
642 set_pobox_creation(q, argv);
643 set_pop_usage(q, argv, 1);
647 followup_delete_pobox(q, argv)
651 set_pop_usage(q, argv, -1);
655 set_pobox_creation(q, argv)
664 users_id = *(int *)argv[0];
666 mach_id = *(int *)argv[2];
669 ## range of p is pobox
670 ## repeat replace p (created = "now")
671 ## where p.#users_id = @users_id and p.#type = @type and
672 ## p.#mach_id = @mach_id and p.#box = @box
674 return (SMS_SUCCESS);
678 ** set_pop_usage - incr/decr usage count for pop server in serverhosts talbe
681 ** q->name - "add_pobox" or "delete_pobox"
686 ** - incr/decr value field in serverhosts table for pop/mach_id
690 set_pop_usage(q, argv, count)
697 if (bcmp(argv[1], "POP", 3)) return(SMS_SUCCESS);
699 mach_id = *(int *)argv[2];
702 ## range of sh is serverhosts
703 ## repeat replace sh (value1 = sh.value1 + @n)
704 ## where sh.service = "pop" and sh.#mach_id = @mach_id
710 ** delete_user_poboxes - delete all poboxes for a user
713 ** argv[0] - users_id
717 delete_user_poboxes(q, argv)
727 users_id = *(int *)argv[0];
729 /* get machine ids for pop server(s) on which the user currently exists */
730 ## range of p is pobox
732 ## repeat retrieve (mach_id = p.#mach_id)
733 ## where p.#users_id = @users_id and p.type = "POP"
735 mach_ids[i++] = mach_id;
741 /* decrement counts on serverhost entries */
742 ## range of sh is serverhosts
744 mach_id = mach_ids[i];
745 ## repeat replace sh (value1 = sh.value1 - 1)
746 ## where sh.service = "pop" and sh.#mach_id = @mach_id
749 /* delete user's poboxes */
750 ## repeat delete p where p.#users_id = @users_id
758 ** delete_current_quota - adjust nfsphys values on xxx_quota queries.
763 ** argv[2] - users_id
764 ** argv[3] - quota (add_new_quota only)
767 ** delete_current_quota:
768 ** - find nfsquota entry
769 ** - decrement nfsphys.allocated by nfsquota.quota
771 ** - increment nfsphys.allocated by quota
775 add_new_quota(q, argv)
777 register char *argv[];
783 mach_id = *(int*)argv[0];
785 quota = *(int *)argv[3];
787 ## range of np is nfsphys
788 ## repeat replace np (allocated = np.allocated + @quota)
789 ## where np.#mach_id = @mach_id and np.#device = @device
794 delete_current_quota(q, argv, cl, access_check)
796 register char *argv[];
805 if (access_check) return(SMS_SUCCESS);
807 mach_id = *(int *)argv[0];
809 users_id = *(int *)argv[2];
811 ## range of np is nfsphys
812 ## range of nq is nfsquota
813 ## repeat retrieve (quota = nq.#quota)
814 ## where nq.#mach_id = @mach_id and nq.#device = @device and
815 ## nq.#users_id = @users_id
816 ## repeat replace np (allocated = np.allocated - @quota)
817 ## where np.#mach_id = @mach_id and np.#device = @device
823 ** add_hostaccess - create entry in hostaccess table upon adding a new
824 ** machine to the serverhosts table where service =
833 add_hostaccess(q, argv)
839 /* only work with service = "hostaccess" */
840 if (bcmp(argv[0], "hostaccess", 10)) return(SMS_SUCCESS);
842 mach_id = *(int *)argv[1];
843 ## repeat append hostaccess (#mach_id = @mach_id, status = 0)
844 ## repeat replace tblstats (modtime = "now", appends = tblstats.appends + 1)
845 ## where tblstats.table = "hostaccess"
849 /* followup to delete_server_host_info */
851 delete_hostaccess(q, argv)
857 /* only work with service = "hostaccess" */
858 if (bcmp(argv[0], "hostaccess", 10)) return(SMS_SUCCESS);
860 mach_id = *(int *)argv[1];
861 ## repeat delete hostaccess where hostaccess.#mach_id = @mach_id
862 ## repeat replace tblstats (modtime = "now", deletes = tblstats.deletes + 1)
863 ## where tblstats.table = "hostaccess"
867 followup_ushp(q, argv)
874 mach_id = *(int *)argv[0];
875 ## range of ha is hostaccess
876 ## repeat retrieve (status = ha.#status) where ha.#mach_id = @mach_id
878 ## repeat replace ha (#status = @status) where ha.#mach_id = @mach_id
882 followup_usha(q, argv)
889 mach_id = *(int *)argv[0];
890 ## range of ha is hostaccess
891 ## repeat retrieve (status = ha.#status) where ha.#mach_id = @mach_id
893 ## repeat replace ha (#status = @status) where ha.#mach_id = @mach_id
898 ** followup_delete_list - called after the delete_list query to clean up
899 ** members table; also deletes list from maillist
900 ** and groups tables.
902 ** Inputs: argv[0] - list_id
905 ** - foreach string member: decr string refc; ifzero, delete string
906 ** - delete all members entries for this list_id
910 followup_delete_list(q, argv)
912 register char *argv[];
918 struct save_queue *sq;
919 struct save_queue *sq_create();
921 list_id = *(int *)argv[0];
924 ## range of m is members
925 ## repeat retrieve (string_id = m.member_id)
926 ## where m.#list_id = @list_id and m.member_type = "STRING"
928 sq_save_data(sq, string_id);
931 while (sq_get_data(sq, &string_id)) {
932 ## range of s is strings
933 ## repeat retrieve (refc = s.#refc) where s.#string_id = @string_id
934 ## inquire_equel (rowcount = "rowcount")
935 if (rowcount == 0) continue;
937 ## repeat delete s where s.#string_id = @string_id
939 ## repeat replace s (#refc = @refc) where s.#string_id = @string_id
944 ## repeat delete m where m.#list_id = @list_id
945 ## repeat delete maillists where maillists.#list_id = @list_id
946 ## repeat delete groups where groups.#list_id = @list_id
952 ** followup_grvd - Support routine for get_rvd_servers query
955 ** q - grvd query structure
956 ** sq - save_queue struture: contains list of {machine, oper_acl_id,
957 ** admin_acl_id, shutdown_acl_id} records.
958 ** v - validate structure (not used)
959 ** action - action routine
960 ** actarg - action routine argument
963 ** - translate acl_ids to list names
967 followup_grvd(q, sq, v, action, actarg)
969 struct save_queue *sq;
978 ## char shutdown[33];
985 ## range of l is list
987 while (sq_get_data(sq, &argv)) {
988 sscanf(argv[0], "%d", &list_id);
989 ## repeat retrieve (oper = l.name) where l.#list_id = @list_id
990 sscanf(argv[1], "%d", &list_id);
991 ## repeat retrieve (admin = l.name) where l.#list_id = @list_id
992 sscanf(argv[2], "%d", &list_id);
993 ## repeat retrieve (shutdown = l.name) where l.#list_id = @list_id
995 (*action)(3, targv, actarg);
1002 return(SMS_SUCCESS);
1005 followup_gars(q, sq, v, action, actarg)
1007 struct save_queue *sq;
1016 ## char shutdown[33];
1021 targv[3] = shutdown;
1023 ## range of l is list
1025 while (sq_get_data(sq, &argv)) {
1026 sscanf(argv[1], "%d", &list_id);
1027 ## repeat retrieve (oper = l.name) where l.#list_id = @list_id
1028 sscanf(argv[2], "%d", &list_id);
1029 ## repeat retrieve (admin = l.name) where l.#list_id = @list_id
1030 sscanf(argv[3], "%d", &list_id);
1031 ## repeat retrieve (shutdown = l.name) where l.#list_id = @list_id
1034 (*action)(4, targv, actarg);
1042 return(SMS_SUCCESS);
1046 ** set_next_object_id - set next object id in values table
1048 ** Inputs: object - object name in values table
1050 ** - called before an APPEND operation to set the next object id to
1051 ** be used for the new record
1055 set_next_object_id(object)
1061 ## range of v is values
1062 ## repeat replace v (value = v.value + 1) where v.#name = @name
1063 return(SMS_SUCCESS);
1067 ** get_query_need - check modtime of query's associated table against given
1068 ** time and return true if greater (false if not)
1071 ** argv[0] - query name
1072 ** argv[1] - time to compare against
1076 get_query_need(q, argv, action, actarg)
1078 register char *argv[];
1082 ## char *last_get_time;
1086 struct query *get_query_by_name();
1088 q1 = get_query_by_name(argv[0]);
1090 last_get_time = argv[1];
1093 if (q1->type != RETRIEVE) return(SMS_NO_MATCH);
1095 ## range of tbs is tblstats
1096 ## repeat retrieve (need = any(tbs.modtime where tbs.#table = @table and
1097 ## tbs.modtime > @last_get_time))
1099 result = (need) ? "true" : "false";
1100 (*action)(1, &result, actarg);
1101 return(SMS_SUCCESS);
1105 ** get_list_is_group
1106 ** get_list_is_maillist
1109 ** argv[0] - list_id
1116 get_list_is_group(q, argv, action, actarg)
1126 list_id = *(int *)argv[0];
1128 ## range of g is groups
1129 ## repeat retrieve (exists = any(g.#list_id where g.#list_id = @list_id))
1131 result = (exists) ? "true" : "false";
1132 (*action)(1, &result, actarg);
1133 return(SMS_SUCCESS);
1136 get_list_is_maillist(q, argv, action, actarg)
1146 list_id = *(int *)argv[0];
1148 ## range of ml is maillists
1149 ## repeat retrieve (exists = any(ml.#list_id where ml.#list_id = @list_id))
1151 result = (exists) ? "true" : "false";
1152 (*action)(1, &result, actarg);
1153 return(SMS_SUCCESS);
1158 ** add_locker - special query routine for creating a user locker
1161 ** argv[0] - users_id
1162 ** argv[1] - machine_id
1164 ** argv[3] - initial quota
1167 ** - get prefix directory (dir) for mount point on specified machine/device
1168 ** - create filesys entry (label=<login>, type=NFS, machine=<machine>,
1169 ** mount=<dir>/<login>, access=w, acl=dbadmin)
1170 ** - increment allocated in nfsphys by quota
1171 ** - create nfsquota entry
1174 ** - SMS_NFSPHYS - machine/device does not exist in nfsphys
1175 ** - SMS_FILESYS_EXISTS - file system already exists
1180 register struct query *q;
1195 /* copy arguments */
1196 users_id = *(int *)argv[0];
1197 mach_id = *(int *)argv[1];
1199 sscanf(argv[3], "%d", "a);
1201 ## range of u is users
1202 ## range of f is filesys
1203 ## range of np is nfsphys
1204 ## range of tbs is tblstats
1206 /* get login name */
1207 ## repeat retrieve (login = u.#login) where u.#users_id = @users_id
1209 /* get user's acl id */
1210 ## repeat retrieve (user_acl = list.list_id) where list.name = @login
1212 /* get filesystem directory prefix; give error if machine/device
1213 pair not in nfsphys table */
1214 printf("np.mach_id = %d and np.device = %s\n", mach_id, device);
1216 ## repeat retrieve (dir = np.#dir, allocated = np.#allocated)
1217 ## where np.#mach_id = @mach_id and np.#device = @device
1218 ## inquire_equel (rowcount = "rowcount")
1219 if (rowcount == 0) return(SMS_NFSPHYS);
1221 /* make sure a filesys with user's name does not already exist */
1222 ## repeat retrieve (rowcount = any(f.label where f.label = @login))
1223 if (rowcount != 0) return(SMS_FILESYS_EXISTS);
1225 /* create a new filesys */
1226 sprintf(locker, "%s/%s", dir, login);
1227 sprintf(mount, "/mit/%s", login);
1228 ## repeat append filesys
1229 ## (#label = @login, type = "NFS", #mach_id = @mach_id,
1230 ## name = @locker, access = "w", order = 1, #mount = @mount,
1231 ## acl_id = @user_acl)
1232 ## repeat replace tbs (appends = tbs.appends + 1, modtime = "now")
1233 ## where tbs.table = "filesys"
1235 /* increment usage count in nfsphys table */
1237 ## replace np (#allocated = allocated)
1238 ## where np.#mach_id = mach_id and np.#device = device
1239 ## repeat replace tbs (updates = tbs.updates + 1, modtime = "now")
1240 ## where tbs.table = "nfsphys"
1242 /* create nfsquota entry */
1243 ## append nfsquota (#users_id = users_id, #mach_id = mach_id,
1244 ## #device = device, #quota = quota)
1245 ## repeat replace tbs (appends = tbs.appends + 1, modtime = "now")
1246 ## where tbs.table = "nfsquota"
1248 return(SMS_SUCCESS);
1252 ** delete_locker - special query routine for deleting a user locker
1255 ** argv[0] - users_id
1258 ** - get login name from users_id
1259 ** - get filesys entry from login
1260 ** - use filesys.mach_id and filesys.name to determine machine/device
1261 ** pair for nfsphys and nfsquota
1262 ** - delete filesys entry (label=<login>)
1263 ** - decrement allocated in nfsphys by quota
1264 ** - delete nfsquota entry
1267 ** - SMS_FILESYS - no filesys exists for user
1271 delete_locker(q, argv)
1272 register struct query *q;
1273 register char *argv[];
1284 /* copy arguments */
1285 users_id = *(int *)argv[0];
1287 ## range of u is users
1288 ## range of f is filesys
1289 ## range of np is nfsphys
1290 ## range of nq is nfsquota
1291 ## range of tbs is tblstats
1293 /* get login name */
1294 ## repeat retrieve (login = u.#login) where u.#users_id = @users_id
1296 /* get mach_id and locker name from filesys entry; then delete it */
1297 ## repeat retrieve (mach_id = f.#mach_id, lname = f.#name)
1298 ## where f.#label = @login
1299 ## inquire_equel (rowcount = "rowcount")
1300 if (rowcount == 0) return(SMS_FILESYS);
1301 ## repeat delete f where f.#label = @login
1303 /* get prefix directory */
1304 c = (char *)rindex(lname, '/');
1307 /* get nfs device */
1308 ## repeat retrieve (ndev = np.device)
1309 ## where np.#mach_id = @mach_id and np.dir = @lname
1311 /* get quota from nfsquota entry; then delete entry */
1312 ## repeat retrieve (quota = nq.#quota)
1313 ## where nq.#mach_id = @mach_id and nq.#device = @ndev and
1314 ## nq.#users_id = @users_id
1315 ## repeat delete nq where nq.#mach_id = @mach_id and nq.#device = @ndev and
1316 ## nq.#users_id = @users_id
1318 /* decrement nfsphys.allocated */
1319 ## repeat replace np (allocated = np.allocated - @quota)
1320 ## where np.#mach_id = @mach_id and np.#device = @ndev
1322 /* adjust table statistics */
1323 ## repeat replace tbs (deletes = tbs.deletes + 1, modtime = "now")
1324 ## where tbs.table = "filesys"
1325 ## repeat replace tbs (updates = tbs.updates + 1, modtime = "now")
1326 ## where tbs.table = "nfsphys"
1327 ## repeat replace tbs (deletes = tbs.deletes + 1, modtime = "now")
1328 ## where tbs.table = "nfsquota"
1330 return(SMS_SUCCESS);
1334 ** add_user_group - create a group for a user and add user to group
1340 ** - verify specified user exists
1341 ** - create a list of same name as user
1342 ** - add user as a member of the list
1346 add_user_group(q, argv)
1358 /* verify user exists */
1359 ## repeat retrieve (users_id = users.#users_id) where users.#login = @login
1360 ## inquire_equel (exists = "rowcount")
1361 if (exists != 1) return(SMS_USER);
1363 /* verify list does not exist */
1364 ## repeat retrieve (exists = any(list.name where list.name = @login))
1365 if (exists) return(SMS_LIST);
1367 /* get new list_id */
1368 ## repeat retrieve (list_id = values.value) where values.name = "list_id"
1370 ## repeat replace values (value = @list_id) where values.name = "list_id"
1372 /* create the list */
1373 ## range of tbs is tblstats
1374 ## repeat append list (name = @login, #list_id = @list_id, flags = 1,
1375 ## desc = "User Group", acl_id = @list_id,
1376 ## expdate = "today" + "5 years", modtime = "now")
1377 ## repeat replace tbs (modtime = "now", appends = tbs.appends + 1)
1378 ## where tbs.table = "list"
1380 /* add user to list */
1381 ## repeat append members (#list_id = @list_id, member_type = "USER",
1382 ## member_id = @users_id)
1383 ## repeat replace tbs (modtime = "now", appends = tbs.appends + 1)
1384 ## where tbs.table = "members"
1387 ## range of g is groups
1388 ## range of v is values
1389 ## repeat retrieve (gid = v.value) where v.name = "gid"
1393 ## repeat retrieve (exists = any(g.#gid where g.#gid = @gid))
1395 ## repeat replace v (value = @gid) where v.name = "gid"
1396 /* add list to group table */
1397 ## repeat append groups (#list_id = @list_id, ltid = list.tid, #gid = @gid)
1398 ## where list.#list_id = @list_id
1400 ## repeat replace tbs (modtime = "now", appends = tbs.appends + 1)
1401 ## where tbs.table = "groups"
1403 ## repeat replace tbs (modtime = "now", appends = tbs.appends + 1)
1404 ## where tbs.table = "members"
1406 /* and we're done */
1407 return(SMS_SUCCESS);
1412 ** get_members_of_list - optimized query for retrieval of list members
1415 ** argv[0] - list_id
1418 ** - retrieve USER members, then LIST members, then STRING members
1422 get_members_of_list(q, argv, action, actarg)
1429 ## char member_name[129];
1432 list_id = *(int *)argv[0];
1434 targv[1] = member_name;
1436 ## range of m is members
1437 ## repeat retrieve (member_name = users.login)
1438 ## where m.#list_id = @list_id and m.member_type = "USER"
1439 ## and m.member_id = users.users_id
1440 ## sort by #member_name
1442 (*action)(2, targv, actarg);
1446 ## repeat retrieve (member_name = list.name)
1447 ## where m.#list_id = @list_id and m.member_type = "LIST"
1448 ## and m.member_id = list.#list_id
1449 ## sort by #member_name
1451 (*action)(2, targv, actarg);
1454 targv[0] = "STRING";
1455 ## repeat retrieve (member_name = strings.string)
1456 ## where m.#list_id = @list_id and m.member_type = "STRING"
1457 ## and m.member_id = strings.string_id
1458 ## sort by #member_name
1460 (*action)(2, targv, actarg);
1463 return(SMS_SUCCESS);
1467 ** get_groups_of_user - optimized query for retrieval of all groups to
1468 ** which a user belongs
1472 get_groups_of_user(q, argv, action, actarg)
1479 ## char list_name[33];
1484 users_id = *(int *)argv[0];
1485 targv[0] = list_name;
1488 ## range of m is members
1490 ## repeat retrieve (list_name = list.name, gid = text(groups.#gid))
1491 ## where m.member_id = @users_id and m.member_type = "USER" and
1492 ## m.list_id = groups.list_id and groups.ltid = list.tid
1493 ## sort by #list_name
1495 (*action)(2, targv, actarg);
1497 ## inquire_equel (rowcount = "rowcount")
1499 return ((rowcount = 0) ? SMS_NO_MATCH : SMS_SUCCESS);
1502 get_groups_of_all_users(q, argv, action, actarg)
1518 ## range of u is users
1519 ## range of l is list
1520 ## range of m is members
1521 ## range of g is groups
1523 ## set lockmode session where readlock = nolock
1525 ## repeat retrieve (login = u.#login, group = l.name, gid = text(g.#gid))
1526 ## where m.member_type = "USER" and m.member_id = u.users_id and
1527 ## u.status != 0 and m.list_id = g.list_id and
1529 ## sort by #login, #group
1531 (*action)(3, targv, actarg);
1534 ## inquire_equel (errorno = "errorno")
1535 ## set lockmode session where readlock = system
1537 return((errorno) ? SMS_INGRES_ERR : SMS_SUCCESS);
1541 ** get_all_poboxes - optimized query for retrieval of all poboxes
1544 ** - retrieve LOCAL boxes, then POP boxes, then FOREIGN boxes
1548 get_all_poboxes(q, argv, action, actarg)
1555 ## char machine[129];
1565 ## set lockmode session where readlock = nolock
1566 ## range of p is pobox
1567 ## repeat retrieve (login=users.#login, machine = #machine.name, box=p.#box)
1568 ## where p.type = "LOCAL" and p.users_id = users.users_id
1569 ## and p.mach_id = #machine.mach_id
1571 (*action)(4, targv, actarg);
1575 ## repeat retrieve (login=users.#login, machine = #machine.name, box=p.#box)
1576 ## where p.type = "POP" and p.users_id = users.users_id
1577 ## and p.mach_id = #machine.mach_id
1579 (*action)(4, targv, actarg);
1582 targv[1] = "FOREIGN";
1583 ## repeat retrieve (login=users.#login, machine=strings.string, box=p.#box)
1584 ## where p.type = "FOREIGN" and p.users_id = users.users_id
1585 ## and p.mach_id = strings.string_id
1587 (*action)(4, targv, actarg);
1589 ## set lockmode session where readlock = system
1591 return(SMS_SUCCESS);
1594 get_new_poboxes(q, argv, action, actarg)
1602 ## char machine[129];
1613 ## range of p is pobox
1614 ## repeat retrieve (login=users.#login, machine = #machine.name, box=p.#box)
1615 ## where p.type = "LOCAL" and p.users_id = users.users_id
1616 ## and p.mach_id = #machine.mach_id and
1617 ## p.#created > @created
1619 (*action)(4, targv, actarg);
1623 ## repeat retrieve (login=users.#login, machine = #machine.name, box=p.#box)
1624 ## where p.type = "POP" and p.users_id = users.users_id
1625 ## and p.mach_id = #machine.mach_id and
1626 ## p.#created > @created
1628 (*action)(4, targv, actarg);
1631 targv[1] = "FOREIGN";
1632 ## repeat retrieve (login=users.#login, machine=strings.string, box=p.#box)
1633 ## where p.type = "FOREIGN" and p.users_id = users.users_id
1634 ## and p.mach_id = strings.string_id and
1635 ## p.#created > @created
1637 (*action)(4, targv, actarg);
1640 return(SMS_SUCCESS);
1643 /* Validation Routines */
1645 validate_row(q, argv, v)
1646 register struct query *q;
1648 register struct validate *v;
1656 /* build where clause */
1657 build_qual(v->qual, v->argc, argv, qual);
1659 /* setup ingres variables */
1664 if (log_flags & LOG_RES)
1665 /* tell the logfile what we're doing */
1666 com_err(whoami, 0, "validating row: %s", qual);
1668 /* look for the record */
1669 ## range of rvar is table
1670 ## retrieve (rowcount = count(rvar.name where qual))
1671 if (rowcount == 0) return(SMS_NO_MATCH);
1672 if (rowcount > 1) return(SMS_NOT_UNIQUE);
1676 validate_fields(q, argv, vo, n)
1678 register char *argv[];
1679 register struct valobj *vo;
1682 register int status;
1687 if (log_flags & LOG_RES)
1688 com_err(whoami, 0, "validating %s in %s: %s",
1689 vo->namefield, vo->table, argv[vo->index]);
1690 status = validate_name(argv, vo);
1694 if (log_flags & LOG_RES)
1695 com_err(whoami, 0, "validating %s in %s: %s",
1696 vo->idfield, vo->table, argv[vo->index]);
1697 status = validate_id(argv, vo);
1701 if (log_flags & LOG_RES)
1702 com_err(whoami, 0, "validating date: %s", argv[vo->index]);
1703 status = validate_date(argv, vo);
1707 if (log_flags & LOG_RES)
1708 com_err(whoami, 0, "validating %s type: %s",
1709 vo->table, argv[vo->index]);
1710 status = validate_type(argv, vo);
1714 if (log_flags & LOG_RES)
1715 com_err(whoami, 0, "validating typed data (%s): %s",
1716 argv[vo->index - 1], argv[vo->index]);
1717 status = validate_typedata(q, argv, vo);
1721 status = SMS_EXISTS;
1725 status = SMS_EXISTS;
1730 if (status != SMS_EXISTS) return(status);
1734 return(SMS_SUCCESS);
1737 validate_id(argv, vo)
1739 register struct valobj *vo;
1749 name = argv[vo->index];
1751 /* minor kludge to upcasify machine names */
1752 if (!bcmp(table, "machine", 7))
1753 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
1754 namefield = vo->namefield;
1755 idfield = vo->idfield;
1756 ## retrieve (id = table.idfield) where table.namefield = name
1757 ## inquire_equel (rowcount = "rowcount")
1758 if (rowcount != 1) return(vo->error);
1759 *(int *)argv[vo->index] = id;
1763 validate_name(argv, vo)
1765 register struct valobj *vo;
1772 name = argv[vo->index];
1774 namefield = vo->namefield;
1775 ## retrieve (rowcount = countu(table.namefield
1776 ## where table.namefield = name))
1777 return ((rowcount == 1) ? SMS_EXISTS : vo->error);
1780 /* Special validation routine for get_filesys */
1781 validate_label(q, argv)
1785 register char *label;
1789 c = (char *)index(label, '*');
1790 if (c == label) return(SMS_NOT_UNIQUE);
1791 return(SMS_SUCCESS);
1794 /* Special validation routine for delete_filesys */
1795 validate_label_2(q, argv)
1799 if (index(argv[0], '*') != 0) return(SMS_NOT_UNIQUE);
1800 return(SMS_SUCCESS);
1803 validate_date(argv, vo)
1811 idate = argv[vo->index];
1813 ## retrieve (dd = interval("years", date(idate) - date("today")))
1814 ## inquire_equel (errorno = "errorno")
1815 if (errorno != 0 || dd > 5.0) return(SMS_DATE);
1816 return(SMS_SUCCESS);
1819 validate_type(argv, vo)
1821 register struct valobj *vo;
1828 typename = vo->table;
1829 value = argv[vo->index];
1831 /* uppercase type fields */
1832 for (c = value; *c; c++) if (islower(*c)) *c = toupper(*c);
1834 ## range of a is alias
1835 ## repeat retrieve (rowcount = count(a.trans where a.name = @typename and
1836 ## a.type = "TYPE" and
1837 ## a.trans = @value))
1838 return ((rowcount == 1) ? SMS_EXISTS : vo->error);
1841 /* validate member or type-specific data field */
1843 validate_typedata(q, argv, vo)
1844 register struct query *q;
1845 register char *argv[];
1846 register struct valobj *vo;
1849 ## char *field_type;
1850 ## char data_type[17];
1856 /* get named object */
1857 name = argv[vo->index];
1859 /* get field type string (known to be at index-1) */
1860 field_type = argv[vo->index-1];
1862 /* get corresponding data type associated with field type name */
1863 ## repeat retrieve (data_type = alias.trans)
1864 ## where alias.#name = @field_type and alias.type = "TYPEDATA"
1865 ## inquire_equel (rowcount = "rowcount")
1866 if (rowcount != 1) return(SMS_TYPE);
1868 /* now retrieve the record id corresponding to the named object */
1870 if (!strcmp(data_type, "user")) {
1872 ## repeat retrieve (id = users.users_id) where users.login = @name
1873 ## inquire_equel (rowcount = "rowcount")
1874 if (rowcount != 1) return(SMS_USER);
1876 } else if (!strcmp(data_type, "list")) {
1878 ## repeat retrieve (id = list.list_id) where list.#name = @name
1879 ## inquire_equel (rowcount = "rowcount")
1880 if (rowcount != 1) return(SMS_LIST);
1882 } else if (!strcmp(data_type, "machine")) {
1884 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
1885 ## repeat retrieve (id = machine.mach_id) where machine.#name = @name
1886 ## inquire_equel (rowcount = "rowcount")
1887 if (rowcount != 1) return(SMS_MACHINE);
1889 } else if (!strcmp(data_type, "string")) {
1891 ## range of s is strings
1892 ## repeat retrieve (id = s.string_id, refc = s.#refc)
1893 ## where s.string = @name
1894 ## inquire_equel (rowcount = "rowcount")
1895 if (rowcount == 0) {
1896 if (q->type != APPEND) return(SMS_STRING);
1897 ## range of v is values
1898 ## retrieve (id = v.value) where v.#name = "strings_id"
1900 ## replace v (value = id) where v.#name = "strings_id"
1901 ## append to strings (string_id = id, string = name, #refc = 1)
1902 } else if (rowcount == 1) {
1903 if (q->type == APPEND || q->type == DELETE) {
1904 refc += (q->type == APPEND) ? 1 : -1;
1906 ## replace s (#refc = refc) where s.string_id = id
1908 ## delete s where s.string_id = id
1916 /* now set value in argv */
1917 *(int *)argv[vo->index] = id;
1919 return (SMS_EXISTS);
1923 translate_ids(q, sq, v, action, actarg)
1924 register struct query *q;
1925 register struct save_queue *sq;
1926 register struct validate *v;
1927 register int (*action)();
1931 ## char *field_type;
1932 ## char data_type[17];
1939 for (i = 0; i < v->objcnt; i++) {
1941 if (vo->type == V_FOLLOWUP) break;
1945 while (sq_get_data(sq, &argv)) {
1949 sscanf(argv[i], "%d", &id);
1951 name = (char *)malloc(129);
1954 /* get field type string (known to be at index-1) */
1955 field_type = argv[vo->index-1];
1957 /* get corresponding data type associated with field type name */
1958 ## repeat retrieve (data_type = alias.trans)
1959 ## where alias.#name = @field_type and alias.type = "TYPEDATA"
1960 ## inquire_equel (rowcount = "rowcount")
1961 if (rowcount != 1) {
1962 sprintf(name, "%d", id);
1963 (*action)(q->vcnt, argv, actarg);
1967 /* retrieve object name */
1969 if (!strcmp(data_type, "user")) {
1971 ## repeat retrieve (name = users.login) where users.users_id = @id
1972 ## inquire_equel (rowcount = "rowcount")
1974 } else if (!strcmp(data_type, "list")) {
1976 ## repeat retrieve (name = list.#name) where list.list_id = @id
1977 ## inquire_equel (rowcount = "rowcount")
1979 } else if (!strcmp(data_type, "machine")) {
1981 ## repeat retrieve (name = machine.#name) where machine.mach_id = @id
1982 ## inquire_equel (rowcount = "rowcount")
1984 } else if (!strcmp(data_type, "string")) {
1986 ## repeat retrieve (name = strings.string)
1987 ## where strings.string_id = @id
1988 ## inquire_equel (rowcount = "rowcount")
1994 /* if there wasn't a corresponding object name, then use the id */
1995 if (rowcount != 1) sprintf(name, "%d", id);
1998 (*action)(q->vcnt, argv, actarg);
2000 /* free saved data */
2001 for (i = 0; i < q->vcnt; i++)
2007 return (SMS_SUCCESS);
2014 * c-continued-statement-offset: 4
2015 * c-brace-offset: -4
2016 * c-argdecl-indent: 4
2017 * c-label-offset: -4