]> andersk Git - moira.git/blame - server/qsupport.qc
Initial revision
[moira.git] / server / qsupport.qc
CommitLineData
05cdd922 1/*
2 * $Source$
3 * $Author$
4 * $Header$
5 *
6 * Copyright (C) 1987 by the Massachusetts Institute of Technology
7 *
8 * $Log$
9 * Revision 1.1 1987-07-29 15:13:57 wesommer
10 * Initial revision
11 *
12 */
13
14#ifndef lint
15static char *rcsid_qsupport_qc = "$Header$";
16#endif lint
17
18#include "query.h"
19#include "sms_server.h"
20#include <ctype.h>
21
22#define SMS_SUCCESS 0
23
24extern char *whoami;
25
26/* Specialized Access Routines */
27
28/**
29 ** access_user - verify that client name equals specified login name
30 **
31 ** Used by: update_user_shell
32 ** update_finger_by_login
33 **
34 ** - since field validation routines are called first, a users_id is
35 ** now in argv[0] instead of the login name. Therefore, we must
36 ** convert the client name to a users_id.
37 **/
38
39access_user(q, argv, cl)
40 struct query *q;
41 char *argv[];
42 client *cl;
43##{
44 register struct krbname *krb;
45## int client_id;
46## char *client_name;
47## int rowcount;
48
49 client_name = cl->kname.name;
50## repeat retrieve (client_id = users.users_id)
51## where users.login = @client_name
52## inquire_equel (rowcount = "rowcount")
53 if (rowcount != 1) return(SMS_PERM);
54 if (client_id != *(int *)argv[0]) return(SMS_PERM);
55
56 return(SMS_SUCCESS);
57##}
58
59/**
60 ** access_list - check access for adding or deleting list members
61 **
62 ** Inputs: argv[0] - list_id
63 ** cl->krb.name - client name
64 **
65 ** - check that client is a member of the access control list
66 ** - OR, if q->shortname == {amtl | dfml} and
67 ** if list.flags & LF_PUBLIC, allow access if client = member
68 **
69 **/
70
71access_list(q, argv, cl)
72 struct query *q;
73 char *argv[];
74 client *cl;
75##{
76## int list_id;
77## int acl_id;
78## int flags;
79 int member_id;
80 char *client_type;
81 int client_id;
82 int status;
83 int exists;
84
85 list_id = *(int *)argv[0];
86## repeat retrieve (acl_id = list.#acl_id, flags = list.#flags)
87## where list.#list_id = @list_id
88
89 /* parse client structure */
90 status = get_client(cl, &client_type, &client_id);
91 if (status != SMS_SUCCESS) return(status);
92
93 /* if amtl or dmfl and list is public allow client to add or delete self */
94 if (!bcmp("amtl", q->shortname, 4) || !bcmp("dmfl", q->shortname, 4)) {
95 if ((flags & LF_PUBLIC) && !bcmp("USER", argv[1], 4)) {
96 member_id = *(int *)argv[2];
97 if (member_id == client_id) return(SMS_SUCCESS);
98 }
99 }
100
101 /* check for client in access control list */
102 exists = find_member(acl_id, client_type, client_id, 0);
103 if (!exists) return(SMS_PERM);
104
105 return(SMS_SUCCESS);
106##}
107\f
108/**
109 ** Setup routine for add_user
110 **
111 ** Inputs: argv[0] - login
112 ** argv[1] - uid
113 **
114 ** Description:
115 **
116 ** - if argv[1] == "#" then set argv[1] = next(uid)
117 ** - if argv[0] == "#" then set argv[0] = "#<uid>"
118 **
119 **/
120
121setup_add_user(q, argv, cl, access_check)
122 struct query *q;
123 register char *argv[];
124 client *cl;
125 int access_check;
126##{
127## int nuid;
128## int exists;
129
130 if (access_check) return(SMS_SUCCESS);
131
132 if (!bcmp(argv[1], "#", 2)) {
133## range of u is users
134## range of v is values
135## repeat retrieve (nuid = v.value) where v.name = "uid"
136 exists = 1;
137 while (exists) {
138 nuid++;
139## repeat retrieve (exists = any(u.#uid where u.#uid = @nuid))
140 }
141## repeat replace v (value = @nuid) where v.name = "uid"
142 sprintf(argv[1], "%d", nuid);
143 }
144
145 if (!bcmp(argv[0], "#", 2)) {
146 sprintf(argv[0], "#%s", argv[1]);
147 }
148
149 return(SMS_SUCCESS);
150##}
151
152/**
153 ** Setup routine for add_group
154 **
155 ** Inputs: none
156 **
157 ** Description: allocate next gid and store in values table
158 **
159 **/
160
161setup_add_group(q, argv, cl, access_check)
162 struct query *q;
163 char *argv[];
164 client *cl;
165 int access_check;
166##{
167## int ngid;
168## int exists;
169
170 if (access_check) return(SMS_SUCCESS);
171
172## range of g is groups
173## range of v is values
174## repeat retrieve (ngid = v.value) where v.name = "gid"
175 exists = 1;
176 while (exists) {
177 ngid++;
178## repeat retrieve (exists = any(g.#gid where g.#gid = @ngid))
179 }
180
181## repeat replace v (value = @ngid) where v.name = "gid"
182 return(SMS_SUCCESS);
183##}
184\f
185/* Followup Routines */
186
187set_user_modtime(q, argv)
188 struct query *q;
189 char *argv[];
190##{
191## char *login;
192
193 login = argv[0];
194## repeat replace u (modtime = "now") where u.#login = @login
195 return(SMS_SUCCESS);
196##}
197
198set_user_modtime_by_id(q, argv)
199 struct query *q;
200 char *argv[];
201##{
202## int users_id;
203
204 users_id = *(int *)argv[0];
205## repeat replace users (modtime = "now") where users.#users_id = @users_id
206 return(SMS_SUCCESS);
207##}
208
209set_list_modtime(q, argv)
210 struct query *q;
211 char *argv[];
212##{
213## char *list_name;
214
215 list_name = argv[0];
216## repeat replace list (modtime = "now") where list.name = @list_name
217 return(SMS_SUCCESS);
218##}
219
220set_list_modtime_by_id(q, argv)
221 struct query *q;
222 char *argv[];
223##{
224## int list_id;
225
226 list_id = *(int *)argv[0];
227## repeat replace list (modtime = "now") where list.#list_id = @list_id
228 return(SMS_SUCCESS);
229##}
230
231set_finger_modtime(q, argv)
232 struct query *q;
233 char *argv[];
234##{
235## int users_id;
236
237 users_id = *(int *)argv[0];
238## repeat replace f (modtime = "now") where f.#users_id = @users_id
239 return(SMS_SUCCESS);
240##}
241
242/**
243 ** delete_list_members - called after the delete_list query to clean up
244 ** members table.
245 **
246 ** Inputs: argv[0] - list_id
247 **
248 ** Description:
249 ** - foreach string member: decr string refc; ifzero, delete string
250 ** - delete all members entries for this list_id
251 **
252 **/
253
254delete_list_members(q, argv)
255 struct query *q;
256 register char *argv[];
257##{
258## int list_id;
259## int string_id;
260## int refc;
261## int rowcount;
262 struct save_queue *sq;
263 struct save_queue *sq_create();
264
265 list_id = *(int *)argv[0];
266 sq = sq_create();
267
268## range of m is members
269## repeat retrieve (string_id = m.member_id)
270## where m.#list_id = @list_id and m.member_type = "STRING"
271## {
272 sq_save_data(sq, string_id);
273## }
274
275 while (sq_get_data(sq, &string_id)) {
276## range of s is strings
277## repeat retrieve (refc = s.#refc) where s.#string_id = @string_id
278## inquire_equel (rowcount = "rowcount")
279 if (rowcount == 0) continue;
280 if (--refc == 0) {
281## repeat delete s where s.#string_id = @string_id
282 } else {
283## repeat replace s (#refc = @refc) where s.#string_id = @string_id
284 }
285 }
286 sq_destroy(sq);
287
288## repeat delete m where m.#list_id = @list_id
289
290 return(SMS_SUCCESS);
291##}
292
293/**
294 ** grvd_support - Support routine for get_rvd_servers query
295 **
296 ** Inputs:
297 ** q - grvd query structure
298 ** sq - save_queue struture: contains list of {machine, oper_acl_id,
299 ** admin_acl_id, shutdown_acl_id} records.
300 ** v - validate structure (not used)
301 ** action - action routine
302 ** actarg - action routine argument
303 **
304 ** Description:
305 ** - translate acl_ids to list names
306 **
307 **/
308
309grvd_support(q, sq, v, action, actarg)
310 struct query *q;
311 struct save_queue *sq;
312 struct validate *v;
313 int (*action)();
314 int actarg;
315##{
316 char **argv;
317 char *targv[4];
318## char oper[33];
319## char admin[33];
320## char shutdown[33];
321## int list_id;
322
323 targv[1] = oper;
324 targv[2] = admin;
325 targv[3] = shutdown;
326
327## range of l is list
328
329 while (sq_get_data(sq, &argv)) {
330 sscanf(argv[1], "%d", &list_id);
331## repeat retrieve (oper = l.name) where l.#list_id = @list_id
332 sscanf(argv[2], "%d", &list_id);
333## repeat retrieve (admin = l.name) where l.#list_id = @list_id
334 sscanf(argv[3], "%d", &list_id);
335## repeat retrieve (shutdown = l.name) where l.#list_id = @list_id
336
337 targv[0] = argv[0];
338 (*action)(4, targv, actarg);
339 free(argv[0]);
340 free(argv[1]);
341 free(argv[2]);
342 free(argv[3]);
343 }
344
345 sq_destroy(sq);
346 return(SMS_SUCCESS);
347##}
348
349/**
350 ** set_next_object_id - set next object id in values table
351 **
352 ** Inputs: object - object name in values table
353 **
354 ** - called before an APPEND operation to set the next object id to
355 ** be used for the new record
356 **
357 **/
358
359set_next_object_id(object)
360 char *object;
361##{
362## char *name;
363## int id;
364
365 name = object;
366## range of v is values
367## repeat retrieve (id = v.value) where v.#name = @name
368 id++;
369## repeat replace v (value = @id) where v.#name = @name
370 return(SMS_SUCCESS);
371##}
372
373\f
374/**
375 ** add_locker - special query routine for creating a user locker
376 **
377 ** Inputs:
378 ** argv[0] - users_id
379 ** argv[1] - machine_id
380 ** argv[2] - device
381 ** argv[3] - initial quota
382 **
383 ** Description:
384 ** - get prefix directory (dir) for mount point on specified machine/device
385 ** - create filesys entry (label=<login>, type=NFS, machine=<machine>,
386 ** mount=<dir>/<login>, access=w, acl=dbadmin)
387 ** - increment allocated in nfsphys by quota
388 ** - create nfsquota entry
389 **
390 ** Errors:
391 ** - SMS_NFSPHYS - machine/device does not exist in nfsphys
392 ** - SMS_FILESYS_EXISTS - file system already exists
393 **
394 **/
395
396add_locker(q, argv)
397 register struct query *q;
398 char *argv[];
399##{
400## int users_id;
401## int mach_id;
402## char *device;
403## int quota;
404## int rowcount;
405## char *login;
406## char dir[32];
407## int allocated;
408## char locker[64];
409## char mount[64];
410## int user_acl;
411
412 /* copy arguments */
413 users_id = *(int *)argv[0];
414 mach_id = *(int *)argv[1];
415 device = argv[2];
416 sscanf(argv[3], "%d", &quota);
417
418## range of u is users
419## range of f is filesys
420## range of np is nfsphys
421
422 /* get login name */
423## repeat retrieve (login = u.#login) where u.#users_id = @users_id
424
425 /* get user's acl id */
426## repeat retrieve (user_acl = list.list_id) where list.name = @login
427
428 /* get filesystem directory prefix; give error if machine/device
429 pair not in nfsphys table */
430## repeat retrieve (dir = np.#dir, allocated = np.#allocated)
431## where np.#mach_id = @mach_id and np.#device = device
432## inquire_equel (rowcount = "rowcount")
433 if (rowcount == 0) return(SMS_NFSPHYS);
434
435 /* make sure a filesys with user's name does not already exist */
436## repeat retrieve (rowcount = any(f.label where f.label = @login))
437 if (rowcount != 0) return(SMS_FILESYS_EXISTS);
438
439 /* create a new filesys */
440 sprintf(locker, "%s/%s", dir, login);
441 sprintf(mount, "/mit/%s", login);
442## repeat append filesys
443## (#users_id = @users_id, type = "NFS", #mach_id = @mach_id,
444## name = @locker, access = "w", order = 1, #mount = @mount,
445## acl_id = @user_acl)
446
447 /* increment usage count in nfsphys table */
448 allocated += quota;
449## replace np (#allocated = allocated)
450## where np.#mach_id = mach_id and np.#device = device
451
452 /* create nfsquota entry */
453## append nfsquota (#users_id = users_id, #mach_id = mach_id,
454## device = #device, #quota = quota)
455
456 return(SMS_SUCCESS);
457##}
458\f
459/* Validation Routines */
460
461validate_row(q, argv, v)
462 register struct query *q;
463 char *argv[];
464 register struct validate *v;
465##{
466## char *rvar;
467## char *table;
468## char *name;
469## char qual[128];
470## int rowcount;
471
472 /* build where clause */
473 build_qual(v->qual, v->argc, argv, qual);
474
475 /* setup ingres variables */
476 rvar = q->rvar;
477 table = q->rtable;
478 name = v->field;
479
480 /* tell the logfile what we're doing */
481 com_err(whoami, 0, "validating row");
482 com_err(whoami, 0, qual);
483
484 /* look for the record */
485## range of rvar is table
486## retrieve (rowcount = count(rvar.name where qual))
487 com_err(whoami, 0, "row validated");
488 if (rowcount == 0) return(SMS_NO_MATCH);
489 if (rowcount > 1) return(SMS_NOT_UNIQUE);
490 return(SMS_EXISTS);
491##}
492
493validate_fields(q, argv, vo, n)
494 struct query *q;
495 register char *argv[];
496 register struct valobj *vo;
497 register int n;
498{
499 register int status;
500 char buf[64];
501
502 while (--n >= 0) {
503 switch (vo->type) {
504 case V_NAME:
505 sprintf(buf, "validating %s in %s: %s",
506 vo->namefield, vo->table, argv[vo->index]);
507 com_err(whoami, 0, buf);
508 status = validate_name(argv, vo);
509 break;
510
511 case V_ID:
512 sprintf(buf, "validating %s in %s: %s",
513 vo->idfield, vo->table, argv[vo->index]);
514 com_err(whoami, 0, buf);
515 status = validate_id(argv, vo);
516 break;
517
518 case V_TYPE:
519 sprintf(buf, "validating %s type: %s",
520 vo->table, argv[vo->index]);
521 com_err(whoami, 0, buf);
522 status = validate_type(argv, vo);
523 break;
524
525 case V_TYPEDATA:
526 sprintf(buf, "validating type-specific data: %s",
527 argv[vo->index]);
528 com_err(whoami, 0, buf);
529 status = validate_typedata(q, argv, vo);
530 break;
531
532 case V_FOLLOWUP:
533 status = SMS_EXISTS;
534 break;
535
536 }
537
538 if (status != SMS_EXISTS) return(status);
539 vo++;
540 }
541
542 return(SMS_SUCCESS);
543}
544
545validate_id(argv, vo)
546 char *argv[];
547 register struct valobj *vo;
548##{
549## char *name;
550## char *table;
551## char *namefield;
552## char *idfield;
553## int id;
554## int rowcount;
555
556 name = argv[vo->index];
557 table = vo->table;
558 namefield = vo->namefield;
559 idfield = vo->idfield;
560## retrieve (id = table.idfield) where table.namefield = name
561## inquire_equel (rowcount = "rowcount")
562 if (rowcount != 1) return(vo->error);
563 *(int *)argv[vo->index] = id;
564 return(SMS_EXISTS);
565##}
566
567validate_name(argv, vo)
568 char *argv[];
569 register struct valobj *vo;
570##{
571## char *name;
572## char *table;
573## char *namefield;
574## int rowcount;
575
576 name = argv[vo->index];
577 table = vo->table;
578 namefield = vo->namefield;
579## retrieve (rowcount = countu(table.namefield
580## where table.namefield = name))
581 return ((rowcount == 1) ? SMS_EXISTS : vo->error);
582##}
583
584validate_type(argv, vo)
585 char *argv[];
586 register struct valobj *vo;
587##{
588## char *typename;
589## char *value;
590## int rowcount;
591 register char *c;
592
593 typename = vo->table;
594 value = argv[vo->index];
595
596 /* uppercase type fields */
597 for (c = value; *c; c++) if (islower(*c)) *c = toupper(*c);
598
599## range of a is alias
600## repeat retrieve (rowcount = count(a.trans where a.name = @typename and
601## a.type = "TYPE" and
602## a.trans = @value))
603 return ((rowcount == 1) ? SMS_EXISTS : vo->error);
604##}
605
606/* validate member or type-specific data field */
607
608validate_typedata(q, argv, vo)
609 register struct query *q;
610 register char *argv[];
611 register struct valobj *vo;
612##{
613## char *name;
614## char *field_type;
615## char data_type[17];
616## int id;
617## int refc;
618## int rowcount;
619
620 /* get named object */
621 name = argv[vo->index];
622
623 /* get field type string (known to be at index-1) */
624 field_type = argv[vo->index-1];
625
626 /* get corresponding data type associated with field type name */
627## repeat retrieve (data_type = alias.trans)
628## where alias.#name = @field_type and alias.type = "TYPEDATA"
629## inquire_equel (rowcount = "rowcount")
630 if (rowcount != 1) return(SMS_TYPE);
631
632 /* now retrieve the record id corresponding to the named object */
633
634 if (!strcmp(data_type, "user")) {
635 /* USER */
636## repeat retrieve (id = users.users_id) where users.login = @name
637## inquire_equel (rowcount = "rowcount")
638 if (rowcount != 1) return(SMS_USER);
639
640 } else if (!strcmp(data_type, "list")) {
641 /* LIST */
642## repeat retrieve (id = list.list_id) where list.#name = @name
643## inquire_equel (rowcount = "rowcount")
644 if (rowcount != 1) return(SMS_LIST);
645
646 } else if (!strcmp(data_type, "machine")) {
647 /* MACHINE */
648## repeat retrieve (id = machine.mach_id) where machine.#name = @name
649## inquire_equel (rowcount = "rowcount")
650 if (rowcount != 1) return(SMS_MACHINE);
651
652 } else if (!strcmp(data_type, "string")) {
653 /* STRING */
654## range of s is strings
655## repeat retrieve (id = s.string_id, refc = s.#refc)
656## where s.string = @name
657## inquire_equel (rowcount = "rowcount")
658 if (rowcount == 0) {
659 if (q->type != APPEND) return(SMS_STRING);
660## range of v is values
661## retrieve (id = v.value) where v.#name = "strings_id"
662 id++;
663## replace v (value = id) where v.#name = "strings_id"
664## append to strings (string_id = id, string = name, #refc = 1)
665 } else if (rowcount == 1) {
666 if (q->type == APPEND || q->type == DELETE) {
667 refc += (q->type == APPEND) ? 1 : -1;
668 if (refc > 0) {
669## replace s (#refc = refc) where s.string_id = id
670 } else {
671## delete s where s.string_id = id
672 }
673 }
674 }
675 } else {
676 return(SMS_TYPE);
677 }
678
679 /* now set value in argv */
680 *(int *)argv[vo->index] = id;
681
682 return (SMS_EXISTS);
683##}
684
685\f
686translate_ids(q, sq, v, action, actarg)
687 register struct query *q;
688 register struct save_queue *sq;
689 register struct validate *v;
690 register int (*action)();
691 int actarg;
692##{
693## char *name;
694## char *field_type;
695## char data_type[17];
696## int id;
697## int rowcount;
698 register int i;
699 struct valobj *vo;
700 char **argv;
701
702 for (i = 0; i < v->objcnt; i++) {
703 vo = &v->valobj[i];
704 if (vo->type == V_FOLLOWUP) break;
705 }
706
707 /* for each row */
708 while (sq_get_data(sq, &argv)) {
709
710 /* get object id */
711 i = vo->index;
712 sscanf(argv[i], "%d", &id);
713 free(argv[i]);
714 name = (char *)malloc(129);
715 argv[i] = name;
716
717 /* get field type string (known to be at index-1) */
718 field_type = argv[vo->index-1];
719
720 /* get corresponding data type associated with field type name */
721## repeat retrieve (data_type = alias.trans)
722## where alias.#name = @field_type and alias.type = "TYPEDATA"
723## inquire_equel (rowcount = "rowcount")
724 if (rowcount != 1) {
725 sprintf(name, "%d", id);
726 (*action)(q->vcnt, argv, actarg);
727 continue;
728 }
729
730 /* retrieve object name */
731
732 if (!strcmp(data_type, "user")) {
733 /* USER */
734## repeat retrieve (name = users.login) where users.users_id = @id
735## inquire_equel (rowcount = "rowcount")
736
737 } else if (!strcmp(data_type, "list")) {
738 /* LIST */
739## repeat retrieve (name = list.#name) where list.list_id = @id
740## inquire_equel (rowcount = "rowcount")
741
742 } else if (!strcmp(data_type, "machine")) {
743 /* MACHINE */
744## repeat retrieve (name = machine.#name) where machine.mach_id = @id
745## inquire_equel (rowcount = "rowcount")
746
747 } else if (!strcmp(data_type, "string")) {
748 /* STRING */
749## repeat retrieve (name = strings.string)
750## where strings.string_id = @id
751## inquire_equel (rowcount = "rowcount")
752
753 } else {
754 rowcount = 0;
755 }
756
757 /* if there wasn't a corresponding object name, then use the id */
758 if (rowcount != 1) sprintf(name, "%d", id);
759
760 /* send the data */
761 (*action)(q->vcnt, argv, actarg);
762
763 /* free saved data */
764 for (i = 0; i < q->vcnt; i++)
765 free(argv[i]);
766 free(argv);
767 }
768
769 sq_destroy(sq);
770 return (SMS_SUCCESS);
771##}
772\f
773/*
774 * Local Variables:
775 * mode: c
776 * c-indent-level: 4
777 * c-continued-statement-offset: 4
778 * c-brace-offset: -4
779 * c-argdecl-indent: 4
780 * c-label-offset: -4
781 * End:
782 */
This page took 0.189376 seconds and 5 git commands to generate.