6 * Copyright (C) 1987 by the Massachusetts Institute of Technology
9 * Revision 1.2 1987-07-29 16:00:39 wesommer
12 Revision 1.1 87/07/29 15:13:57 wesommer
18 static char *rcsid_qsupport_qc = "$Header$";
22 #include "sms_server.h"
29 /* Specialized Access Routines */
32 ** access_user - verify that client name equals specified login name
34 ** Used by: update_user_shell
35 ** update_finger_by_login
37 ** - since field validation routines are called first, a users_id is
38 ** now in argv[0] instead of the login name. Therefore, we must
39 ** convert the client name to a users_id.
42 access_user(q, argv, cl)
47 register struct krbname *krb;
52 client_name = cl->kname.name;
53 ## repeat retrieve (client_id = users.users_id)
54 ## where users.login = @client_name
55 ## inquire_equel (rowcount = "rowcount")
56 if (rowcount != 1) return(SMS_PERM);
57 if (client_id != *(int *)argv[0]) return(SMS_PERM);
63 ** access_list - check access for adding or deleting list members
65 ** Inputs: argv[0] - list_id
66 ** cl->krb.name - client name
68 ** - check that client is a member of the access control list
69 ** - OR, if q->shortname == {amtl | dfml} and
70 ** if list.flags & LF_PUBLIC, allow access if client = member
74 access_list(q, argv, cl)
88 list_id = *(int *)argv[0];
89 ## repeat retrieve (acl_id = list.#acl_id, flags = list.#flags)
90 ## where list.#list_id = @list_id
92 /* parse client structure */
93 status = get_client(cl, &client_type, &client_id);
94 if (status != SMS_SUCCESS) return(status);
96 /* if amtl or dmfl and list is public allow client to add or delete self */
97 if (!bcmp("amtl", q->shortname, 4) || !bcmp("dmfl", q->shortname, 4)) {
98 if ((flags & LF_PUBLIC) && !bcmp("USER", argv[1], 4)) {
99 member_id = *(int *)argv[2];
100 if (member_id == client_id) return(SMS_SUCCESS);
104 /* check for client in access control list */
105 exists = find_member(acl_id, client_type, client_id, 0);
106 if (!exists) return(SMS_PERM);
112 ** Setup routine for add_user
114 ** Inputs: argv[0] - login
119 ** - if argv[1] == "#" then set argv[1] = next(uid)
120 ** - if argv[0] == "#" then set argv[0] = "#<uid>"
124 setup_add_user(q, argv, cl, access_check)
126 register char *argv[];
133 if (access_check) return(SMS_SUCCESS);
135 if (!bcmp(argv[1], "#", 2)) {
136 ## range of u is users
137 ## range of v is values
138 ## repeat retrieve (nuid = v.value) where v.name = "uid"
142 ## repeat retrieve (exists = any(u.#uid where u.#uid = @nuid))
144 ## repeat replace v (value = @nuid) where v.name = "uid"
145 sprintf(argv[1], "%d", nuid);
148 if (!bcmp(argv[0], "#", 2)) {
149 sprintf(argv[0], "#%s", argv[1]);
156 ** Setup routine for add_group
160 ** Description: allocate next gid and store in values table
164 setup_add_group(q, argv, cl, access_check)
173 if (access_check) return(SMS_SUCCESS);
175 ## range of g is groups
176 ## range of v is values
177 ## repeat retrieve (ngid = v.value) where v.name = "gid"
181 ## repeat retrieve (exists = any(g.#gid where g.#gid = @ngid))
184 ## repeat replace v (value = @ngid) where v.name = "gid"
188 /* Followup Routines */
190 set_user_modtime(q, argv)
197 ## repeat replace u (modtime = "now") where u.#login = @login
201 set_user_modtime_by_id(q, argv)
207 users_id = *(int *)argv[0];
208 ## repeat replace users (modtime = "now") where users.#users_id = @users_id
212 set_list_modtime(q, argv)
219 ## repeat replace list (modtime = "now") where list.name = @list_name
223 set_list_modtime_by_id(q, argv)
229 list_id = *(int *)argv[0];
230 ## repeat replace list (modtime = "now") where list.#list_id = @list_id
234 set_finger_modtime(q, argv)
240 users_id = *(int *)argv[0];
241 ## repeat replace f (modtime = "now") where f.#users_id = @users_id
246 ** delete_list_members - called after the delete_list query to clean up
249 ** Inputs: argv[0] - list_id
252 ** - foreach string member: decr string refc; ifzero, delete string
253 ** - delete all members entries for this list_id
257 delete_list_members(q, argv)
259 register char *argv[];
265 struct save_queue *sq;
266 struct save_queue *sq_create();
268 list_id = *(int *)argv[0];
271 ## range of m is members
272 ## repeat retrieve (string_id = m.member_id)
273 ## where m.#list_id = @list_id and m.member_type = "STRING"
275 sq_save_data(sq, string_id);
278 while (sq_get_data(sq, &string_id)) {
279 ## range of s is strings
280 ## repeat retrieve (refc = s.#refc) where s.#string_id = @string_id
281 ## inquire_equel (rowcount = "rowcount")
282 if (rowcount == 0) continue;
284 ## repeat delete s where s.#string_id = @string_id
286 ## repeat replace s (#refc = @refc) where s.#string_id = @string_id
291 ## repeat delete m where m.#list_id = @list_id
297 ** grvd_support - Support routine for get_rvd_servers query
300 ** q - grvd query structure
301 ** sq - save_queue struture: contains list of {machine, oper_acl_id,
302 ** admin_acl_id, shutdown_acl_id} records.
303 ** v - validate structure (not used)
304 ** action - action routine
305 ** actarg - action routine argument
308 ** - translate acl_ids to list names
312 grvd_support(q, sq, v, action, actarg)
314 struct save_queue *sq;
323 ## char shutdown[33];
330 ## range of l is list
332 while (sq_get_data(sq, &argv)) {
333 sscanf(argv[1], "%d", &list_id);
334 ## repeat retrieve (oper = l.name) where l.#list_id = @list_id
335 sscanf(argv[2], "%d", &list_id);
336 ## repeat retrieve (admin = l.name) where l.#list_id = @list_id
337 sscanf(argv[3], "%d", &list_id);
338 ## repeat retrieve (shutdown = l.name) where l.#list_id = @list_id
341 (*action)(4, targv, actarg);
353 ** set_next_object_id - set next object id in values table
355 ** Inputs: object - object name in values table
357 ** - called before an APPEND operation to set the next object id to
358 ** be used for the new record
362 set_next_object_id(object)
369 ## range of v is values
370 ## repeat retrieve (id = v.value) where v.#name = @name
372 ## repeat replace v (value = @id) where v.#name = @name
378 ** add_locker - special query routine for creating a user locker
381 ** argv[0] - users_id
382 ** argv[1] - machine_id
384 ** argv[3] - initial quota
387 ** - get prefix directory (dir) for mount point on specified machine/device
388 ** - create filesys entry (label=<login>, type=NFS, machine=<machine>,
389 ** mount=<dir>/<login>, access=w, acl=dbadmin)
390 ** - increment allocated in nfsphys by quota
391 ** - create nfsquota entry
394 ** - SMS_NFSPHYS - machine/device does not exist in nfsphys
395 ** - SMS_FILESYS_EXISTS - file system already exists
400 register struct query *q;
416 users_id = *(int *)argv[0];
417 mach_id = *(int *)argv[1];
419 sscanf(argv[3], "%d", "a);
421 ## range of u is users
422 ## range of f is filesys
423 ## range of np is nfsphys
426 ## repeat retrieve (login = u.#login) where u.#users_id = @users_id
428 /* get user's acl id */
429 ## repeat retrieve (user_acl = list.list_id) where list.name = @login
431 /* get filesystem directory prefix; give error if machine/device
432 pair not in nfsphys table */
433 ## repeat retrieve (dir = np.#dir, allocated = np.#allocated)
434 ## where np.#mach_id = @mach_id and np.#device = device
435 ## inquire_equel (rowcount = "rowcount")
436 if (rowcount == 0) return(SMS_NFSPHYS);
438 /* make sure a filesys with user's name does not already exist */
439 ## repeat retrieve (rowcount = any(f.label where f.label = @login))
440 if (rowcount != 0) return(SMS_FILESYS_EXISTS);
442 /* create a new filesys */
443 sprintf(locker, "%s/%s", dir, login);
444 sprintf(mount, "/mit/%s", login);
445 ## repeat append filesys
446 ## (#label = @login, type = "NFS", #mach_id = @mach_id,
447 ## name = @locker, access = "w", order = 1, #mount = @mount,
448 ## acl_id = @user_acl)
450 /* increment usage count in nfsphys table */
452 ## replace np (#allocated = allocated)
453 ## where np.#mach_id = mach_id and np.#device = device
455 /* create nfsquota entry */
456 ## append nfsquota (#users_id = users_id, #mach_id = mach_id,
457 ## #device = device, #quota = quota)
462 /* Validation Routines */
464 validate_row(q, argv, v)
465 register struct query *q;
467 register struct validate *v;
475 /* build where clause */
476 build_qual(v->qual, v->argc, argv, qual);
478 /* setup ingres variables */
483 /* tell the logfile what we're doing */
484 com_err(whoami, 0, "validating row");
485 com_err(whoami, 0, qual);
487 /* look for the record */
488 ## range of rvar is table
489 ## retrieve (rowcount = count(rvar.name where qual))
490 com_err(whoami, 0, "row validated");
491 if (rowcount == 0) return(SMS_NO_MATCH);
492 if (rowcount > 1) return(SMS_NOT_UNIQUE);
496 validate_fields(q, argv, vo, n)
498 register char *argv[];
499 register struct valobj *vo;
508 sprintf(buf, "validating %s in %s: %s",
509 vo->namefield, vo->table, argv[vo->index]);
510 com_err(whoami, 0, buf);
511 status = validate_name(argv, vo);
515 sprintf(buf, "validating %s in %s: %s",
516 vo->idfield, vo->table, argv[vo->index]);
517 com_err(whoami, 0, buf);
518 status = validate_id(argv, vo);
522 sprintf(buf, "validating %s type: %s",
523 vo->table, argv[vo->index]);
524 com_err(whoami, 0, buf);
525 status = validate_type(argv, vo);
529 sprintf(buf, "validating type-specific data: %s",
531 com_err(whoami, 0, buf);
532 status = validate_typedata(q, argv, vo);
541 if (status != SMS_EXISTS) return(status);
548 validate_id(argv, vo)
550 register struct valobj *vo;
559 name = argv[vo->index];
561 namefield = vo->namefield;
562 idfield = vo->idfield;
563 ## retrieve (id = table.idfield) where table.namefield = name
564 ## inquire_equel (rowcount = "rowcount")
565 if (rowcount != 1) return(vo->error);
566 *(int *)argv[vo->index] = id;
570 validate_name(argv, vo)
572 register struct valobj *vo;
579 name = argv[vo->index];
581 namefield = vo->namefield;
582 ## retrieve (rowcount = countu(table.namefield
583 ## where table.namefield = name))
584 return ((rowcount == 1) ? SMS_EXISTS : vo->error);
587 validate_type(argv, vo)
589 register struct valobj *vo;
596 typename = vo->table;
597 value = argv[vo->index];
599 /* uppercase type fields */
600 for (c = value; *c; c++) if (islower(*c)) *c = toupper(*c);
602 ## range of a is alias
603 ## repeat retrieve (rowcount = count(a.trans where a.name = @typename and
604 ## a.type = "TYPE" and
605 ## a.trans = @value))
606 return ((rowcount == 1) ? SMS_EXISTS : vo->error);
609 /* validate member or type-specific data field */
611 validate_typedata(q, argv, vo)
612 register struct query *q;
613 register char *argv[];
614 register struct valobj *vo;
618 ## char data_type[17];
623 /* get named object */
624 name = argv[vo->index];
626 /* get field type string (known to be at index-1) */
627 field_type = argv[vo->index-1];
629 /* get corresponding data type associated with field type name */
630 ## repeat retrieve (data_type = alias.trans)
631 ## where alias.#name = @field_type and alias.type = "TYPEDATA"
632 ## inquire_equel (rowcount = "rowcount")
633 if (rowcount != 1) return(SMS_TYPE);
635 /* now retrieve the record id corresponding to the named object */
637 if (!strcmp(data_type, "user")) {
639 ## repeat retrieve (id = users.users_id) where users.login = @name
640 ## inquire_equel (rowcount = "rowcount")
641 if (rowcount != 1) return(SMS_USER);
643 } else if (!strcmp(data_type, "list")) {
645 ## repeat retrieve (id = list.list_id) where list.#name = @name
646 ## inquire_equel (rowcount = "rowcount")
647 if (rowcount != 1) return(SMS_LIST);
649 } else if (!strcmp(data_type, "machine")) {
651 ## repeat retrieve (id = machine.mach_id) where machine.#name = @name
652 ## inquire_equel (rowcount = "rowcount")
653 if (rowcount != 1) return(SMS_MACHINE);
655 } else if (!strcmp(data_type, "string")) {
657 ## range of s is strings
658 ## repeat retrieve (id = s.string_id, refc = s.#refc)
659 ## where s.string = @name
660 ## inquire_equel (rowcount = "rowcount")
662 if (q->type != APPEND) return(SMS_STRING);
663 ## range of v is values
664 ## retrieve (id = v.value) where v.#name = "strings_id"
666 ## replace v (value = id) where v.#name = "strings_id"
667 ## append to strings (string_id = id, string = name, #refc = 1)
668 } else if (rowcount == 1) {
669 if (q->type == APPEND || q->type == DELETE) {
670 refc += (q->type == APPEND) ? 1 : -1;
672 ## replace s (#refc = refc) where s.string_id = id
674 ## delete s where s.string_id = id
682 /* now set value in argv */
683 *(int *)argv[vo->index] = id;
689 translate_ids(q, sq, v, action, actarg)
690 register struct query *q;
691 register struct save_queue *sq;
692 register struct validate *v;
693 register int (*action)();
698 ## char data_type[17];
705 for (i = 0; i < v->objcnt; i++) {
707 if (vo->type == V_FOLLOWUP) break;
711 while (sq_get_data(sq, &argv)) {
715 sscanf(argv[i], "%d", &id);
717 name = (char *)malloc(129);
720 /* get field type string (known to be at index-1) */
721 field_type = argv[vo->index-1];
723 /* get corresponding data type associated with field type name */
724 ## repeat retrieve (data_type = alias.trans)
725 ## where alias.#name = @field_type and alias.type = "TYPEDATA"
726 ## inquire_equel (rowcount = "rowcount")
728 sprintf(name, "%d", id);
729 (*action)(q->vcnt, argv, actarg);
733 /* retrieve object name */
735 if (!strcmp(data_type, "user")) {
737 ## repeat retrieve (name = users.login) where users.users_id = @id
738 ## inquire_equel (rowcount = "rowcount")
740 } else if (!strcmp(data_type, "list")) {
742 ## repeat retrieve (name = list.#name) where list.list_id = @id
743 ## inquire_equel (rowcount = "rowcount")
745 } else if (!strcmp(data_type, "machine")) {
747 ## repeat retrieve (name = machine.#name) where machine.mach_id = @id
748 ## inquire_equel (rowcount = "rowcount")
750 } else if (!strcmp(data_type, "string")) {
752 ## repeat retrieve (name = strings.string)
753 ## where strings.string_id = @id
754 ## inquire_equel (rowcount = "rowcount")
760 /* if there wasn't a corresponding object name, then use the id */
761 if (rowcount != 1) sprintf(name, "%d", id);
764 (*action)(q->vcnt, argv, actarg);
766 /* free saved data */
767 for (i = 0; i < q->vcnt; i++)
773 return (SMS_SUCCESS);
780 * c-continued-statement-offset: 4
782 * c-argdecl-indent: 4