6 * Copyright (C) 1987 by the Massachusetts Institute of Technology
9 * Revision 1.13 1987-09-01 16:24:01 wesommer
10 * A list should be considered modified if its acl changes.
12 Revision 1.12 87/08/29 00:05:54 mike
13 Fixed bug in check_nfs.
14 Added code to upcasify machine names in validate_id.
16 Revision 1.11 87/08/28 14:55:45 mike
17 Modified delete_locker to require only one argument, the login name.
18 Modified get_groups_of_all_users and get_all_poboxes to disable INGRES
21 Revision 1.10 87/08/25 15:56:54 mike
22 - Fixed bugs in get_groups_of_all_users
23 - Added tblstats updates to add_user_group
24 - Added routines: add_hostaccess (ashi), delete_hostaccess (dshi),
25 followup_ushp, and followup_usha
27 Revision 1.9 87/08/22 17:41:34 wesommer
28 More of Mike's changes.
30 Revision 1.8 87/08/18 15:05:20 wesommer
31 Fixed definition of add_locker.
33 Revision 1.7 87/08/04 01:49:41 wesommer
36 Revision 1.6 87/08/04 01:10:02 wesommer
37 Changes by mike; checked in prior to my hacking.
39 Revision 1.5 87/07/30 14:54:13 wesommer
40 Added debugging code in an attempt to catch a flakey problem.
42 Revision 1.4 87/07/30 00:30:21 wesommer
43 replaced appends = appends+1 with appends = tbs.appends+1
45 Revision 1.3 87/07/30 00:26:11 wesommer
46 Changes by mike prior to "appends" fix.
48 Revision 1.2 87/07/29 16:00:39 wesommer
51 Revision 1.1 87/07/29 15:13:57 wesommer
57 static char *rcsid_qsupport_qc = "$Header$";
61 #include "sms_server.h"
68 /* Specialized Access Routines */
71 ** access_user - verify that client name equals specified login name
73 ** Used by: update_user_shell
74 ** update_finger_by_login
76 ** - since field validation routines are called first, a users_id is
77 ** now in argv[0] instead of the login name. Therefore, we must
78 ** convert the client name to a users_id.
81 access_user(q, argv, cl)
86 register struct krbname *krb;
91 client_name = cl->kname.name;
92 ## repeat retrieve (client_id = users.users_id)
93 ## where users.login = @client_name
94 ## inquire_equel (rowcount = "rowcount")
95 if (rowcount != 1) return(SMS_PERM);
96 if (client_id != *(int *)argv[0]) return(SMS_PERM);
102 ** access_pop - same as access_user plus verifies that a user has only one
103 ** mailbox of type "POP"
106 ** argv[0] - users_id
112 ** - if q->name = "add_pobox" and type = "POP",
113 ** verify that no POP box already exists for user
114 ** - call access_user
118 access_pop(q, argv, cl)
128 if (!bcmp(q->name, "add_pobox", 10) && !bcmp(argv[1], "POP", 4)) {
129 users_id = *(int *)argv[0];
130 mach_id = *(int *)argv[2];
132 ## range of p is pobox
133 ## repeat retrieve (exists = any(p.#box where p.#users_id = @users_id
134 ## and p.type = "POP"
135 ## and p.#mach_id = @mach_id
136 ## and p.#box = @box))
137 if (exists) return(SMS_EXISTS);
140 return(access_user(q, argv, cl));
144 ** access_list - check access for adding or deleting list members
146 ** Inputs: argv[0] - list_id
147 ** cl->krb.name - client name
149 ** - check that client is a member of the access control list
150 ** - OR, if q->shortname == {amtl | dfml} and
151 ** if list.flags & LF_PUBLIC, allow access if client = member
155 access_list(q, argv, cl)
169 list_id = *(int *)argv[0];
170 ## repeat retrieve (acl_id = list.#acl_id, flags = list.#flags)
171 ## where list.#list_id = @list_id
173 /* parse client structure */
174 status = get_client(cl, &client_type, &client_id);
175 if (status != SMS_SUCCESS) return(status);
177 /* if amtl or dmfl and list is public allow client to add or delete self */
178 if (!bcmp("amtl", q->shortname, 4) || !bcmp("dmfl", q->shortname, 4)) {
179 if ((flags & LF_PUBLIC) && !bcmp("USER", argv[1], 4)) {
180 member_id = *(int *)argv[2];
181 if (member_id == client_id) return(SMS_SUCCESS);
185 /* check for client in access control list */
186 exists = find_member(acl_id, client_type, client_id, 0);
187 if (!exists) return(SMS_PERM);
193 ** access_maillist - access_list + disallow adding user-group to maillists
200 access_maillist(q, argv, cl)
207 ## char list_name[32];
210 status = access_list(q, argv, cl);
211 if (status != SMS_SUCCESS) return(status);
212 if (bcmp(q->name, "add_maillist", 12)) return(status);
214 list_id = *(int *)argv[0];
215 ## range of g is groups
216 ## repeat retrieve (exists = any(g.#list_id where g.#list_id = @list_id))
217 if (!exists) return(SMS_SUCCESS);
218 ## repeat retrieve (list_name = list.name) where list.#list_id = @list_id
219 ## repeat retrieve (exists = any(users.login where users.login = @list_name))
220 return ((exists) ? SMS_USER_GROUP : SMS_SUCCESS);
224 ** Setup routine for add_group
228 ** Description: allocate next gid and store in values table
232 setup_add_group(q, argv, cl, access_check)
242 status = access_list(q, argv, cl);
244 if (status != SMS_SUCCESS || access_check) return(status);
246 ## range of g is groups
247 ## range of v is values
248 ## repeat retrieve (ngid = v.value) where v.name = "gid"
252 ## repeat retrieve (exists = any(g.#gid where g.#gid = @ngid))
255 ## repeat replace v (value = @ngid) where v.name = "gid"
260 ** Setup routine for add_user
262 ** Inputs: argv[0] - login
267 ** - if argv[1] == "#" then set argv[1] = next(uid)
268 ** - if argv[0] == "#" then set argv[0] = "#<uid>"
272 setup_add_user(q, argv, cl, access_check)
274 register char *argv[];
281 if (access_check) return(SMS_SUCCESS);
283 if (!bcmp(argv[1], "#", 2)) {
284 ## range of u is users
285 ## range of v is values
286 ## repeat retrieve (nuid = v.value) where v.name = "uid"
290 ## repeat retrieve (exists = any(u.#uid where u.#uid = @nuid))
292 ## repeat replace v (value = @nuid) where v.name = "uid"
293 sprintf(argv[1], "%d", nuid);
296 if (!bcmp(argv[0], "#", 2)) {
297 sprintf(argv[0], "#%s", argv[1]);
304 ** followup_add_user - add finger entry, set_user_modtime
305 ** followup_delete_user - delete finger entry
308 ** argv[0] - login (add_user)
309 ** argv[0] - users_id (delete_user)
313 followup_add_user(q, argv)
322 ## char fullname[128];
328 /* get user information */
329 ## range of u is users
330 ## repeat retrieve (users_id = u.#users_id, last = u.#last,
331 ## first = u.#first, middle = u.#middle)
332 ## where u.#login = @login
337 while (*cp1) *cp2++ = *cp1++;
340 if (*cp1 == 0) cp2--;
341 while (*cp1) *cp2++ = *cp1++;
344 while (*cp2++ = *cp1++) ;
346 /* create a finger entry */
347 ## repeat append finger (#users_id = @users_id, #fullname = @fullname)
349 /* set modtime (creation time) on user */
350 ## repeat replace u (modtime = "now") where u.#users_id = @users_id
355 followup_delete_user(q, argv)
361 users_id = *(int *)argv[0];
362 ## repeat delete finger where finger.#users_id = @users_id
367 ** setup_add_filesys - verify existance of referenced file systems
368 ** setup_update_filesys - same, except argv[1..5] --> argv[2..6]
370 ** Inputs: Add Update
371 ** argv[0] - label label
372 ** argv[1] - type new label
373 ** argv[2] - mach_id type
374 ** argv[3] - name mach_id
375 ** argv[4] - mount name
376 ** argv[5] - access mount
381 ** * verify mach_id/name in rvdvirt
382 ** * verify access in {r, x, R, X}
384 ** * extract directory prefix from name
385 ** * verify mach_id/dir in nfsphys
386 ** * verify access in {r, w, R, W}
389 ** SMS_RVD - no such rvd
390 ** SMS_NFS - specified directory not exported
391 ** SMS_FILESYS_ACCESS - invalid filesys access
395 setup_add_filesys(q, argv)
405 mach_id = *(int *)argv[2];
409 if (!bcmp(type, "RVD", 3))
410 return (check_rvd(mach_id, name, access));
411 else if (!bcmp(type, "NFS", 3))
412 return (check_nfs(mach_id, name, access));
417 setup_update_filesys(q, argv)
427 mach_id = *(int *)argv[3];
431 if (!bcmp(type, "RVD", 3))
432 return (check_rvd(mach_id, name, access));
433 else if (!bcmp(type, "NFS", 3))
434 return (check_nfs(mach_id, name, access));
439 ##check_rvd(mach_id, name, access)
447 ## range of rv is rvdvirt
448 ## retrieve (rowcount = any(rv.#name where rv.#mach_id = mach_id and
450 if (rowcount == 0) return(SMS_RVD);
452 caccess = (isupper(*access)) ? tolower(*access) : *access;
453 if (caccess != 'r' && caccess != 'x') return(SMS_FILESYS_ACCESS);
458 ##check_nfs(mach_id, name, access)
470 caccess = (isupper(*access)) ? tolower(*access) : *access;
471 if (caccess != 'r' && caccess != 'w') return(SMS_FILESYS_ACCESS);
474 ## range of np is nfsphys
475 ## retrieve (dir = np.#dir) where np.#mach_id = mach_id
480 if (*cp1++ != *cp2) break;
484 status = SMS_SUCCESS;
492 /* Followup Routines */
494 set_user_modtime(q, argv)
501 ## repeat replace u (modtime = "now") where u.#login = @login
505 set_user_modtime_by_id(q, argv)
511 users_id = *(int *)argv[0];
512 ## repeat replace users (modtime = "now") where users.#users_id = @users_id
516 set_list_modtime(q, argv)
523 ## repeat replace list (modtime = "now") where list.name = @list_name
527 set_list_modtime_by_id(q, argv)
533 list_id = *(int *)argv[0];
534 ## repeat replace list (modtime = "now") where list.#list_id = @list_id
535 ## repeat replace list (modtime = "now") where list.#acl_id = @list_id
539 set_finger_modtime(q, argv)
545 users_id = *(int *)argv[0];
546 ## repeat replace f (modtime = "now") where f.#users_id = @users_id
551 ** followup_amtl - followup for amtl and dmfl; when adding a list
552 ** member to a maillist, add list to maillist table,
553 ** unless list is a user-group.
554 ** Then set_list_modtime_by_id.
558 ** argv[1] - member_type
559 ** argv[2] - member_id
563 followup_amtl(q, argv)
570 ## char list_name[33];
572 list_id = *(int *)argv[0];
574 ## repeat replace list (modtime = "now") where list.#list_id = @list_id
575 ## repeat replace list (modtime = "now") where list.#acl_id = @list_id
577 /* if query is not amtl or if member_type is not LIST then return */
578 if (bcmp(q->shortname, "amtl", 4) || bcmp(argv[1], "LIST", 4))
581 member_id = *(int *)argv[2];
582 ## range of l is list
583 ## range of ml is maillists
584 ## range of g is groups
586 /* is parent list a mailing list? */
587 ## repeat retrieve (exists = any(ml.#list_id where ml.#list_id=@list_id))
589 /* if not then return */
590 if (!exists) return(SMS_SUCCESS);
592 /* is member_list a user-group? */
594 ## repeat retrieve (exists = any(g.#list_id where g.#list_id = @member_id))
597 ## repeat retrieve (list_name = l.#name) where l.#list_id = @member_id
598 /* is list_name a username? */
599 ## repeat retrieve (exists = any(users.login
600 ## where users.login = @list_name))
601 /* yes, return error */
602 if (exists) return(SMS_USER_GROUP);
605 /* list is not a user-group; add list to maillist table */
606 ## repeat append maillists (#list_id = @member_id, ltid = l.tid)
607 ## where l.#list_id = @member_id
613 ** followup_add_pobox
614 ** followup_delete_pobox - followup routines for pobox queries
617 ** add_pobox: set pobox creation time
618 ** increment pop usage in serverhosts
620 ** delete_pobox: decrement pop usage in serverhosts
624 followup_add_pobox(q, argv)
628 set_pobox_creation(q, argv);
629 set_pop_usage(q, argv, 1);
633 followup_delete_pobox(q, argv)
637 set_pop_usage(q, argv, -1);
641 set_pobox_creation(q, argv)
650 users_id = *(int *)argv[0];
652 mach_id = *(int *)argv[2];
655 ## range of p is pobox
656 ## repeat replace p (created = "now")
657 ## where p.#users_id = @users_id and p.#type = @type and
658 ## p.#mach_id = @mach_id and p.#box = @box
660 return (SMS_SUCCESS);
664 ** set_pop_usage - incr/decr usage count for pop server in serverhosts talbe
667 ** q->name - "add_pobox" or "delete_pobox"
672 ** - incr/decr value field in serverhosts table for pop/mach_id
676 set_pop_usage(q, argv, count)
683 if (bcmp(argv[1], "POP", 3)) return(SMS_SUCCESS);
685 mach_id = *(int *)argv[2];
688 ## range of sh is serverhosts
689 ## repeat replace sh (value1 = sh.value1 + @n)
690 ## where sh.service = "pop" and sh.#mach_id = @mach_id
696 ** delete_user_poboxes - delete all poboxes for a user
699 ** argv[0] - users_id
703 delete_user_poboxes(q, argv)
713 users_id = *(int *)argv[0];
715 /* get machine ids for pop server(s) on which the user currently exists */
716 ## range of p is pobox
718 ## repeat retrieve (mach_id = p.#mach_id)
719 ## where p.#users_id = @users_id and p.type = "POP"
721 mach_ids[i++] = mach_id;
727 /* decrement counts on serverhost entries */
728 ## range of sh is serverhosts
730 mach_id = mach_ids[i];
731 ## repeat replace sh (value1 = sh.value1 - 1)
732 ## where sh.service = "pop" and sh.#mach_id = @mach_id
735 /* delete user's poboxes */
736 ## repeat delete p where p.#users_id = @users_id
744 ** delete_current_quota - adjust nfsphys values on xxx_quota queries.
749 ** argv[2] - users_id
750 ** argv[3] - quota (add_new_quota only)
753 ** delete_current_quota:
754 ** - find nfsquota entry
755 ** - decrement nfsphys.allocated by nfsquota.quota
757 ** - increment nfsphys.allocated by quota
761 add_new_quota(q, argv)
763 register char *argv[];
769 mach_id = *(int*)argv[0];
771 quota = *(int *)argv[3];
773 ## range of np is nfsphys
774 ## repeat replace np (allocated = np.allocated + @quota)
775 ## where np.#mach_id = @mach_id and np.#device = @device
780 delete_current_quota(q, argv, cl, access_check)
782 register char *argv[];
791 if (access_check) return(SMS_SUCCESS);
793 mach_id = *(int *)argv[0];
795 users_id = *(int *)argv[2];
797 ## range of np is nfsphys
798 ## range of nq is nfsquota
799 ## repeat retrieve (quota = nq.#quota)
800 ## where nq.#mach_id = @mach_id and nq.#device = @device and
801 ## nq.#users_id = @users_id
802 ## repeat replace np (allocated = np.allocated - @quota)
803 ## where np.#mach_id = @mach_id and np.#device = @device
809 ** add_hostaccess - create entry in hostaccess table upon adding a new
810 ** machine to the serverhosts table where service =
819 add_hostaccess(q, argv)
825 /* only work with service = "hostaccess" */
826 if (bcmp(argv[0], "hostaccess", 10)) return(SMS_SUCCESS);
828 mach_id = *(int *)argv[1];
829 ## repeat append hostaccess (#mach_id = @mach_id, status = 0)
830 ## repeat replace tblstats (modtime = "now", appends = tblstats.appends + 1)
831 ## where tblstats.table = "hostaccess"
835 /* followup to delete_server_host_info */
837 delete_hostaccess(q, argv)
843 /* only work with service = "hostaccess" */
844 if (bcmp(argv[0], "hostaccess", 10)) return(SMS_SUCCESS);
846 mach_id = *(int *)argv[1];
847 ## repeat delete hostaccess where hostaccess.#mach_id = @mach_id
848 ## repeat replace tblstats (modtime = "now", deletes = tblstats.deletes + 1)
849 ## where tblstats.table = "hostaccess"
853 followup_ushp(q, argv)
860 mach_id = *(int *)argv[0];
861 ## range of ha is hostaccess
862 ## repeat retrieve (status = ha.#status) where ha.#mach_id = @mach_id
864 ## repeat replace ha (#status = @status) where ha.#mach_id = @mach_id
868 followup_usha(q, argv)
875 mach_id = *(int *)argv[0];
876 ## range of ha is hostaccess
877 ## repeat retrieve (status = ha.#status) where ha.#mach_id = @mach_id
879 ## repeat replace ha (#status = @status) where ha.#mach_id = @mach_id
884 ** delete_list_members - called after the delete_list query to clean up
887 ** Inputs: argv[0] - list_id
890 ** - foreach string member: decr string refc; ifzero, delete string
891 ** - delete all members entries for this list_id
895 delete_list_members(q, argv)
897 register char *argv[];
903 struct save_queue *sq;
904 struct save_queue *sq_create();
906 list_id = *(int *)argv[0];
909 ## range of m is members
910 ## repeat retrieve (string_id = m.member_id)
911 ## where m.#list_id = @list_id and m.member_type = "STRING"
913 sq_save_data(sq, string_id);
916 while (sq_get_data(sq, &string_id)) {
917 ## range of s is strings
918 ## repeat retrieve (refc = s.#refc) where s.#string_id = @string_id
919 ## inquire_equel (rowcount = "rowcount")
920 if (rowcount == 0) continue;
922 ## repeat delete s where s.#string_id = @string_id
924 ## repeat replace s (#refc = @refc) where s.#string_id = @string_id
929 ## repeat delete m where m.#list_id = @list_id
935 ** followup_grvd - Support routine for get_rvd_servers query
938 ** q - grvd query structure
939 ** sq - save_queue struture: contains list of {machine, oper_acl_id,
940 ** admin_acl_id, shutdown_acl_id} records.
941 ** v - validate structure (not used)
942 ** action - action routine
943 ** actarg - action routine argument
946 ** - translate acl_ids to list names
950 followup_grvd(q, sq, v, action, actarg)
952 struct save_queue *sq;
961 ## char shutdown[33];
968 ## range of l is list
970 while (sq_get_data(sq, &argv)) {
971 sscanf(argv[0], "%d", &list_id);
972 ## repeat retrieve (oper = l.name) where l.#list_id = @list_id
973 sscanf(argv[1], "%d", &list_id);
974 ## repeat retrieve (admin = l.name) where l.#list_id = @list_id
975 sscanf(argv[2], "%d", &list_id);
976 ## repeat retrieve (shutdown = l.name) where l.#list_id = @list_id
978 (*action)(3, targv, actarg);
988 followup_gars(q, sq, v, action, actarg)
990 struct save_queue *sq;
999 ## char shutdown[33];
1004 targv[3] = shutdown;
1006 ## range of l is list
1008 while (sq_get_data(sq, &argv)) {
1009 sscanf(argv[1], "%d", &list_id);
1010 ## repeat retrieve (oper = l.name) where l.#list_id = @list_id
1011 sscanf(argv[2], "%d", &list_id);
1012 ## repeat retrieve (admin = l.name) where l.#list_id = @list_id
1013 sscanf(argv[3], "%d", &list_id);
1014 ## repeat retrieve (shutdown = l.name) where l.#list_id = @list_id
1017 (*action)(4, targv, actarg);
1025 return(SMS_SUCCESS);
1029 ** set_next_object_id - set next object id in values table
1031 ** Inputs: object - object name in values table
1033 ** - called before an APPEND operation to set the next object id to
1034 ** be used for the new record
1038 set_next_object_id(object)
1044 ## range of v is values
1045 ## repeat replace v (value = v.value + 1) where v.#name = @name
1046 return(SMS_SUCCESS);
1050 ** get_query_need - check modtime of query's associated table against given
1051 ** time and return true if greater (false if not)
1054 ** argv[0] - query name
1055 ** argv[1] - time to compare against
1059 get_query_need(q, argv, action, actarg)
1061 register char *argv[];
1065 ## char *last_get_time;
1069 struct query *get_query_by_name();
1071 q1 = get_query_by_name(argv[0]);
1073 last_get_time = argv[1];
1076 if (q1->type != RETRIEVE) return(SMS_NO_MATCH);
1078 ## range of tbs is tblstats
1079 ## repeat retrieve (need = any(tbs.modtime where tbs.#table = @table and
1080 ## tbs.modtime > @last_get_time))
1082 result = (need) ? "true" : "false";
1083 (*action)(1, &result, actarg);
1084 return(SMS_SUCCESS);
1088 ** get_list_is_group
1089 ** get_list_is_maillist
1092 ** argv[0] - list_id
1099 get_list_is_group(q, argv, action, actarg)
1109 list_id = *(int *)argv[0];
1111 ## range of g is groups
1112 ## repeat retrieve (exists = any(g.#list_id where g.#list_id = @list_id))
1114 result = (exists) ? "true" : "false";
1115 (*action)(1, &result, actarg);
1116 return(SMS_SUCCESS);
1119 get_list_is_maillist(q, argv, action, actarg)
1129 list_id = *(int *)argv[0];
1131 ## range of ml is maillists
1132 ## repeat retrieve (exists = any(ml.#list_id where ml.#list_id = @list_id))
1134 result = (exists) ? "true" : "false";
1135 (*action)(1, &result, actarg);
1136 return(SMS_SUCCESS);
1141 ** add_locker - special query routine for creating a user locker
1144 ** argv[0] - users_id
1145 ** argv[1] - machine_id
1147 ** argv[3] - initial quota
1150 ** - get prefix directory (dir) for mount point on specified machine/device
1151 ** - create filesys entry (label=<login>, type=NFS, machine=<machine>,
1152 ** mount=<dir>/<login>, access=w, acl=dbadmin)
1153 ** - increment allocated in nfsphys by quota
1154 ** - create nfsquota entry
1157 ** - SMS_NFSPHYS - machine/device does not exist in nfsphys
1158 ** - SMS_FILESYS_EXISTS - file system already exists
1163 register struct query *q;
1178 /* copy arguments */
1179 users_id = *(int *)argv[0];
1180 mach_id = *(int *)argv[1];
1182 sscanf(argv[3], "%d", "a);
1184 ## range of u is users
1185 ## range of f is filesys
1186 ## range of np is nfsphys
1187 ## range of tbs is tblstats
1189 /* get login name */
1190 ## repeat retrieve (login = u.#login) where u.#users_id = @users_id
1192 /* get user's acl id */
1193 ## repeat retrieve (user_acl = list.list_id) where list.name = @login
1195 /* get filesystem directory prefix; give error if machine/device
1196 pair not in nfsphys table */
1197 printf("np.mach_id = %d and np.device = %s\n", mach_id, device);
1199 ## repeat retrieve (dir = np.#dir, allocated = np.#allocated)
1200 ## where np.#mach_id = @mach_id and np.#device = @device
1201 ## inquire_equel (rowcount = "rowcount")
1202 if (rowcount == 0) return(SMS_NFSPHYS);
1204 /* make sure a filesys with user's name does not already exist */
1205 ## repeat retrieve (rowcount = any(f.label where f.label = @login))
1206 if (rowcount != 0) return(SMS_FILESYS_EXISTS);
1208 /* create a new filesys */
1209 sprintf(locker, "%s/%s", dir, login);
1210 sprintf(mount, "/mit/%s", login);
1211 ## repeat append filesys
1212 ## (#label = @login, type = "NFS", #mach_id = @mach_id,
1213 ## name = @locker, access = "w", order = 1, #mount = @mount,
1214 ## acl_id = @user_acl)
1215 ## repeat replace tbs (appends = tbs.appends + 1, modtime = "now")
1216 ## where tbs.table = "filesys"
1218 /* increment usage count in nfsphys table */
1220 ## replace np (#allocated = allocated)
1221 ## where np.#mach_id = mach_id and np.#device = device
1222 ## repeat replace tbs (updates = tbs.updates + 1, modtime = "now")
1223 ## where tbs.table = "nfsphys"
1225 /* create nfsquota entry */
1226 ## append nfsquota (#users_id = users_id, #mach_id = mach_id,
1227 ## #device = device, #quota = quota)
1228 ## repeat replace tbs (appends = tbs.appends + 1, modtime = "now")
1229 ## where tbs.table = "nfsquota"
1231 return(SMS_SUCCESS);
1235 ** delete_locker - special query routine for deleting a user locker
1238 ** argv[0] - users_id
1241 ** - get login name from users_id
1242 ** - get filesys entry from login
1243 ** - use filesys.mach_id and filesys.name to determine machine/device
1244 ** pair for nfsphys and nfsquota
1245 ** - delete filesys entry (label=<login>)
1246 ** - decrement allocated in nfsphys by quota
1247 ** - delete nfsquota entry
1250 ** - SMS_FILESYS - no filesys exists for user
1254 delete_locker(q, argv)
1255 register struct query *q;
1256 register char *argv[];
1267 /* copy arguments */
1268 users_id = *(int *)argv[0];
1270 ## range of u is users
1271 ## range of f is filesys
1272 ## range of np is nfsphys
1273 ## range of nq is nfsquota
1274 ## range of tbs is tblstats
1276 /* get login name */
1277 ## repeat retrieve (login = u.#login) where u.#users_id = @users_id
1279 /* get mach_id and locker name from filesys entry; then delete it */
1280 ## repeat retrieve (mach_id = f.#mach_id, lname = f.#name)
1281 ## where f.#label = @login
1282 ## inquire_equel (rowcount = "rowcount")
1283 if (rowcount == 0) return(SMS_FILESYS);
1284 ## repeat delete f where f.#label = @login
1286 /* get prefix directory */
1287 c = (char *)rindex(lname, '/');
1290 /* get nfs device */
1291 ## repeat retrieve (ndev = np.device)
1292 ## where np.#mach_id = @mach_id and np.dir = @lname
1294 /* get quota from nfsquota entry; then delete entry */
1295 ## repeat retrieve (quota = nq.#quota)
1296 ## where nq.#mach_id = @mach_id and nq.#device = @ndev and
1297 ## nq.#users_id = @users_id
1298 ## repeat delete nq where nq.#mach_id = @mach_id and nq.#device = @ndev and
1299 ## nq.#users_id = @users_id
1301 /* decrement nfsphys.allocated */
1302 ## repeat replace np (allocated = np.allocated - @quota)
1303 ## where np.#mach_id = @mach_id and np.#device = @ndev
1305 /* adjust table statistics */
1306 ## repeat replace tbs (deletes = tbs.deletes + 1, modtime = "now")
1307 ## where tbs.table = "filesys"
1308 ## repeat replace tbs (updates = tbs.updates + 1, modtime = "now")
1309 ## where tbs.table = "nfsphys"
1310 ## repeat replace tbs (deletes = tbs.deletes + 1, modtime = "now")
1311 ## where tbs.table = "nfsquota"
1313 return(SMS_SUCCESS);
1317 ** add_user_group - create a group for a user and add user to group
1323 ** - verify specified user exists
1324 ** - create a list of same name as user
1325 ** - add user as a member of the list
1329 add_user_group(q, argv)
1341 /* verify user exists */
1342 ## repeat retrieve (users_id = users.#users_id) where users.#login = @login
1343 ## inquire_equel (exists = "rowcount")
1344 if (exists != 1) return(SMS_USER);
1346 /* verify list does not exist */
1347 ## repeat retrieve (exists = any(list.name where list.name = @login))
1348 if (exists) return(SMS_LIST);
1350 /* get new list_id */
1351 ## repeat retrieve (list_id = values.value) where values.name = "list_id"
1353 ## repeat replace values (value = @list_id) where values.name = "list_id"
1355 /* create the list */
1356 ## range of tbs is tblstats
1357 ## repeat append list (name = @login, #list_id = @list_id, flags = 1,
1358 ## desc = "User Group", acl_id = @list_id,
1359 ## expdate = "today" + "5 years", modtime = "now")
1360 ## repeat replace tbs (modtime = "now", appends = tbs.appends + 1)
1361 ## where tbs.table = "list"
1363 /* add user to list */
1364 ## repeat append members (#list_id = @list_id, member_type = "USER",
1365 ## member_id = @users_id)
1366 ## repeat replace tbs (modtime = "now", appends = tbs.appends + 1)
1367 ## where tbs.table = "members"
1370 ## range of g is groups
1371 ## range of v is values
1372 ## repeat retrieve (gid = v.value) where v.name = "gid"
1376 ## repeat retrieve (exists = any(g.#gid where g.#gid = @gid))
1378 ## repeat replace v (value = @gid) where v.name = "gid"
1380 /* add list to group table */
1381 ## repeat append groups (#list_id = @list_id, ltid = list.tid, #gid = @gid)
1382 ## where list.#list_id = @list_id
1383 ## repeat replace tbs (modtime = "now", appends = tbs.appends + 1)
1384 ## where tbs.table = "members"
1386 /* and we're done */
1387 return(SMS_SUCCESS);
1392 ** get_members_of_list - optimized query for retrieval of list members
1395 ** argv[0] - list_id
1398 ** - retrieve USER members, then LIST members, then STRING members
1402 get_members_of_list(q, argv, action, actarg)
1409 ## char member_name[129];
1412 list_id = *(int *)argv[0];
1414 targv[1] = member_name;
1416 ## range of m is members
1417 ## repeat retrieve (member_name = users.login)
1418 ## where m.#list_id = @list_id and m.member_type = "USER"
1419 ## and m.member_id = users.users_id
1420 ## sort by #member_name
1422 (*action)(2, targv, actarg);
1426 ## repeat retrieve (member_name = list.name)
1427 ## where m.#list_id = @list_id and m.member_type = "LIST"
1428 ## and m.member_id = list.#list_id
1429 ## sort by #member_name
1431 (*action)(2, targv, actarg);
1434 targv[0] = "STRING";
1435 ## repeat retrieve (member_name = strings.string)
1436 ## where m.#list_id = @list_id and m.member_type = "STRING"
1437 ## and m.member_id = strings.string_id
1438 ## sort by #member_name
1440 (*action)(2, targv, actarg);
1443 return(SMS_SUCCESS);
1447 ** get_groups_of_user - optimized query for retrieval of all groups to
1448 ** which a user belongs
1452 get_groups_of_user(q, argv, action, actarg)
1459 ## char list_name[33];
1464 users_id = *(int *)argv[0];
1465 targv[0] = list_name;
1468 ## range of m is members
1470 ## repeat retrieve (list_name = list.name, gid = text(groups.#gid))
1471 ## where m.member_id = @users_id and m.member_type = "USER" and
1472 ## m.list_id = groups.list_id and groups.ltid = list.tid
1473 ## sort by #list_name
1475 (*action)(2, targv, actarg);
1477 ## inquire_equel (rowcount = "rowcount")
1479 return ((rowcount = 0) ? SMS_NO_MATCH : SMS_SUCCESS);
1482 get_groups_of_all_users(q, argv, action, actarg)
1498 ## range of u is users
1499 ## range of l is list
1500 ## range of m is members
1501 ## range of g is groups
1503 ## set lockmode session where readlock = nolock
1505 ## repeat retrieve (login = u.#login, group = l.name, gid = text(g.#gid))
1506 ## where m.member_type = "USER" and m.member_id = u.users_id and
1507 ## u.status != 0 and m.list_id = g.list_id and
1509 ## sort by #login, #group
1511 (*action)(3, targv, actarg);
1514 ## inquire_equel (errorno = "errorno")
1515 ## set lockmode session where readlock = system
1517 return((errorno) ? SMS_INGRES_ERR : SMS_SUCCESS);
1521 ** get_all_poboxes - optimized query for retrieval of all poboxes
1524 ** - retrieve LOCAL boxes, then POP boxes, then FOREIGN boxes
1528 get_all_poboxes(q, argv, action, actarg)
1535 ## char machine[129];
1545 ## set lockmode session where readlock = nolock
1546 ## range of p is pobox
1547 ## repeat retrieve (login=users.#login, machine = #machine.name, box=p.#box)
1548 ## where p.type = "LOCAL" and p.users_id = users.users_id
1549 ## and p.mach_id = #machine.mach_id
1551 (*action)(4, targv, actarg);
1555 ## repeat retrieve (login=users.#login, machine = #machine.name, box=p.#box)
1556 ## where p.type = "POP" and p.users_id = users.users_id
1557 ## and p.mach_id = #machine.mach_id
1559 (*action)(4, targv, actarg);
1562 targv[1] = "FOREIGN";
1563 ## repeat retrieve (login=users.#login, machine=strings.string, box=p.#box)
1564 ## where p.type = "FOREIGN" and p.users_id = users.users_id
1565 ## and p.mach_id = strings.string_id
1567 (*action)(4, targv, actarg);
1569 ## set lockmode session where readlock = system
1571 return(SMS_SUCCESS);
1574 get_new_poboxes(q, argv, action, actarg)
1582 ## char machine[129];
1593 ## range of p is pobox
1594 ## repeat retrieve (login=users.#login, machine = #machine.name, box=p.#box)
1595 ## where p.type = "LOCAL" and p.users_id = users.users_id
1596 ## and p.mach_id = #machine.mach_id and
1597 ## p.#created > @created
1599 (*action)(4, targv, actarg);
1603 ## repeat retrieve (login=users.#login, machine = #machine.name, box=p.#box)
1604 ## where p.type = "POP" and p.users_id = users.users_id
1605 ## and p.mach_id = #machine.mach_id and
1606 ## p.#created > @created
1608 (*action)(4, targv, actarg);
1611 targv[1] = "FOREIGN";
1612 ## repeat retrieve (login=users.#login, machine=strings.string, box=p.#box)
1613 ## where p.type = "FOREIGN" and p.users_id = users.users_id
1614 ## and p.mach_id = strings.string_id and
1615 ## p.#created > @created
1617 (*action)(4, targv, actarg);
1620 return(SMS_SUCCESS);
1623 /* Validation Routines */
1625 validate_row(q, argv, v)
1626 register struct query *q;
1628 register struct validate *v;
1636 /* build where clause */
1637 build_qual(v->qual, v->argc, argv, qual);
1639 /* setup ingres variables */
1644 if (log_flags & LOG_RES)
1645 /* tell the logfile what we're doing */
1646 com_err(whoami, 0, "validating row: %s", qual);
1648 /* look for the record */
1649 ## range of rvar is table
1650 ## retrieve (rowcount = count(rvar.name where qual))
1651 if (rowcount == 0) return(SMS_NO_MATCH);
1652 if (rowcount > 1) return(SMS_NOT_UNIQUE);
1656 validate_fields(q, argv, vo, n)
1658 register char *argv[];
1659 register struct valobj *vo;
1662 register int status;
1667 if (log_flags & LOG_RES)
1668 com_err(whoami, 0, "validating %s in %s: %s",
1669 vo->namefield, vo->table, argv[vo->index]);
1670 status = validate_name(argv, vo);
1674 if (log_flags & LOG_RES)
1675 com_err(whoami, 0, "validating %s in %s: %s",
1676 vo->idfield, vo->table, argv[vo->index]);
1677 status = validate_id(argv, vo);
1681 if (log_flags & LOG_RES)
1682 com_err(whoami, 0, "validating date: %s", argv[vo->index]);
1683 status = validate_date(argv, vo);
1687 if (log_flags & LOG_RES)
1688 com_err(whoami, 0, "validating %s type: %s",
1689 vo->table, argv[vo->index]);
1690 status = validate_type(argv, vo);
1694 if (log_flags & LOG_RES)
1695 com_err(whoami, 0, "validating typed data (%s): %s",
1696 argv[vo->index - 1], argv[vo->index]);
1697 status = validate_typedata(q, argv, vo);
1701 status = SMS_EXISTS;
1705 status = SMS_EXISTS;
1710 if (status != SMS_EXISTS) return(status);
1714 return(SMS_SUCCESS);
1717 validate_id(argv, vo)
1719 register struct valobj *vo;
1729 name = argv[vo->index];
1731 /* minor kludge to upcasify machine names */
1732 if (!bcmp(table, "machine", 7))
1733 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
1734 namefield = vo->namefield;
1735 idfield = vo->idfield;
1736 ## retrieve (id = table.idfield) where table.namefield = name
1737 ## inquire_equel (rowcount = "rowcount")
1738 if (rowcount != 1) return(vo->error);
1739 *(int *)argv[vo->index] = id;
1743 validate_name(argv, vo)
1745 register struct valobj *vo;
1752 name = argv[vo->index];
1754 namefield = vo->namefield;
1755 ## retrieve (rowcount = countu(table.namefield
1756 ## where table.namefield = name))
1757 return ((rowcount == 1) ? SMS_EXISTS : vo->error);
1760 validate_date(argv, vo)
1768 idate = argv[vo->index];
1770 ## retrieve (dd = interval("years", date(idate) - date("today")))
1771 ## inquire_equel (errorno = "errorno")
1772 if (errorno != 0 || dd > 5.0) return(SMS_DATE);
1773 return(SMS_SUCCESS);
1776 validate_type(argv, vo)
1778 register struct valobj *vo;
1785 typename = vo->table;
1786 value = argv[vo->index];
1788 /* uppercase type fields */
1789 for (c = value; *c; c++) if (islower(*c)) *c = toupper(*c);
1791 ## range of a is alias
1792 ## repeat retrieve (rowcount = count(a.trans where a.name = @typename and
1793 ## a.type = "TYPE" and
1794 ## a.trans = @value))
1795 return ((rowcount == 1) ? SMS_EXISTS : vo->error);
1798 /* validate member or type-specific data field */
1800 validate_typedata(q, argv, vo)
1801 register struct query *q;
1802 register char *argv[];
1803 register struct valobj *vo;
1806 ## char *field_type;
1807 ## char data_type[17];
1813 /* get named object */
1814 name = argv[vo->index];
1816 /* get field type string (known to be at index-1) */
1817 field_type = argv[vo->index-1];
1819 /* get corresponding data type associated with field type name */
1820 ## repeat retrieve (data_type = alias.trans)
1821 ## where alias.#name = @field_type and alias.type = "TYPEDATA"
1822 ## inquire_equel (rowcount = "rowcount")
1823 if (rowcount != 1) return(SMS_TYPE);
1825 /* now retrieve the record id corresponding to the named object */
1827 if (!strcmp(data_type, "user")) {
1829 ## repeat retrieve (id = users.users_id) where users.login = @name
1830 ## inquire_equel (rowcount = "rowcount")
1831 if (rowcount != 1) return(SMS_USER);
1833 } else if (!strcmp(data_type, "list")) {
1835 ## repeat retrieve (id = list.list_id) where list.#name = @name
1836 ## inquire_equel (rowcount = "rowcount")
1837 if (rowcount != 1) return(SMS_LIST);
1839 } else if (!strcmp(data_type, "machine")) {
1841 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
1842 ## repeat retrieve (id = machine.mach_id) where machine.#name = @name
1843 ## inquire_equel (rowcount = "rowcount")
1844 if (rowcount != 1) return(SMS_MACHINE);
1846 } else if (!strcmp(data_type, "string")) {
1848 ## range of s is strings
1849 ## repeat retrieve (id = s.string_id, refc = s.#refc)
1850 ## where s.string = @name
1851 ## inquire_equel (rowcount = "rowcount")
1852 if (rowcount == 0) {
1853 if (q->type != APPEND) return(SMS_STRING);
1854 ## range of v is values
1855 ## retrieve (id = v.value) where v.#name = "strings_id"
1857 ## replace v (value = id) where v.#name = "strings_id"
1858 ## append to strings (string_id = id, string = name, #refc = 1)
1859 } else if (rowcount == 1) {
1860 if (q->type == APPEND || q->type == DELETE) {
1861 refc += (q->type == APPEND) ? 1 : -1;
1863 ## replace s (#refc = refc) where s.string_id = id
1865 ## delete s where s.string_id = id
1873 /* now set value in argv */
1874 *(int *)argv[vo->index] = id;
1876 return (SMS_EXISTS);
1880 translate_ids(q, sq, v, action, actarg)
1881 register struct query *q;
1882 register struct save_queue *sq;
1883 register struct validate *v;
1884 register int (*action)();
1888 ## char *field_type;
1889 ## char data_type[17];
1896 for (i = 0; i < v->objcnt; i++) {
1898 if (vo->type == V_FOLLOWUP) break;
1902 while (sq_get_data(sq, &argv)) {
1906 sscanf(argv[i], "%d", &id);
1908 name = (char *)malloc(129);
1911 /* get field type string (known to be at index-1) */
1912 field_type = argv[vo->index-1];
1914 /* get corresponding data type associated with field type name */
1915 ## repeat retrieve (data_type = alias.trans)
1916 ## where alias.#name = @field_type and alias.type = "TYPEDATA"
1917 ## inquire_equel (rowcount = "rowcount")
1918 if (rowcount != 1) {
1919 sprintf(name, "%d", id);
1920 (*action)(q->vcnt, argv, actarg);
1924 /* retrieve object name */
1926 if (!strcmp(data_type, "user")) {
1928 ## repeat retrieve (name = users.login) where users.users_id = @id
1929 ## inquire_equel (rowcount = "rowcount")
1931 } else if (!strcmp(data_type, "list")) {
1933 ## repeat retrieve (name = list.#name) where list.list_id = @id
1934 ## inquire_equel (rowcount = "rowcount")
1936 } else if (!strcmp(data_type, "machine")) {
1938 ## repeat retrieve (name = machine.#name) where machine.mach_id = @id
1939 ## inquire_equel (rowcount = "rowcount")
1941 } else if (!strcmp(data_type, "string")) {
1943 ## repeat retrieve (name = strings.string)
1944 ## where strings.string_id = @id
1945 ## inquire_equel (rowcount = "rowcount")
1951 /* if there wasn't a corresponding object name, then use the id */
1952 if (rowcount != 1) sprintf(name, "%d", id);
1955 (*action)(q->vcnt, argv, actarg);
1957 /* free saved data */
1958 for (i = 0; i < q->vcnt; i++)
1964 return (SMS_SUCCESS);
1971 * c-continued-statement-offset: 4
1972 * c-brace-offset: -4
1973 * c-argdecl-indent: 4
1974 * c-label-offset: -4