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