]> andersk Git - moira.git/blob - server/qsupport.qc
Fixed add_locker.
[moira.git] / server / qsupport.qc
1 /*
2  *      $Source$
3  *      $Author$
4  *      $Header$
5  *
6  *      Copyright (C) 1987 by the Massachusetts Institute of Technology
7  *
8  *      $Log$
9  *      Revision 1.2  1987-07-29 16:00:39  wesommer
10  *      Fixed add_locker.
11  *
12 Revision 1.1  87/07/29  15:13:57  wesommer
13 Initial revision
14
15  */
16
17 #ifndef lint
18 static 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
27 extern 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
42 access_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
74 access_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
124 setup_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
164 setup_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
190 set_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
201 set_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
212 set_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
223 set_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
234 set_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
257 delete_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
312 grvd_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
362 set_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
399 add_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 
446 ##             (#label = @login, type = "NFS", #mach_id = @mach_id,
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,
457 ##                   #device = device, #quota = quota)
458
459     return(SMS_SUCCESS);
460 ##}
461 \f
462 /* Validation Routines */
463
464 validate_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
496 validate_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
548 validate_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
570 validate_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
587 validate_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
611 validate_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
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)();
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.099735 seconds and 5 git commands to generate.