]> andersk Git - moira.git/blame_incremental - server/qsupport.qc
have access_list make sure people can't change their group IDs
[moira.git] / server / qsupport.qc
... / ...
CommitLineData
1/*
2 * $Source$
3 * $Author$
4 * $Header$
5 *
6 * Copyright (C) 1987 by the Massachusetts Institute of Technology
7 *
8 */
9
10#ifndef lint
11static char *rcsid_qsupport_qc = "$Header$";
12#endif lint
13
14#include "query.h"
15#include "sms_server.h"
16#include <ctype.h>
17
18
19extern char *whoami, *strsave();
20
21
22/* Specialized Access Routines */
23
24/* access_user - verify that client name equals specified login name
25 *
26 * - since field validation routines are called first, a users_id is
27 * now in argv[0] instead of the login name.
28 */
29
30access_user(q, argv, cl)
31 struct query *q;
32 char *argv[];
33 client *cl;
34{
35 if (cl->users_id != *(int *)argv[0])
36 return(SMS_PERM);
37 else
38 return(SMS_SUCCESS);
39}
40
41
42
43/* access_login - verify that client name equals specified login name
44 *
45 * argv[0...n] contain search info. q->
46 */
47
48access_login(q, argv, cl)
49 struct query *q;
50 char *argv[];
51 client *cl;
52##{
53## int rowcount, id;
54## char qual[256];
55
56 build_qual(q->qual, q->argc, argv, qual);
57## retrieve (id = u.users_id) where qual
58## inquire_equel(rowcount = "rowcount")
59 if (rowcount != 1 || id != cl->users_id)
60 return(SMS_PERM);
61 else
62 return(SMS_SUCCESS);
63##}
64
65
66
67/* access_list - check access for most list operations
68 *
69 * Inputs: argv[0] - list_id
70 * q - query name
71 * argv[2] - member ID (only for queries "amtl" and "dmfl")
72 * argv[7] - group IID (only for query "ulis")
73 * cl - client name
74 *
75 * - check that client is a member of the access control list
76 * - OR, if the query is add_member_to_list or delete_member_from_list
77 * and the list is public, allow access if client = member
78 */
79
80access_list(q, argv, cl)
81 struct query *q;
82 char *argv[];
83 client *cl;
84##{
85## int list_id, acl_id, flags, rowcount, gid;
86## char acl_type[9];
87 char *client_type;
88 int client_id, status;
89
90 list_id = *(int *)argv[0];
91## repeat retrieve (acl_id = list.#acl_id, acl_type = list.#acl_type,
92## gid = list.#gid, flags = list.#public)
93## where list.#list_id = @list_id
94## inquire_equel(rowcount = "rowcount")
95 if (rowcount != 1)
96 return(SMS_INTERNAL);
97
98 /* parse client structure */
99 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
100 return(status);
101
102 /* if amtl or dmfl and list is public allow client to add or delete self */
103 if ((!strcmp("amtl", q->shortname) || !strcmp("dmfl", q->shortname)) &&
104 (flags && !strcmp("USER", argv[1]))) {
105 if (*(int *)argv[2] == client_id) return(SMS_SUCCESS);
106 /* if update_list, don't allow them to change the GID */
107 } else if (!strcmp("ulis", q->shortname)) {
108 if ((!strcmp(argv[7], UNIQUE_GID) && (gid != -1)) ||
109 (strcmp(argv[7], UNIQUE_GID) && (gid != atoi(argv[7]))))
110 return(SMS_PERM);
111 }
112
113 /* check for client in access control list */
114 status = find_member(acl_type, acl_id, client_type, client_id, 0);
115 if (!status) return(SMS_PERM);
116
117 return(SMS_SUCCESS);
118##}
119
120
121/* access_visible_list - allow access to list only if it is not hidden,
122 * or if the client is on the ACL
123 *
124 * Inputs: argv[0] - list_id
125 * cl - client identifier
126 */
127
128access_visible_list(q, argv, cl)
129 struct query *q;
130 char *argv[];
131 client *cl;
132##{
133## int list_id, acl_id, flags, rowcount;
134## char acl_type[9];
135 char *client_type;
136 int client_id, status;
137
138 list_id = *(int *)argv[0];
139## repeat retrieve (flags = list.hidden, acl_id = list.#acl_id,
140## acl_type = list.#acl_type) where list.#list_id = @list_id
141## inquire_equel(rowcount = "rowcount")
142 if (rowcount != 1)
143 return(SMS_INTERNAL);
144 if (!flags)
145 return(SMS_SUCCESS);
146
147 /* parse client structure */
148 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
149 return(status);
150
151 /* check for client in access control list */
152 status = find_member(acl_type, acl_id, client_type, client_id, 0);
153 if (!status)
154 return(SMS_PERM);
155
156 return(SMS_SUCCESS);
157##}
158
159
160/* access_vis_list_by_name - allow access to list only if it is not hidden,
161 * or if the client is on the ACL
162 *
163 * Inputs: argv[0] - list name
164 * cl - client identifier
165 */
166
167access_vis_list_by_name(q, argv, cl)
168 struct query *q;
169 char *argv[];
170 client *cl;
171##{
172## int acl_id, flags, rowcount;
173## char acl_type[9], *listname;
174 char *client_type;
175 int client_id, status;
176
177 listname = argv[0];
178## repeat retrieve (flags = list.hidden, acl_id = list.#acl_id,
179## acl_type = list.#acl_type) where list.#name = @listname
180## inquire_equel(rowcount = "rowcount");
181 if (rowcount > 1)
182 return(SMS_WILDCARD);
183 if (rowcount == 0)
184 return(SMS_NO_MATCH);
185 if (!flags)
186 return(SMS_SUCCESS);
187
188 /* parse client structure */
189 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
190 return(status);
191
192 /* check for client in access control list */
193 status = find_member(acl_type, acl_id, client_type, client_id, 0);
194 if (!status)
195 return(SMS_PERM);
196
197 return(SMS_SUCCESS);
198##}
199
200
201/* access_member - allow user to access member of type "USER" and name matches
202 * username, or to access member of type "LIST" and list is one that user is
203 * on the acl of, or the list is visible.
204 */
205
206access_member(q, argv, cl)
207 struct query *q;
208 char *argv[];
209 client *cl;
210{
211 if (!strcmp(argv[0], "LIST") || !strcmp(argv[0], "RLIST"))
212 return(access_visible_list(q, &argv[1], cl));
213
214 if (!strcmp(argv[0], "USER") || !strcmp(argv[0], "RUSER")) {
215 if (cl->users_id == *(int *)argv[1])
216 return(SMS_SUCCESS);
217 }
218
219 return(SMS_PERM);
220}
221
222
223/* access_qgli - special access routine for Qualified_get_lists. Allows
224 * access iff argv[0] == "TRUE" and argv[2] == "FALSE".
225 */
226
227access_qgli(q, argv, cl)
228 struct query *q;
229 char *argv[];
230 client *cl;
231{
232 if (!strcmp(argv[0], "TRUE") && !strcmp(argv[2], "FALSE"))
233 return(SMS_SUCCESS);
234 return(SMS_PERM);
235}
236
237
238/* access_service - allow access if user is on ACL of service. Don't
239 * allow access if a wildcard is used.
240 */
241
242access_service(q, argv, cl)
243 struct query *q;
244 char *argv[];
245 client *cl;
246##{
247## int acl_id, rowcount;
248## char *name, acl_type[9];
249 int client_id, status;
250 char *client_type;
251
252 name = argv[0];
253## repeat retrieve (acl_id = servers.#acl_id, acl_type = servers.#acl_type)
254## where servers.#name = uppercase(@name)
255## inquire_equel(rowcount = "rowcount")
256 if (rowcount > 1)
257 return(SMS_PERM);
258
259 /* parse client structure */
260 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
261 return(status);
262
263 /* check for client in access control list */
264 status = find_member(acl_type, acl_id, client_type, client_id, 0);
265 if (!status) return(SMS_PERM);
266
267 return(SMS_SUCCESS);
268##}
269
270
271
272/* access_filesys - verify that client is owner or on owners list of filesystem
273 * named by argv[0]
274 */
275
276access_filesys(q, argv, cl)
277 struct query *q;
278 char *argv[];
279 client *cl;
280##{
281## int rowcount, users_id, list_id;
282## char *name;
283 int status, client_id;
284 char *client_type;
285
286 name = argv[0];
287## repeat retrieve (users_id = filesys.owner, list_id = filesys.owners)
288## where filesys.label = @name
289## inquire_equel(rowcount = "rowcount")
290
291 if (rowcount != 1)
292 return(SMS_PERM);
293 if (users_id == cl->users_id)
294 return(SMS_SUCCESS);
295 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
296 return(status);
297 status = find_member("LIST", list_id, client_type, client_id, 0);
298 if (status)
299 return(SMS_SUCCESS);
300 return(SMS_PERM);
301##}
302
303
304\f
305/* Setup Routines */
306
307/* Setup routine for add_user
308 *
309 * Inputs: argv[0] - login
310 * argv[1] - uid
311 *
312 * Description:
313 *
314 * - if argv[1] == UNIQUE_UID then set argv[1] = next(uid)
315 * - if argv[0] == UNIQUE_LOGIN then set argv[0] = "#<uid>"
316 */
317
318setup_ausr(q, argv, cl)
319 struct query *q;
320 register char *argv[];
321 client *cl;
322##{
323## int nuid, rowcount;
324
325 if (!strcmp(argv[1], UNIQUE_UID) || atoi(argv[1]) == -1) {
326 if (set_next_object_id("uid", "users"))
327 return(SMS_INGRES_ERR);
328## repeat retrieve (nuid = values.value) where values.name = "uid"
329## inquire_equel(rowcount = "rowcount")
330 if (rowcount != 1)
331 return(SMS_INTERNAL);
332 sprintf(argv[1], "%d", nuid);
333 }
334
335 if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[1]) == -1) {
336 sprintf(argv[0], "#%s", argv[1]);
337 }
338
339 return(SMS_SUCCESS);
340##}
341
342
343/* setup_dusr - verify that the user is no longer being referenced
344 * and may safely be deleted.
345 */
346
347int setup_dusr(q, argv)
348 struct query *q;
349 char **argv;
350##{
351## int flag, id;
352
353 id = *(int *)argv[0];
354
355 /* For now, only allow users to be deleted if their status is 0 */
356## repeat retrieve (flag = u.status) where u.users_id = @id
357 if (flag != 0)
358 return(SMS_IN_USE);
359
360## repeat delete nfsquota where nfsquota.users_id = @id
361## repeat retrieve (flag = any(members.member_id where members.member_id=@id
362## and members.member_type = "USER"))
363 if (flag)
364 return(SMS_IN_USE);
365## repeat retrieve (flag = any(filesys.label where filesys.owner=@id))
366 if (flag)
367 return(SMS_IN_USE);
368## repeat retrieve (flag = any(list.name where list.acl_id=@id and
369## list.acl_type = "USER"))
370 if (flag)
371 return(SMS_IN_USE);
372## repeat retrieve (flag = any(servers.name where servers.acl_id=@id and
373## servers.acl_type = "USER"))
374 if (flag)
375 return(SMS_IN_USE);
376## repeat retrieve (flag=any(hostaccess.acl_id where hostaccess.acl_id=@id and
377## hostaccess.acl_type = "USER"))
378 if (flag)
379 return(SMS_IN_USE);
380 else
381 return(SMS_SUCCESS);
382##}
383
384
385/* setup_spop: verify that there is already a valid POP machine_id in the
386 * pop_id field. Also take care of keeping track of the post office usage.
387 */
388int setup_spop(q, argv)
389struct query *q;
390char **argv;
391##{
392## int id, flag;
393## char type[9];
394
395 id = *(int *)argv[0];
396## repeat retrieve (type = u.potype, flag = any(machine.name
397## where machine.mach_id = u.pop_id
398## and u.pop_id != 0
399## and u.users_id = @id))
400## where u.users_id = @id
401 if (!flag)
402 return(SMS_MACHINE);
403 if (strcmp(type, "POP"))
404 set_pop_usage(id, 1);
405 return(SMS_SUCCESS);
406##}
407
408
409/* setup_dpob: Take care of keeping track of the post office usage.
410 */
411int setup_dpob(q, argv)
412struct query *q;
413char **argv;
414##{
415## int id, user;
416## char type[9];
417
418 user = *(int *)argv[0];
419## repeat retrieve (type = u.potype, id = u.pop_id)
420## where u.users_id = @user
421
422 if (strcmp(type, "POP"))
423 set_pop_usage(id, -1);
424 return(SMS_SUCCESS);
425##}
426
427
428/* setup_dmac - verify that the machine is no longer being referenced
429 * and may safely be deleted.
430 */
431
432int setup_dmac(q, argv)
433 struct query *q;
434 char **argv;
435##{
436## int flag, id;
437
438 id = *(int *)argv[0];
439## repeat retrieve (flag = any(users.login where users.potype = "POP"
440## and users.pop_id=@id))
441 if (flag)
442 return(SMS_IN_USE);
443## repeat retrieve (flag = any(serverhosts.mach_id
444## where serverhosts.mach_id=@id))
445 if (flag)
446 return(SMS_IN_USE);
447## repeat retrieve (flag = any(nfsphys.mach_id where nfsphys.mach_id=@id))
448 if (flag)
449 return(SMS_IN_USE);
450## repeat retrieve (flag = any(hostaccess.mach_id where hostaccess.mach_id=@id))
451 if (flag)
452 return(SMS_IN_USE);
453## repeat retrieve (flag = any(pcap.mach_id where pcap.mach_id=@id))
454 if (flag)
455 return(SMS_IN_USE);
456
457## repeat delete mcmap where mcmap.mach_id = @id
458 return(SMS_SUCCESS);
459##}
460
461
462/* setup_dclu - verify that the cluster is no longer being referenced
463 * and may safely be deleted.
464 */
465
466int setup_dclu(q, argv)
467 struct query *q;
468 char **argv;
469##{
470## int flag, id;
471
472 id = *(int *)argv[0];
473## repeat retrieve (flag = any(mcmap.mach_id where mcmap.clu_id=@id))
474 if (flag)
475 return(SMS_IN_USE);
476## repeat retrieve (flag = any(svc.clu_id where svc.clu_id=@id))
477 if (flag)
478 return(SMS_IN_USE);
479 else
480 return(SMS_SUCCESS);
481##}
482
483
484/* setup_alis - if argv[5] is non-zero and argv[6] is UNIQUE_ID, then allocate
485 * a new gid and put it in argv[6]. Otherwise if argv[6] is UNIQUE_ID but
486 * argv[5] is not, then remember that UNIQUE_ID is being stored by putting
487 * a -1 there. Remember that this is also used for ulis, with the indexes
488 * at 6 & 7.
489 */
490
491int setup_alis(q, argv)
492struct query *q;
493char **argv;
494##{
495## int ngid;
496 char *malloc();
497 int idx;
498
499 if (!strcmp(q->shortname, "alis"))
500 idx = 6;
501 else if (!strcmp(q->shortname, "ulis"))
502 idx = 7;
503
504 if (!strcmp(argv[idx], UNIQUE_GID) || atoi(argv[idx]) == -1) {
505 if (atoi(argv[idx - 1])) {
506 if (set_next_object_id("gid", "list"))
507 return(SMS_INGRES_ERR);
508## repeat retrieve (ngid = values.value) where values.name = "gid"
509 sprintf(argv[idx], "%d", ngid);
510 } else {
511 strcpy(argv[idx], "-1");
512 }
513 }
514
515 return(SMS_SUCCESS);
516##}
517
518
519/* setup_dlist - verify that the list is no longer being referenced
520 * and may safely be deleted.
521 */
522
523int setup_dlis(q, argv)
524 struct query *q;
525 char **argv;
526##{
527## int flag, id;
528
529 id = *(int *)argv[0];
530## repeat retrieve (flag = any(members.member_id where members.member_id=@id
531## and members.member_type = "LIST"))
532 if (flag)
533 return(SMS_IN_USE);
534## repeat retrieve (flag = any(members.member_id where members.list_id=@id))
535 if (flag)
536 return(SMS_IN_USE);
537## repeat retrieve (flag = any(filesys.label where filesys.owners=@id))
538 if (flag)
539 return(SMS_IN_USE);
540## repeat retrieve (flag = any(capacls.tag where capacls.list_id=@id))
541 if (flag)
542 return(SMS_IN_USE);
543## repeat retrieve (flag = any(list.name where list.acl_id=@id and
544## list.acl_type = "LIST" and list.list_id != @id))
545 if (flag)
546 return(SMS_IN_USE);
547## repeat retrieve (flag = any(servers.name where servers.acl_id=@id and
548## servers.acl_type = "LIST"))
549 if (flag)
550 return(SMS_IN_USE);
551## repeat retrieve (flag=any(hostaccess.acl_id where hostaccess.acl_id=@id and
552## hostaccess.acl_type = "LIST"))
553 if (flag)
554 return(SMS_IN_USE);
555## repeat retrieve (flag = any(zephyr.class
556## where zephyr.xmt_type = "LIST" and zephyr.xmt_id = @id or
557## zephyr.sub_type = "LIST" and zephyr.sub_id = @id or
558## zephyr.iws_type = "LIST" and zephyr.iws_id = @id or
559## zephyr.iui_type = "LIST" and zephyr.iui_id = @id))
560 if (flag)
561 return(SMS_IN_USE);
562 else
563 return(SMS_SUCCESS);
564##}
565
566
567/* setup_dsin - verify that the service is no longer being referenced
568 * and may safely be deleted.
569 */
570
571int setup_dsin(q, argv)
572 struct query *q;
573 char **argv;
574##{
575## int flag;
576## char *name;
577
578 name = argv[0];
579## repeat retrieve (flag = any(serverhosts.service
580## where serverhosts.service=uppercase(@name)))
581 if (flag)
582 return(SMS_IN_USE);
583## repeat retrieve (flag = servers.inprogress) where servers.#name = @name
584 if (flag)
585 return(SMS_IN_USE);
586 else
587 return(SMS_SUCCESS);
588##}
589
590
591/* setup_dshi - verify that the service-host is no longer being referenced
592 * and may safely be deleted.
593 */
594
595int setup_dshi(q, argv)
596 struct query *q;
597 char **argv;
598##{
599## int flag, id;
600## char *name;
601
602 name = argv[0];
603 id = *(int *)argv[1];
604## repeat retrieve (flag=serverhosts.inprogress)
605## where serverhosts.service=uppercase(@name) and serverhosts.mach_id=@id
606 if (flag)
607 return(SMS_IN_USE);
608 else
609 return(SMS_SUCCESS);
610##}
611
612
613/**
614 ** setup_add_filesys - verify existance of referenced file systems
615 **
616 ** Inputs: Add
617 ** argv[1] - type
618 ** argv[2] - mach_id
619 ** argv[3] - name
620 ** argv[5] - access
621 **
622 ** Description:
623 ** - for type = RVD:
624 ** * allow anything
625 ** - for type = NFS:
626 ** * extract directory prefix from name
627 ** * verify mach_id/dir in nfsphys
628 ** * verify access in {r, w, R, W}
629 **
630 ** Side effect: sets variable var_phys_id to the ID of the physical
631 ** filesystem (nfsphys_id for NFS, 0 for RVD)
632 **
633 ** Errors:
634 ** SMS_NFS - specified directory not exported
635 ** SMS_FILESYS_ACCESS - invalid filesys access
636 **
637 **/
638
639##static int var_phys_id;
640
641setup_afil(q, argv)
642 struct query *q;
643 char *argv[];
644{
645 char *type;
646 int mach_id;
647 char *name;
648 char *access;
649
650 type = argv[1];
651 mach_id = *(int *)argv[2];
652 name = argv[3];
653 access = argv[5];
654 var_phys_id = 0;
655
656 if (!strcmp(type, "NFS"))
657 return (check_nfs(mach_id, name, access));
658 else
659 return(SMS_SUCCESS);
660}
661
662
663setup_ufil(q, argv)
664 struct query *q;
665 char *argv[];
666{
667 char *type;
668 int mach_id;
669 char *name;
670 char *access;
671
672 type = argv[2];
673 mach_id = *(int *)argv[3];
674 name = argv[4];
675 access = argv[6];
676 var_phys_id = 0;
677
678 if (!strcmp(type, "NFS"))
679 return (check_nfs(mach_id, name, access));
680 else
681 return(SMS_SUCCESS);
682}
683
684
685/* Find the NFS physical partition that the named directory is on.
686 * This is done by comparing the dir against the mount point of the
687 * partition. To make sure we get the correct match when there is
688 * more than one, we sort the query in reverse order by dir name.
689 */
690
691##check_nfs(mach_id, name, access)
692## int mach_id;
693 char *name;
694 char *access;
695##{
696## char dir[32];
697 char caccess;
698 register int status;
699 register char *cp1;
700 register char *cp2;
701
702 caccess = (isupper(*access)) ? tolower(*access) : *access;
703 if (caccess != 'r' && caccess != 'w') return(SMS_FILESYS_ACCESS);
704
705 status = SMS_NFS;
706## range of np is nfsphys
707## repeat retrieve (var_phys_id = np.#nfsphys_id, dir = trim(np.#dir))
708## where np.#mach_id = @mach_id sort by #dir:d {
709 cp1 = name;
710 cp2 = dir;
711 while (*cp2) {
712 if (*cp1++ != *cp2) break;
713 cp2++;
714 }
715 if (*cp2 == 0) {
716 status = SMS_SUCCESS;
717## endretrieve
718 }
719## }
720
721 return(status);
722##}
723
724
725/* setup_dfil: free any quota records associated with a filesystem
726 * when it is deleted.
727 */
728
729setup_dfil(q, argv, cl)
730 struct query *q;
731 char **argv;
732 client *cl;
733##{
734## int id;
735
736 id = *(int *)argv[0];
737## range of q is nfsquota
738## range of fs is filesys
739## range of n is nfsphys
740## repeat replace n (allocated=n.allocated-sum(q.quota where q.filsys_id=@id))
741## where n.nfsphys_id = fs.phys_id and fs.filsys_id = @id
742
743## repeat delete q where q.filsys_id = @id
744 return(SMS_SUCCESS);
745##}
746
747
748/* setup_dnfp: check to see that the nfs physical partition does not have
749 * any filesystems assigned to it before allowing it to be deleted.
750 */
751
752setup_dnfp(q, argv, cl)
753 struct query *q;
754 char **argv;
755 client *cl;
756##{
757## int id, exists;
758
759 id = *(int *)argv[0];
760## repeat retrieve (exists = any(filesys.label where filesys.phys_id = @id))
761 if (exists)
762 return(SMS_IN_USE);
763 return(SMS_SUCCESS);
764##}
765
766
767/* setup_dnfq: Remove allocation from nfsphys before deleting quota.
768 * argv[0] = filsys_id
769 * argv[1] = users_id
770 */
771
772setup_dnfq(q, argv, cl)
773 struct query *q;
774 char **argv;
775 client *cl;
776##{
777## int quota, fs, user;
778
779 fs = *(int *)argv[0];
780 user = *(int *)argv[1];
781
782## range of q is nfsquota
783## repeat retrieve (quota = q.#quota) where q.users_id = @user and
784## q.filsys_id = @fs
785## repeat replace nfsphys (allocated = nfsphys.allocated - @quota)
786## where nfsphys.nfsphys_id = filesys.#phys_id and filesys.filsys_id = @fs
787 return(SMS_SUCCESS);
788##}
789
790
791\f
792/* FOLLOWUP ROUTINES */
793
794/* generic set_modtime routine. This takes the table name from the query,
795 * and will update the modtime, modby, and modwho fields in the entry in
796 * the table whose name field matches argv[0].
797 */
798
799set_modtime(q, argv, cl)
800 struct query *q;
801 char *argv[];
802 client *cl;
803##{
804## char *name, *entity, *table;
805## int who;
806
807 entity = cl->entity;
808 who = cl->users_id;
809 table = q->rtable;
810 name = argv[0];
811
812## replace table (modtime = "now", modby = who, modwith = entity)
813## where table.#name = name
814 return(SMS_SUCCESS);
815##}
816
817/* generic set_modtime_by_id routine. This takes the table name from
818 * the query, and the id name from the validate record,
819 * and will update the modtime, modby, and modwho fields in the entry in
820 * the table whose id matches argv[0].
821 */
822
823set_modtime_by_id(q, argv, cl)
824 struct query *q;
825 char **argv;
826 client *cl;
827##{
828## char *entity, *table, *id_name;
829## int who, id;
830
831 entity = cl->entity;
832 who = cl->users_id;
833 table = q->rtable;
834 id_name = q->validate->object_id;
835
836 id = *(int *)argv[0];
837## replace table (modtime = "now", modby = who, modwith = entity)
838## where table.id_name = id
839 return(SMS_SUCCESS);
840##}
841
842
843/* Sets the finger modtime on a user record. The users_id will be in argv[0].
844 */
845
846set_finger_modtime(q, argv, cl)
847 struct query *q;
848 char *argv[];
849 client *cl;
850##{
851## int users_id, who;
852## char *entity;
853
854 entity = cl->entity;
855 who = cl->users_id;
856 users_id = *(int *)argv[0];
857
858## repeat replace u (fmodtime = "now", fmodby = @who, fmodwith = @entity)
859## where u.#users_id = @users_id
860 return(SMS_SUCCESS);
861##}
862
863
864/* Sets the pobox modtime on a user record. The users_id will be in argv[0].
865 */
866
867set_pobox_modtime(q, argv, cl)
868 struct query *q;
869 char **argv;
870 client *cl;
871##{
872## int users_id, who;
873## char *entity;
874
875 entity = cl->entity;
876 who = cl->users_id;
877 users_id = *(int *)argv[0];
878
879## repeat replace users (pmodtime = "now", pmodby = @who, pmodwith = @entity)
880## where users.#users_id = @users_id
881 return(SMS_SUCCESS);
882##}
883
884
885/* Sets the modtime on a machine record. The machine name is in argv[0].
886 * This routine is different from the generic set_modtime in that the
887 * name is uppercased first.
888 */
889
890set_mach_modtime(q, argv, cl)
891 struct query *q;
892 char **argv;
893 client *cl;
894##{
895## char *host, *entity;
896## int who;
897
898 entity = cl->entity;
899 who = cl->users_id;
900
901 host = argv[0];
902## repeat replace m (modtime = "now", modby = @who, modwith = @entity)
903## where m.name = uppercase(@host)
904 return(SMS_SUCCESS);
905##}
906
907
908/* Sets the modtime on the machine whose mach_id is in argv[0]. This routine
909 * is necessary for add_machine_to_cluster becuase the table that query
910 * operates on is "mcm", not "machine".
911 */
912
913set_mach_modtime_by_id(q, argv, cl)
914 struct query *q;
915 char **argv;
916 client *cl;
917##{
918## char *entity;
919## int who, id;
920
921 entity = cl->entity;
922 who = cl->users_id;
923
924 id = *(int *)argv[0];
925## range of m is machine
926## repeat replace m (modtime = "now", modby = @who, modwith = @entity)
927## where m.mach_id = @id
928 return(SMS_SUCCESS);
929##}
930
931
932/* Sets the modtime on the cluster whose mach_id is in argv[0]. This routine
933 * is necessary for add_cluster_data and delete_cluster_data becuase the
934 * table that query operates on is "svc", not "cluster".
935 */
936
937set_cluster_modtime_by_id(q, argv, cl)
938 struct query *q;
939 char **argv;
940 client *cl;
941##{
942## char *entity;
943## int who, id;
944
945 entity = cl->entity;
946 who = cl->users_id;
947
948 id = *(int *)argv[0];
949## range of c is cluster
950## repeat replace c (modtime = "now", modby = @who, modwith = @entity)
951## where c.clu_id = @id
952 return(SMS_SUCCESS);
953##}
954
955
956/* sets the modtime on the serverhost where the service name is in argv[0]
957 * and the mach_id is in argv[1].
958 */
959
960set_serverhost_modtime(q, argv, cl)
961 struct query *q;
962 char **argv;
963 client *cl;
964##{
965## char *entity, *serv;
966## int who, id;
967
968 entity = cl->entity;
969 who = cl->users_id;
970
971 serv = argv[0];
972 id = *(int *)argv[1];
973## repeat replace sh (modtime = "now", modby = @who, modwith = @entity)
974## where sh.service = uppercase(@serv) and sh.mach_id = @id
975 return(SMS_SUCCESS);
976##}
977
978
979/* sets the modtime on the nfsphys where the mach_id is in argv[0] and the
980 * directory name is in argv[1].
981 */
982
983set_nfsphys_modtime(q, argv, cl)
984 struct query *q;
985 char **argv;
986 client *cl;
987##{
988## char *entity, *dir;
989## int who, id;
990
991 entity = cl->entity;
992 who = cl->users_id;
993
994 id = *(int *)argv[0];
995 dir = argv[1];
996## repeat replace np (modtime = "now", modby = @who, modwith = @entity)
997## where np.#dir = @dir and np.mach_id = @id
998 return(SMS_SUCCESS);
999##}
1000
1001
1002/* sets the modtime on a filesystem, where argv[0] contains the filesys
1003 * label.
1004 */
1005
1006set_filesys_modtime(q, argv, cl)
1007 struct query *q;
1008 char *argv[];
1009 client *cl;
1010##{
1011## char *label, *entity;
1012## int who;
1013
1014 entity = cl->entity;
1015 who = cl->users_id;
1016
1017 label = argv[0];
1018 if (!strcmp(q->shortname, "ufil"))
1019 label = argv[1];
1020
1021## repeat replace fs (modtime = "now", modby = @who, modwith = @entity,
1022## #phys_id = @var_phys_id) where fs.#label = @label
1023 return(SMS_SUCCESS);
1024##}
1025
1026
1027/* sets the modtime on a zephyr class, where argv[0] contains the class
1028 * name.
1029 */
1030
1031set_zephyr_modtime(q, argv, cl)
1032 struct query *q;
1033 char *argv[];
1034 client *cl;
1035##{
1036## char *class, *entity;
1037## int who;
1038
1039 entity = cl->entity;
1040 who = cl->users_id;
1041
1042 class = argv[0];
1043
1044## repeat replace z (modtime = "now", modby = @who, modwith = @entity)
1045## where z.#class = @class
1046 return(SMS_SUCCESS);
1047##}
1048
1049
1050/* fixes the modby field. This will be the second to last thing in the
1051 * argv, the argv length is determined from the query structure. It is
1052 * passed as a pointer to an integer. This will either turn it into a
1053 * username, or # + the users_id.
1054 */
1055followup_fix_modby(q, sq, v, action, actarg, cl)
1056 struct query *q;
1057 register struct save_queue *sq;
1058 struct validate *v;
1059 register int (*action)();
1060 register int actarg;
1061 client *cl;
1062##{
1063 register int i, j;
1064 char **argv, *malloc();
1065## int id, rowcount;
1066## char *name;
1067
1068 i = q->vcnt - 2;
1069 while (sq_get_data(sq, &argv)) {
1070 id = atoi(argv[i]);
1071 free(argv[i]);
1072 argv[i] = malloc(9);
1073 name = argv[i];
1074## repeat retrieve (name = users.login) where users.users_id = @id
1075## inquire_equel(rowcount = "rowcount")
1076 if (rowcount != 1) {
1077 sprintf(argv[i], "#%d", id);
1078 }
1079 (*action)(q->vcnt, argv, actarg);
1080 for (j = 0; j < q->vcnt; j++)
1081 free(argv[j]);
1082 free(argv);
1083 }
1084 sq_destroy(sq);
1085 return(SMS_SUCCESS);
1086##}
1087
1088
1089/**
1090 ** followup_ausr - add finger and pobox entries, set_user_modtime
1091 **
1092 ** Inputs:
1093 ** argv[0] - login (add_user)
1094 ** argv[3] - last name
1095 ** argv[4] - first name
1096 ** argv[5] - middle name
1097 **
1098 **/
1099
1100followup_ausr(q, argv, cl)
1101 struct query *q;
1102 char *argv[];
1103 client *cl;
1104##{
1105## int who;
1106## char *login, *entity;
1107## char fullname[129];
1108
1109 login = argv[0];
1110 who = cl->users_id;
1111 entity = cl->entity;
1112
1113 /* build fullname */
1114 if (strlen(argv[4]) && strlen(argv[5]))
1115 sprintf(fullname, "%s %s %s", argv[4], argv[5], argv[3]);
1116 else if (strlen(argv[4]))
1117 sprintf(fullname, "%s %s", argv[4], argv[3]);
1118 else
1119 sprintf(fullname, "%s", argv[3]);
1120
1121 /* create finger entry, pobox & set modtime on user */
1122## repeat replace u (modtime = "now", modby=@who, modwith=@entity,
1123## #fullname=@fullname, mit_affil = u.mit_year,
1124## fmodtime="now", fmodby=@who, fmodwith=@entity,
1125## potype="NONE", pmodtime="now", pmodby=@who, pmodwith=@entity)
1126## where u.#login = @login
1127
1128 return(SMS_SUCCESS);
1129##}
1130
1131
1132/* followup_gpob: fixes argv[2] based on the IDs currently there and the
1133 * type in argv[1]. Then completes the upcall to the user.
1134 *
1135 * argv[2] is of the form "123:234" where the first integer is the machine
1136 * ID if it is a pop box, and the second is the string ID if it is an SMTP
1137 * box. argv[1] should be "POP", "SMTP", or "NONE". Boxes of type NONE
1138 * are skipped.
1139 */
1140
1141followup_gpob(q, sq, v, action, actarg, cl)
1142 register struct query *q;
1143 register struct save_queue *sq;
1144 register struct validate *v;
1145 register int (*action)();
1146 int actarg;
1147 client *cl;
1148##{
1149 char **argv, *index();
1150 char *ptype, *p;
1151## char box[129], *name;
1152## int mid, sid, rowcount;
1153
1154 /* for each row */
1155 while (sq_get_data(sq, &argv)) {
1156 sms_trim_args(2, argv);
1157 ptype = argv[1];
1158 p = index(argv[2], ':');
1159 *p++ = 0;
1160 mid = atoi(argv[2]);
1161 sid = atoi(p);
1162 free(argv[2]);
1163
1164 if (!strcmp(ptype, "POP")) {
1165## repeat retrieve (box=machine.#name) where machine.mach_id=@mid
1166## inquire_equel(rowcount = "rowcount")
1167 if (rowcount != 1)
1168 return(SMS_MACHINE);
1169 } else if (!strcmp(ptype, "SMTP")) {
1170## repeat retrieve (box=strings.string) where strings.string_id=@sid
1171## inquire_equel(rowcount = "rowcount")
1172 if (rowcount != 1)
1173 return(SMS_STRING);
1174 } else /* ptype == "NONE" */ {
1175 goto skip;
1176 }
1177
1178 if (!strcmp(q->shortname, "gpob")) {
1179 sid = atoi(argv[4]);
1180 free(argv[4]);
1181 argv[4] = malloc(9);
1182 name = argv[4];
1183## repeat retrieve (name = users.login) where users.users_id = @sid
1184## inquire_equel(rowcount = "rowcount")
1185 if (rowcount != 1)
1186 sprintf(name, "#%d", sid);
1187 }
1188
1189 argv[2] = box;
1190 (*action)(q->vcnt, argv, actarg);
1191 skip:
1192 /* free saved data */
1193 free(argv[0]);
1194 free(argv[1]);
1195 free(argv);
1196 }
1197
1198 sq_destroy(sq);
1199 return (SMS_SUCCESS);
1200##}
1201
1202
1203/* followup_glin: fix the ace_name in argv[8]. argv[7] will contain the
1204 * ace_type: "LIST", "USER", or "NONE". Decode the id in argv[8] into the
1205 * proper name based on the type, and repace that string in the argv.
1206 * Also fixes the modby field by called followup_fix_modby.
1207 */
1208
1209followup_glin(q, sq, v, action, actarg, cl)
1210 register struct query *q;
1211 register struct save_queue *sq;
1212 register struct validate *v;
1213 register int (*action)();
1214 int actarg;
1215 client *cl;
1216##{
1217 char **argv, *malloc(), *realloc(), *type;
1218## char *name;
1219## int id, rowcount;
1220 int i, idx;
1221
1222 idx = 8;
1223 if (!strcmp(q->shortname, "gsin"))
1224 idx = 12;
1225
1226 while (sq_get_data(sq, &argv)) {
1227 sms_trim_args(q->vcnt, argv);
1228
1229 id = atoi(argv[i = q->vcnt - 2]);
1230 free(argv[i]);
1231 name = argv[i] = malloc(9);
1232## repeat retrieve (name = users.login) where users.users_id = @id
1233## inquire_equel(rowcount = "rowcount")
1234 if (rowcount != 1)
1235 sprintf(argv[i], "#%d", id);
1236
1237 id = atoi(argv[idx]);
1238 type = argv[idx - 1];
1239 if ((name = malloc(33)) == NULL)
1240 return(SMS_NO_MEM);
1241
1242 if (!strcmp(type, "LIST")) {
1243## repeat retrieve (name = list.#name) where list.list_id = @id
1244## inquire_equel(rowcount = "rowcount")
1245 if (rowcount != 1)
1246 strcpy(name, "???");
1247 } else if (!strcmp(type, "USER")) {
1248## repeat retrieve (name = users.login) where users.users_id = @id
1249## inquire_equel(rowcount = "rowcount")
1250 if (rowcount != 1)
1251 strcpy(name, "???");
1252 } else if (!strcmp(type, "NONE")) {
1253 strcpy(name, "NONE");
1254 } else
1255 strcpy(name, "???");
1256 free(argv[idx]);
1257 argv[idx] = name;
1258
1259 if (!strcmp(q->shortname, "glin") && atoi(argv[6]) == -1) {
1260 argv[6] = realloc(argv[6], strlen(UNIQUE_GID) + 1);
1261 strcpy(argv[6], UNIQUE_GID);
1262 }
1263
1264 /* send the data */
1265 (*action)(q->vcnt, argv, actarg);
1266
1267 /* free saved data */
1268 for (i = 0; i < q->vcnt; i++)
1269 free(argv[i]);
1270 free(argv);
1271 }
1272
1273 sq_destroy(sq);
1274 return (SMS_SUCCESS);
1275##}
1276
1277
1278/** followup_amtl - followup for amtl and dmfl; when adding a list
1279 ** member to a maillist, make member list a maillist also
1280 ** unless list is a user-group.
1281 ** Then set_list_modtime_by_id.
1282 **
1283 ** Inputs:
1284 ** argv[0] - list_id
1285 ** argv[1] - member_type
1286 ** argv[2] - member_id
1287 **
1288 **/
1289
1290followup_amtl(q, argv, cl)
1291 struct query *q;
1292 char *argv[];
1293 client *cl;
1294##{
1295## int list_id;
1296## int member_id;
1297## int exists, who;
1298## char *entity;
1299
1300 list_id = *(int *)argv[0];
1301 entity = cl->entity;
1302 who = cl->users_id;
1303
1304## range of l is list
1305## repeat replace l (modtime = "now", modby = @who, modwith = @entity)
1306## where l.#list_id = @list_id
1307
1308 /* if query is not amtl or if member_type is not LIST then return */
1309 if (bcmp(q->shortname, "amtl", 4) || bcmp(argv[1], "LIST", 4))
1310 return(SMS_SUCCESS);
1311
1312 member_id = *(int *)argv[2];
1313
1314 /* is parent list a mailing list? */
1315## repeat retrieve (exists = l.maillist) where l.#list_id=@list_id
1316 if (!exists)
1317 return(SMS_SUCCESS);
1318
1319 /* list is not a user-group; add list to maillist table */
1320## repeat replace l (maillist = 1) where l.#list_id = @member_id
1321 return(SMS_SUCCESS);
1322##}
1323
1324
1325/* followup_anfq: Add allocation to nfsphys after creating quota.
1326 * argv[0] = filsys_id
1327 * argv[2] = ascii(quota)
1328 */
1329
1330followup_anfq(q, argv, cl)
1331 struct query *q;
1332 char **argv;
1333 client *cl;
1334##{
1335## int quota, user, fs, who;
1336## char *entity;
1337
1338 fs = *(int *)argv[0];
1339 user = *(int *)argv[1];
1340 quota = atoi(argv[2]);
1341 who = cl->users_id;
1342 entity = cl->entity;
1343
1344## repeat replace nq (modtime = "now", modby = @who, modwith = @entity)
1345## where nq.filsys_id = @fs and nq.users_id = @user
1346## repeat replace nfsphys (allocated = nfsphys.allocated + @quota)
1347## where nfsphys.nfsphys_id = filesys.#phys_id and filesys.filsys_id = @fs
1348 return(SMS_SUCCESS);
1349##}
1350
1351
1352/* followup_gzcl:
1353 */
1354
1355followup_gzcl(q, sq, v, action, actarg, cl)
1356 register struct query *q;
1357 register struct save_queue *sq;
1358 register struct validate *v;
1359 register int (*action)();
1360 int actarg;
1361 client *cl;
1362##{
1363## char *name;
1364## int rowcount, id;
1365 char **argv;
1366 int i;
1367
1368 while (sq_get_data(sq, &argv)) {
1369 sms_trim_args(q->vcnt, argv);
1370
1371 id = atoi(argv[i = q->vcnt - 2]);
1372 free(argv[i]);
1373 name = argv[i] = malloc(9);
1374## repeat retrieve (name = users.login) where users.users_id = @id
1375## inquire_equel(rowcount = "rowcount")
1376 if (rowcount != 1)
1377 sprintf(argv[i], "#%d", id);
1378
1379 for (i = 1; i < 8; i+=2) {
1380 id = atoi(argv[i+1]);
1381 free(argv[i+1]);
1382 if ((name = argv[i+1] = malloc(33)) == NULL)
1383 return(SMS_NO_MEM);
1384 if (!strcmp(argv[i], "LIST")) {
1385## repeat retrieve (name = list.#name) where list.list_id = @id
1386## inquire_equel(rowcount = "rowcount")
1387 if (rowcount != 1)
1388 strcpy(name, "???");
1389 } else if (!strcmp(argv[i], "USER")) {
1390## repeat retrieve (name = users.login) where users.users_id = @id
1391## inquire_equel(rowcount = "rowcount")
1392 if (rowcount != 1)
1393 strcpy(name, "???");
1394 } else if (!strcmp(argv[i], "NONE")) {
1395 strcpy(name, "NONE");
1396 } else {
1397 strcpy(name, "???");
1398 }
1399 }
1400
1401 /* send the data */
1402 (*action)(q->vcnt, argv, actarg);
1403
1404 /* free saved data */
1405 for (i = 0; i < q->vcnt; i++)
1406 free(argv[i]);
1407 free(argv);
1408 }
1409 sq_destroy(sq);
1410 return(SMS_SUCCESS);
1411##}
1412
1413
1414/* followup_gsha:
1415 */
1416
1417followup_gsha(q, sq, v, action, actarg, cl)
1418 register struct query *q;
1419 register struct save_queue *sq;
1420 register struct validate *v;
1421 register int (*action)();
1422 int actarg;
1423 client *cl;
1424##{
1425## char *name;
1426## int rowcount, id;
1427 char **argv;
1428 int i;
1429
1430 while (sq_get_data(sq, &argv)) {
1431 sms_trim_args(q->vcnt, argv);
1432
1433 id = atoi(argv[4]);
1434 free(argv[4]);
1435 name = argv[4] = malloc(9);
1436## repeat retrieve (name = users.login) where users.users_id = @id
1437## inquire_equel(rowcount = "rowcount")
1438 if (rowcount != 1)
1439 sprintf(argv[4], "#%d", id);
1440
1441 id = atoi(argv[2]);
1442 free(argv[2]);
1443 if ((name = argv[2] = malloc(33)) == NULL)
1444 return(SMS_NO_MEM);
1445 if (!strcmp(argv[1], "LIST")) {
1446## repeat retrieve (name = list.#name) where list.list_id = @id
1447## inquire_equel(rowcount = "rowcount")
1448 if (rowcount != 1)
1449 strcpy(name, "???");
1450 } else if (!strcmp(argv[1], "USER")) {
1451## repeat retrieve (name = users.login) where users.users_id = @id
1452## inquire_equel(rowcount = "rowcount")
1453 if (rowcount != 1)
1454 strcpy(name, "???");
1455 } else if (!strcmp(argv[1], "NONE")) {
1456 strcpy(name, "NONE");
1457 } else {
1458 strcpy(name, "???");
1459 }
1460
1461 /* send the data */
1462 (*action)(q->vcnt, argv, actarg);
1463
1464 /* free saved data */
1465 for (i = 0; i < q->vcnt; i++)
1466 free(argv[i]);
1467 free(argv);
1468 }
1469 sq_destroy(sq);
1470 return(SMS_SUCCESS);
1471##}
1472
1473
1474\f
1475/* Special query routines */
1476
1477/* set_pobox - this does all of the real work.
1478 * argv = user_id, type, box
1479 * if type is POP, then box should be a machine, and its ID should be put in
1480 * pop_id. If type is SMTP, then box should be a string and its ID should
1481 * be put in box_id. If type is NONE, then box doesn't matter.
1482 */
1483
1484int set_pobox(q, argv, cl)
1485 struct query *q;
1486 char **argv;
1487 client *cl;
1488##{
1489## int user, id, rowcount;
1490## char *box, potype[9];
1491
1492 box = argv[2];
1493 user = *(int *)argv[0];
1494
1495## repeat retrieve (id = users.pop_id, potype = users.#potype)
1496## where users.users_id = @user
1497 if (!strcmp(potype, "POP"))
1498 set_pop_usage(id, -1);
1499
1500 if (!strcmp(argv[1], "POP")) {
1501## repeat retrieve (id=machine.mach_id) where machine.name=uppercase(@box)
1502## inquire_equel(rowcount = "rowcount")
1503 if (rowcount != 1)
1504 return(SMS_MACHINE);
1505## repeat replace users (#potype = "POP", pop_id = @id)
1506## where users.users_id = @user
1507 set_pop_usage(id, 1);
1508 } else if (!strcmp(argv[1], "SMTP")) {
1509## range of s is strings
1510## repeat retrieve (id = s.string_id) where s.string = @box
1511## inquire_equel (rowcount = "rowcount")
1512 if (rowcount == 0) {
1513## range of v is values
1514## repeat retrieve (id = v.value) where v.name = "strings_id"
1515 id++;
1516## repeat replace v (value = @id) where v.name = "strings_id"
1517## append to strings (string_id = id, string = box)
1518 }
1519## repeat replace users (#potype = "SMTP", box_id = @id)
1520## where users.users_id = @user
1521 } else /* argv[1] == "NONE" */ {
1522## repeat replace users (#potype = "NONE") where users.users_id = @user
1523 }
1524
1525 set_pobox_modtime(q, argv, cl);
1526## repeat replace tblstats (updates = tblstats.updates + 1, modtime = "now")
1527## where tblstats.#table = "users"
1528 return(SMS_SUCCESS);
1529##}
1530
1531
1532/* get_list_info: passed a wildcard list name, returns lots of stuff about
1533 * each list. This is tricky: first build a queue of all requested
1534 * data. Rest of processing consists of fixing gid, ace_name, and modby.
1535 */
1536
1537get_list_info(q, aargv, cl, action, actarg)
1538 register struct query *q;
1539 char **aargv;
1540 client *cl;
1541 register int (*action)();
1542 int actarg;
1543##{
1544 char *argv[13], *malloc(), *realloc();
1545## char *name, acl_type[9], listname[33], active[5], public[5], hidden[5];
1546## char maillist[5], group[5], gid[6], acl_name[33], desc[256], modtime[27];
1547## char modby[9], modwith[9];
1548## int id, rowcount, acl_id, hid, modby_id;
1549 int returned;
1550 struct save_queue *sq, *sq_create();
1551
1552 returned = rowcount = 0;
1553 name = aargv[0];
1554
1555 sq = sq_create();
1556## range of l is list
1557## repeat retrieve (id = l.list_id) where l.#name = @name {
1558 sq_save_data(sq, id);
1559 rowcount++;
1560## }
1561 if (rowcount == 0)
1562 return(SMS_NO_MATCH);
1563
1564 argv[0] = listname; argv[1] = active; argv[2] = public; argv[3] = hidden;
1565 argv[4] = maillist; argv[5] = group; argv[6] = gid; argv[7] = acl_type;
1566 argv[8] = acl_name; argv[9] = desc; argv[10] = modtime; argv[11] = modby;
1567 argv[12] = modwith;
1568
1569 while (sq_get_data(sq, &id)) {
1570 if (id == 0)
1571 continue;
1572 argv[6] = gid;
1573## repeat retrieve (listname = l.#name, active = text(l.#active),
1574## public = text(l.#public), hidden = text(l.#hidden),
1575## hid = l.#hidden, maillist = text(l.#maillist),
1576## group = text(l.#group), gid = text(l.#gid),
1577## acl_type = trim(l.#acl_type), acl_id = l.#acl_id,
1578## desc = l.#desc, modtime = l.#modtime, modby_id = l.#modby,
1579## modwith =l.#modwith)
1580## where l.list_id = @id
1581
1582 if (atoi(gid) == -1)
1583 argv[6] = UNIQUE_GID;
1584
1585 if (!strcmp(acl_type, "LIST")) {
1586## repeat retrieve (acl_name = l.#name) where l.list_id = @acl_id
1587## inquire_equel(rowcount = "rowcount")
1588 if (rowcount != 1)
1589 strcpy(acl_name, "???");
1590 } else if (!strcmp(acl_type, "USER")) {
1591## repeat retrieve (acl_name = users.#login)
1592## where users.users_id = @acl_id
1593## inquire_equel(rowcount = "rowcount")
1594 if (rowcount != 1)
1595 strcpy(acl_name, "???");
1596 } else if (!strcmp(acl_type, "NONE")) {
1597 strcpy(acl_name, "NONE");
1598 } else
1599 strcpy(acl_name, "???");
1600
1601## repeat retrieve (modby = users.login) where users.users_id = @modby_id
1602## inquire_equel(rowcount = "rowcount")
1603 if (rowcount != 1)
1604 sprintf(modby, "#%d", id);
1605
1606 sms_trim_args(q->vcnt, argv);
1607 returned++;
1608 (*action)(q->vcnt, argv, actarg);
1609 }
1610
1611 sq_destroy(sq);
1612## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
1613## where tblstats.#table = "list"
1614
1615 return (SMS_SUCCESS);
1616##}
1617
1618
1619/* get_ace_use - given a type and a name, return a type and a name.
1620 * The ace_type is one of "LIST", "USER", "RLIST", or "RUSER" in argv[0],
1621 * and argv[1] will contain the ID of the entity in question. The R*
1622 * types mean to recursively look at every containing list, not just
1623 * when the object in question is a direct member. On return, the
1624 * usage type will be one of LIST, SERVICE, FILESYS, QUOTA, QUERY, or ZEPHYR.
1625 */
1626
1627int get_ace_use(q, argv, cl, action, actarg)
1628 struct query *q;
1629 char *argv[];
1630 client *cl;
1631 int (*action)();
1632 int actarg;
1633##{
1634 int found = 0;
1635## char *atype;
1636## int aid, listid, id;
1637 struct save_queue *sq, *sq_create();
1638
1639 atype = argv[0];
1640 aid = *(int *)argv[1];
1641 if (!strcmp(atype, "LIST") || !strcmp(atype, "USER")) {
1642 return(get_ace_internal(atype, aid, action, actarg));
1643 }
1644
1645 sq = sq_create();
1646 if (!strcmp(atype, "RLIST")) {
1647 sq_save_data(sq, aid);
1648 /* get all the list_id's of containing lists */
1649## range of m is members
1650 while (sq_get_data(sq, &id)) {
1651## repeat retrieve (listid = m.list_id)
1652## where m.member_type = "LIST" and m.member_id = @id {
1653 sq_save_unique_data(sq, listid);
1654## }
1655 }
1656 /* now process each one */
1657 while (sq_get_data(sq, &id)) {
1658 if (get_ace_internal("LIST", id, action, actarg) == SMS_SUCCESS)
1659 found++;
1660 }
1661 }
1662
1663 if (!strcmp(atype, "RUSER")) {
1664## range of m is members
1665## repeat retrieve (listid = m.list_id)
1666## where m.member_type = "USER" and m.member_id = @aid {
1667 sq_save_data(sq, listid);
1668## }
1669 /* get all the list_id's of containing lists */
1670 while (sq_get_data(sq, &id)) {
1671## repeat retrieve (listid = m.list_id)
1672## where m.member_type = "LIST" and m.member_id = @id {
1673 sq_save_unique_data(sq, listid);
1674## }
1675 }
1676 /* now process each one */
1677 while (sq_get_data(sq, &id)) {
1678 if (get_ace_internal("LIST", id, action, actarg) == SMS_SUCCESS)
1679 found++;
1680 }
1681 if (get_ace_internal("USER", aid, action, actarg) == SMS_SUCCESS)
1682 found++;
1683 }
1684
1685 sq_destroy(sq);
1686 if (!found) return(SMS_NO_MATCH);
1687 return(SMS_SUCCESS);
1688##}
1689
1690
1691/* This looks up a single list or user for ace use. atype must be "USER"
1692 * or "LIST", and aid is the ID of the corresponding object. This is used
1693 * by get_ace_use above.
1694 */
1695
1696##get_ace_internal(atype, aid, action, actarg)
1697## char *atype;
1698## int aid;
1699 int (*action)();
1700 int actarg;
1701##{
1702 char *rargv[2];
1703 int found = 0;
1704## char name[33];
1705
1706 rargv[1] = name;
1707 if (!strcmp(atype, "LIST")) {
1708 rargv[0] = "FILESYS";
1709## repeat retrieve (name = filesys.label)
1710## where filesys.owners = @aid {
1711 (*action)(2, rargv, actarg);
1712 found++;
1713## }
1714
1715 rargv[0] = "QUERY";
1716## repeat retrieve (name = capacls.capability)
1717## where capacls.list_id = @aid {
1718 (*action)(2, rargv, actarg);
1719 found++;
1720## }
1721 } else if (!strcmp(atype, "USER")) {
1722 rargv[0] = "FILESYS";
1723## repeat retrieve (name = filesys.label)
1724## where filesys.owner = @aid {
1725 (*action)(2, rargv, actarg);
1726 found++;
1727## }
1728 }
1729
1730 rargv[0] = "LIST";
1731## repeat retrieve (name = list.#name)
1732## where list.acl_type = @atype and list.acl_id = @aid {
1733 (*action)(2, rargv, actarg);
1734 found++;
1735## }
1736
1737 rargv[0] = "SERVICE";
1738## repeat retrieve (name = servers.#name)
1739## where servers.acl_type = @atype and servers.acl_id = @aid {
1740 (*action)(2, rargv, actarg);
1741 found++;
1742## }
1743
1744 rargv[0] = "HOSTACCESS";
1745## repeat retrieve (name = machine.#name)
1746## where machine.mach_id = hostaccess.mach_id and
1747## hostaccess.acl_type = @atype and hostaccess.acl_id = @aid {
1748 (*action)(2, rargv, actarg);
1749 found++;
1750## }
1751 rargv[0] = "ZEPHYR";
1752## repeat retrieve (name = zephyr.class)
1753## where zephyr.xmt_type = @atype and zephyr.xmt_id = @aid or
1754## zephyr.sub_type = @atype and zephyr.sub_id = @aid or
1755## zephyr.iws_type = @atype and zephyr.iws_id = @aid or
1756## zephyr.iui_type = @atype and zephyr.iui_id = @aid {
1757 (*action)(2, rargv, actarg);
1758 found++;
1759## }
1760
1761 if (!found) return(SMS_NO_MATCH);
1762 return(SMS_SUCCESS);
1763##}
1764
1765
1766/* get_lists_of_member - given a type and a name, return the name and flags
1767 * of all of the lists of the given member. The member_type is one of
1768 * "LIST", "USER", "STRING", "RLIST", "RUSER", or "RSTRING" in argv[0],
1769 * and argv[1] will contain the ID of the entity in question. The R*
1770 * types mean to recursively look at every containing list, not just
1771 * when the object in question is a direct member.
1772 */
1773
1774int get_lists_of_member(q, argv, cl, action, actarg)
1775 struct query *q;
1776 char *argv[];
1777 client *cl;
1778 int (*action)();
1779 int actarg;
1780##{
1781 int found = 0;
1782## char *atype;
1783## int aid, listid, id;
1784 struct save_queue *sq, *sq_create();
1785
1786 atype = argv[0];
1787 aid = *(int *)argv[1];
1788 if (!strcmp(atype, "LIST") ||
1789 !strcmp(atype, "USER") ||
1790 !strcmp(atype, "STRING")) {
1791 return(glom_internal(atype, aid, action, actarg));
1792 }
1793
1794 sq = sq_create();
1795 if (!strcmp(atype, "RLIST")) {
1796 sq_save_data(sq, aid);
1797 /* get all the list_id's of containing lists */
1798## range of m is members
1799 while (sq_get_data(sq, &id)) {
1800## repeat retrieve (listid = m.list_id)
1801## where m.member_type = "LIST" and m.member_id = @id {
1802 sq_save_unique_data(sq, listid);
1803## }
1804 }
1805 /* now process each one */
1806 while (sq_get_data(sq, &id)) {
1807 if (glom_internal("LIST", id, action, actarg) == SMS_SUCCESS)
1808 found++;
1809 }
1810 }
1811
1812 if (!strcmp(atype, "RUSER")) {
1813## range of m is members
1814## repeat retrieve (listid = m.list_id)
1815## where m.member_type = "USER" and m.member_id = @aid {
1816 sq_save_data(sq, listid);
1817## }
1818 /* get all the list_id's of containing lists */
1819 while (sq_get_data(sq, &id)) {
1820## repeat retrieve (listid = m.list_id)
1821## where m.member_type = "LIST" and m.member_id = @id {
1822 sq_save_unique_data(sq, listid);
1823## }
1824 }
1825 /* now process each one */
1826 while (sq_get_data(sq, &id)) {
1827 if (glom_internal("LIST", id, action, actarg) == SMS_SUCCESS)
1828 found++;
1829 }
1830 if (glom_internal("USER", aid, action, actarg) == SMS_SUCCESS)
1831 found++;
1832 }
1833
1834 if (!strcmp(atype, "RSTRING")) {
1835## range of m is members
1836## repeat retrieve (listid = m.list_id)
1837## where m.member_type = "STRING" and m.member_id = @aid {
1838 sq_save_data(sq, listid);
1839## }
1840 /* get all the list_id's of containing lists */
1841 while (sq_get_data(sq, &id)) {
1842## repeat retrieve (listid = m.list_id)
1843## where m.member_type = "LIST" and m.member_id = @id {
1844 sq_save_unique_data(sq, listid);
1845## }
1846 }
1847 /* now process each one */
1848 while (sq_get_data(sq, &id)) {
1849 if (glom_internal("LIST", id, action, actarg) == SMS_SUCCESS)
1850 found++;
1851 }
1852 if (glom_internal("STRING", aid, action, actarg) == SMS_SUCCESS)
1853 found++;
1854 }
1855
1856## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
1857## where tblstats.#table = "members"
1858 sq_destroy(sq);
1859 if (!found) return(SMS_NO_MATCH);
1860 return(SMS_SUCCESS);
1861##}
1862
1863
1864/* This looks up a single list, user, or string as a member. atype must be
1865 * "USER", "LIST", or "STRING" and aid is the ID of the corresponding object.
1866 * This is used by get_lists_of_members above.
1867 */
1868
1869##glom_internal(atype, aid, action, actarg)
1870## char *atype;
1871## int aid;
1872 int (*action)();
1873 int actarg;
1874##{
1875 char *rargv[6];
1876 int found = 0;
1877## char name[33], active[5], public[5], hidden[5], maillist[5], group[5];
1878
1879 rargv[0] = name;
1880 rargv[1] = active;
1881 rargv[2] = public;
1882 rargv[3] = hidden;
1883 rargv[4] = maillist;
1884 rargv[5] = group;
1885## repeat retrieve (name = list.#name, active = text(list.#active),
1886## public = text(list.#public), hidden = text(list.#hidden),
1887## maillist = text(list.#maillist), group = text(list.#group))
1888## where list.list_id = m.list_id and
1889## m.member_type = @atype and m.member_id = @aid {
1890 (*action)(6, rargv, actarg);
1891 found++;
1892## }
1893
1894 if (!found) return(SMS_NO_MATCH);
1895 return(SMS_SUCCESS);
1896##}
1897
1898
1899/* qualified_get_lists: passed "TRUE", "FALSE", or "DONTCARE" for each of
1900 * the five flags associated with each list. It will return the name of
1901 * each list that meets the quailifications. It does this by building a
1902 * where clause based on the arguments, then doing a retrieve.
1903 */
1904
1905static char *lflags[5] = { "active", "public", "hidden", "maillist", "group" };
1906
1907int qualified_get_lists(q, argv, cl, action, actarg)
1908 struct query *q;
1909 char *argv[];
1910 client *cl;
1911 int (*action)();
1912 int actarg;
1913{
1914 return(qualified_get(q, argv, action, actarg, "l.list_id != 0",
1915 "l", "name", lflags));
1916}
1917
1918
1919/** get_members_of_list - optimized query for retrieval of list members
1920 **
1921 ** Inputs:
1922 ** argv[0] - list_id
1923 **
1924 ** Description:
1925 ** - retrieve USER members, then LIST members, then STRING members
1926 **/
1927
1928get_members_of_list(q, argv, cl, action, actarg)
1929 struct query *q;
1930 char *argv[];
1931 client *cl;
1932 int (*action)();
1933 int actarg;
1934##{
1935## int list_id;
1936## char member_name[129];
1937 char *targv[2];
1938
1939 list_id = *(int *)argv[0];
1940 targv[0] = "USER";
1941 targv[1] = member_name;
1942
1943## range of m is members
1944## repeat retrieve (member_name = users.login)
1945## where m.#list_id = @list_id and m.member_type = "USER"
1946## and m.member_id = users.users_id
1947## sort by #member_name
1948## {
1949 (*action)(2, targv, actarg);
1950## }
1951
1952 targv[0] = "LIST";
1953## repeat retrieve (member_name = list.name)
1954## where m.#list_id = @list_id and m.member_type = "LIST"
1955## and m.member_id = list.#list_id
1956## sort by #member_name
1957## {
1958 (*action)(2, targv, actarg);
1959## }
1960
1961 targv[0] = "STRING";
1962## repeat retrieve (member_name = strings.string)
1963## where m.#list_id = @list_id and m.member_type = "STRING"
1964## and m.member_id = strings.string_id
1965## sort by #member_name
1966## {
1967 (*action)(2, targv, actarg);
1968## }
1969
1970## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
1971## where tblstats.#table = "members"
1972 return(SMS_SUCCESS);
1973##}
1974
1975
1976/* count_members_of_list: this is a simple query, but it cannot be done
1977 * through the dispatch table.
1978 */
1979
1980int count_members_of_list(q, argv, cl, action, actarg)
1981 struct query *q;
1982 char *argv[];
1983 client *cl;
1984 int (*action)();
1985 int actarg;
1986##{
1987## int list, ct = 0;
1988 char *rargv[1], countbuf[5];
1989
1990 list = *(int *)argv[0];
1991 rargv[0] = countbuf;
1992## repeat retrieve (ct = count(members.list_id where members.list_id = @list))
1993 sprintf(countbuf, "%d", ct);
1994 (*action)(1, rargv, actarg);
1995## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
1996## where tblstats.#table = "members"
1997 return(SMS_SUCCESS);
1998##}
1999
2000
2001/* qualified_get_server: passed "TRUE", "FALSE", or "DONTCARE" for each of
2002 * the three flags associated with each service. It will return the name of
2003 * each service that meets the quailifications. It does this by building a
2004 * where clause based on the arguments, then doing a retrieve.
2005 */
2006
2007static char *sflags[3] = { "enable", "inprogress", "harderror" };
2008
2009int qualified_get_server(q, argv, cl, action, actarg)
2010 struct query *q;
2011 char *argv[];
2012 client *cl;
2013 int (*action)();
2014 int actarg;
2015{
2016 return(qualified_get(q, argv, action, actarg, "s.name != \"\"",
2017 "s", "name", sflags));
2018}
2019
2020
2021/* generic qualified get routine, used by qualified_get_lists,
2022 * qualified_get_server, and qualified_get_serverhost.
2023 * Args:
2024 * start - a simple where clause, must not be empty
2025 * range - the name of the range variable
2026 * field - the field to return
2027 * flags - an array of strings, names of the flag variables
2028 */
2029
2030int qualified_get(q, argv, action, actarg, start, range, field, flags)
2031 struct query *q;
2032 char *argv[];
2033 int (*action)();
2034 int actarg;
2035 char *start;
2036 char *range;
2037 char *field;
2038 char *flags[];
2039##{
2040## char name[33], qual[256], *rvar, *rtbl, *rfield;
2041 char *rargv[1], buf[32];
2042## int rowcount, i;
2043
2044 strcpy(qual, start);
2045 for (i = 0; i < q->argc; i++) {
2046 if (!strcmp(argv[i], "TRUE")) {
2047 sprintf(buf, " and %s.%s != 0", range, flags[i]);
2048 (void) strcat(qual, buf);
2049 } else if (!strcmp(argv[i], "FALSE")) {
2050 sprintf(buf, " and %s.%s = 0", range, flags[i]);
2051 (void) strcat(qual, buf);
2052 }
2053 }
2054
2055 rargv[0] = name;
2056 rvar = range;
2057 rtbl = q->rtable;
2058 rfield = field;
2059## range of rvar is rtbl
2060## retrieve (name = rvar.rfield) where qual {
2061 (*action)(1, rargv, actarg);
2062## }
2063## inquire_equel(rowcount = "rowcount")
2064## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
2065## where tblstats.#table = @rtbl
2066 if (rowcount == 0)
2067 return(SMS_NO_MATCH);
2068 return(SMS_SUCCESS);
2069##}
2070
2071
2072/* qualified_get_serverhost: passed "TRUE", "FALSE", or "DONTCARE" for each of
2073 * the five flags associated with each serverhost. It will return the name of
2074 * each service and host that meets the quailifications. It does this by
2075 * building a where clause based on the arguments, then doing a retrieve.
2076 */
2077
2078static char *shflags[6] = { "service", "enable", "override", "success",
2079 "inprogress", "hosterror" };
2080
2081int qualified_get_serverhost(q, argv, cl, action, actarg)
2082 struct query *q;
2083 char *argv[];
2084 client *cl;
2085 int (*action)();
2086 int actarg;
2087##{
2088## char sname[33], mname[33], qual[256];
2089 char *rargv[2], buf[32];
2090## int rowcount, i;
2091
2092 sprintf(qual, "machine.mach_id = sh.mach_id and sh.service = uppercase(\"%s\")",
2093 argv[0]);
2094 for (i = 1; i < q->argc; i++) {
2095 if (!strcmp(argv[i], "TRUE")) {
2096 sprintf(buf, " and sh.%s != 0", shflags[i]);
2097 strcat(qual, buf);
2098 } else if (!strcmp(argv[i], "FALSE")) {
2099 sprintf(buf, " and sh.%s = 0", shflags[i]);
2100 strcat(qual, buf);
2101 }
2102 }
2103
2104 rargv[0] = sname;
2105 rargv[1] = mname;
2106## range of sh is serverhosts
2107## retrieve (sname = sh.service, mname = machine.name) where qual {
2108 (*action)(2, rargv, actarg);
2109## }
2110## inquire_equel(rowcount = "rowcount")
2111## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
2112## where tblstats.#table = "serverhosts"
2113 if (rowcount == 0)
2114 return(SMS_NO_MATCH);
2115 return(SMS_SUCCESS);
2116##}
2117
2118
2119/* register_user - change user's login name and allocate a pobox, group,
2120 * filesystem, and quota for them. The user's status must start out as 0,
2121 * and is left as 2. Arguments are: user's UID, new login name, and user's
2122 * type for filesystem allocation (SMS_FS_STUDENT, SMS_FS_FACULTY,
2123 * SMS_FS_STAFF, SMS_FS_MISC).
2124 */
2125
2126register_user(q, argv, cl)
2127 struct query *q;
2128 char **argv;
2129 client *cl;
2130##{
2131## char *login, dir[65], *entity, *directory, machname[33];
2132## int who, rowcount, mid, uid, users_id, flag, utype, nid, list_id, quota;
2133## int size, alloc, pid, m_id;
2134 int maxsize;
2135
2136 entity = cl->entity;
2137 who = cl->users_id;
2138
2139 uid = atoi(argv[0]);
2140 login = argv[1];
2141 utype = atoi(argv[2]);
2142
2143## range of u is users
2144## range of l is list
2145## range of sh is serverhosts
2146## range of n is nfsphys
2147## range of m is machine
2148
2149 /* find user */
2150## repeat retrieve (users_id = u.#users_id)
2151## where u.#uid = @uid and u.status = 0
2152## inquire_equel(rowcount = "rowcount");
2153 if (rowcount == 0)
2154 return(SMS_NO_MATCH);
2155 if (rowcount > 1)
2156 return(SMS_NOT_UNIQUE);
2157
2158 /* check new login name */
2159## repeat retrieve (flag = any(u.#login where u.#login = @login))
2160 if (flag)
2161 return(SMS_IN_USE);
2162## repeat retrieve (flag = any(l.#name where l.#name = @login))
2163 if (flag)
2164 return(SMS_IN_USE);
2165## repeat retrieve (flag = any(filesys.#name where filesys.#name = @login))
2166 if (flag)
2167 return(SMS_IN_USE);
2168 com_err(whoami, 0, "new login name OK");
2169
2170 /* choose place for pobox, put in mid */
2171## repeat retrieve (mid = sh.mach_id, machname = m.name)
2172## where sh.service = "POP" and m.mach_id = sh.mach_id and
2173## sh.value2 - sh.value1 = max(sh.value2-sh.value1 where sh.service="POP")
2174## inquire_equel(rowcount = "rowcount");
2175 if (rowcount == 0)
2176 return(SMS_NO_POBOX);
2177
2178 /* change login name, set pobox */
2179## repeat replace u (#login = @login, status = 2, modtime = "now",
2180## modby = @who, modwith = @entity, potype="POP",
2181## pop_id = @mid, pmodtime="now", pmodby=@who,
2182## pmodwith=@entity)
2183## where u.#users_id = @users_id
2184## inquire_equel(rowcount = "rowcount");
2185 if (rowcount != 1)
2186 return(SMS_INTERNAL);
2187 set_pop_usage(mid, 1);
2188 com_err(whoami, 0, "set login name to %s and pobox to %s", login,
2189 trim(machname));
2190
2191 /* create group list */
2192 if (set_next_object_id("gid", "list"))
2193 return(SMS_NO_ID);
2194 if (set_next_object_id("list_id", "list"))
2195 return(SMS_NO_ID);
2196## repeat retrieve (list_id = values.value) where values.name = "list_id"
2197## inquire_equel(rowcount = "rowcount");
2198 if (rowcount != 1)
2199 return(SMS_INTERNAL);
2200## repeat append list (name = @login, #list_id = @list_id, active = 1,
2201## public = 0, hidden = 0, maillist = 0, group = 1,
2202## #gid = values.value, desc = "User Group",
2203## acl_type = "USER", acl_id = @users_id, modtime = "now",
2204## modby = @who, modwith = @entity)
2205## where values.name = "gid"
2206## inquire_equel(rowcount = "rowcount");
2207 if (rowcount != 1)
2208 return(SMS_INTERNAL);
2209## repeat append members (#list_id = @list_id, member_type = "USER",
2210## member_id = @users_id)
2211## inquire_equel(rowcount = "rowcount");
2212 if (rowcount != 1)
2213 return(SMS_INTERNAL);
2214 com_err(whoami, 0, "group list created");
2215
2216 /* decide where to put filesystem */
2217 maxsize = 0;
2218 directory = NULL;
2219## repeat retrieve (mid = n.mach_id, dir = trim(n.#dir), nid = n.nfsphys_id,
2220## flag = n.status, size = n.#size, alloc = n.allocated) {
2221 if ((flag & utype) && (size != 0) && (size - alloc > maxsize)) {
2222 maxsize = size - alloc;
2223 if (directory)
2224 free(directory);
2225 directory = strsave(dir);
2226 pid = nid;
2227 m_id = mid;
2228 }
2229## }
2230 if (maxsize == 0)
2231 return(SMS_NO_FILESYS);
2232
2233 /* create filesystem */
2234 if (set_next_object_id("filsys_id", "filesys"))
2235 return(SMS_NO_ID);
2236## repeat append filesys (filsys_id = values.value, phys_id = @pid,
2237## label = @login, type = "NFS", mach_id = @m_id,
2238## name = @directory + "/" + @login,
2239## mount = "/mit/" + @login,
2240## access = "w", comments = "User Locker",
2241## owner = @users_id, owners = @list_id, createflg = 1,
2242## lockertype = "HOMEDIR", modtime = "now",
2243## modby = @who, modwith = @entity)
2244## where values.name = "filsys_id"
2245## inquire_equel(rowcount = "rowcount");
2246 if (rowcount != 1)
2247 return(SMS_INTERNAL);
2248 com_err(whoami, 0, "filesys created on mach %d in %s/%s", m_id,
2249 directory, login);
2250
2251 /* set quota */
2252## repeat retrieve (quota = values.value) where values.name = "def_quota"
2253## inquire_equel(rowcount = "rowcount");
2254 if (rowcount != 1)
2255 return(SMS_NO_QUOTA);
2256## repeat append nfsquota (#users_id = @users_id, filsys_id = values.value,
2257## #quota = @quota, modtime = "now", modby = @who,
2258## modwith = @entity)
2259## where values.name = "filsys_id"
2260## inquire_equel(rowcount = "rowcount");
2261 if (rowcount != 1)
2262 return(SMS_INTERNAL);
2263## repeat replace nfsphys (allocated = nfsphys.allocated + @quota)
2264## where nfsphys.nfsphys_id = filesys.#phys_id and
2265## filesys.filsys_id = values.value and values.name = "filsys_id"
2266## inquire_equel(rowcount = "rowcount");
2267 if (rowcount != 1)
2268 return(SMS_INTERNAL);
2269 com_err(whoami, 0, "quota of %d assigned", quota);
2270
2271## repeat replace tblstats (updates = tblstats.updates + 1, modtime = "now")
2272## where tblstats.table = "users"
2273## repeat replace tblstats (appends = tblstats.appends + 1, modtime = "now")
2274## where tblstats.table = "list" or tblstats.table = "filesys" or
2275## tblstats.table = "nfsquota"
2276 return(SMS_SUCCESS);
2277##}
2278
2279
2280
2281/** set_pop_usage - incr/decr usage count for pop server in serverhosts talbe
2282 **
2283 ** Inputs:
2284 ** id of machine
2285 ** delta (will be +/- 1)
2286 **
2287 ** Description:
2288 ** - incr/decr value field in serverhosts table for pop/mach_id
2289 **
2290 **/
2291
2292static int set_pop_usage(id, count)
2293int id;
2294int count;
2295##{
2296## int mach_id = id;
2297## int n = count;
2298
2299## range of sh is serverhosts
2300## repeat replace sh (value1 = sh.value1 + @n)
2301## where sh.service = "POP" and sh.#mach_id = @mach_id
2302
2303 return(SMS_SUCCESS);
2304##}
2305
2306
2307\f
2308/* Validation Routines */
2309
2310validate_row(q, argv, v)
2311 register struct query *q;
2312 char *argv[];
2313 register struct validate *v;
2314##{
2315## char *rvar;
2316## char *table;
2317## char *name;
2318## char qual[128];
2319## int rowcount;
2320
2321 /* build where clause */
2322 build_qual(v->qual, v->argc, argv, qual);
2323
2324 /* setup ingres variables */
2325 rvar = q->rvar;
2326 table = q->rtable;
2327 name = v->field;
2328
2329 if (log_flags & LOG_VALID)
2330 /* tell the logfile what we're doing */
2331 com_err(whoami, 0, "validating row: %s", qual);
2332
2333 /* look for the record */
2334## range of rvar is table
2335## retrieve (rowcount = count(rvar.name where qual))
2336 if (rowcount == 0) return(SMS_NO_MATCH);
2337 if (rowcount > 1) return(SMS_NOT_UNIQUE);
2338 return(SMS_EXISTS);
2339##}
2340
2341validate_fields(q, argv, vo, n)
2342 struct query *q;
2343 register char *argv[];
2344 register struct valobj *vo;
2345 register int n;
2346{
2347 register int status;
2348
2349 while (--n >= 0) {
2350 switch (vo->type) {
2351 case V_NAME:
2352 if (log_flags & LOG_VALID)
2353 com_err(whoami, 0, "validating %s in %s: %s",
2354 vo->namefield, vo->table, argv[vo->index]);
2355 status = validate_name(argv, vo);
2356 break;
2357
2358 case V_ID:
2359 if (log_flags & LOG_VALID)
2360 com_err(whoami, 0, "validating %s in %s: %s",
2361 vo->idfield, vo->table, argv[vo->index]);
2362 status = validate_id(argv, vo);
2363 break;
2364
2365 case V_DATE:
2366 if (log_flags & LOG_VALID)
2367 com_err(whoami, 0, "validating date: %s", argv[vo->index]);
2368 status = validate_date(argv, vo);
2369 break;
2370
2371 case V_TYPE:
2372 if (log_flags & LOG_VALID)
2373 com_err(whoami, 0, "validating %s type: %s",
2374 vo->table, argv[vo->index]);
2375 status = validate_type(argv, vo);
2376 break;
2377
2378 case V_TYPEDATA:
2379 if (log_flags & LOG_VALID)
2380 com_err(whoami, 0, "validating typed data (%s): %s",
2381 argv[vo->index - 1], argv[vo->index]);
2382 status = validate_typedata(q, argv, vo);
2383 break;
2384
2385 case V_RENAME:
2386 if (log_flags & LOG_VALID)
2387 com_err(whoami, 0, "validating rename %s in %s",
2388 argv[vo->index], vo->table);
2389 status = validate_rename(argv, vo);
2390 break;
2391
2392 case V_CHAR:
2393 if (log_flags & LOG_VALID)
2394 com_err(whoami, 0, "validating chars: %s", argv[vo->index]);
2395 status = validate_chars(argv[vo->index]);
2396 break;
2397
2398 case V_SORT:
2399 status = SMS_EXISTS;
2400 break;
2401
2402 }
2403
2404 if (status != SMS_EXISTS) return(status);
2405 vo++;
2406 }
2407
2408 return(SMS_SUCCESS);
2409}
2410
2411
2412/* validate_chars: verify that there are no illegal characters in
2413 * the string. Legal characters are printing chars other than
2414 * ", *, ?, \, [ and ].
2415 */
2416static int illegalchars[] = {
2417 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
2418 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
2419 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
2420 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
2421 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ - O */
2422 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* P - _ */
2423 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
2424 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
2425 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2426 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2427 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2428 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2429 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2430 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2431 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2432 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2433};
2434
2435validate_chars(s)
2436register char *s;
2437{
2438 while (*s)
2439 if (illegalchars[*s++])
2440 return(SMS_BAD_CHAR);
2441 return(SMS_EXISTS);
2442}
2443
2444
2445validate_id(argv, vo)
2446 char *argv[];
2447 register struct valobj *vo;
2448##{
2449## char *name;
2450## char *table;
2451## char *namefield;
2452## char *idfield;
2453## int id;
2454## int rowcount;
2455 register char *c;
2456
2457 name = argv[vo->index];
2458 table = vo->table;
2459 /* minor kludge to upcasify machine names */
2460 if (!strcmp(table, "machine"))
2461 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
2462 namefield = vo->namefield;
2463 idfield = vo->idfield;
2464 if (!strcmp(namefield, "uid")) {
2465## retrieve (id = table.idfield) where table.namefield = int4(name)
2466## inquire_equel (rowcount = "rowcount")
2467 } else {
2468## retrieve (id = table.idfield) where table.namefield = name
2469## inquire_equel (rowcount = "rowcount")
2470 }
2471 if (rowcount != 1) return(vo->error);
2472 *(int *)argv[vo->index] = id;
2473 return(SMS_EXISTS);
2474##}
2475
2476validate_name(argv, vo)
2477 char *argv[];
2478 register struct valobj *vo;
2479##{
2480## char *name;
2481## char *table;
2482## char *namefield;
2483## int rowcount;
2484 register char *c;
2485
2486 name = argv[vo->index];
2487 table = vo->table;
2488 namefield = vo->namefield;
2489 if (!strcmp(table, "servers") && !strcmp(namefield, "name")) {
2490 for (c = name; *c; c++)
2491 if (islower(*c))
2492 *c = toupper(*c);
2493 }
2494## retrieve (rowcount = countu(table.namefield
2495## where table.namefield = name))
2496 return ((rowcount == 1) ? SMS_EXISTS : vo->error);
2497##}
2498
2499validate_date(argv, vo)
2500 char *argv[];
2501 struct valobj *vo;
2502##{
2503## char *idate;
2504## double dd;
2505## int errorno;
2506
2507 idate = argv[vo->index];
2508
2509## retrieve (dd = interval("years", date(idate) - date("today")))
2510## inquire_equel (errorno = "errorno")
2511 if (errorno != 0 || dd > 5.0) return(SMS_DATE);
2512 return(SMS_EXISTS);
2513##}
2514
2515
2516validate_rename(argv, vo)
2517char *argv[];
2518struct valobj *vo;
2519##{
2520## char *name, *table, *namefield, *idfield;
2521## int id;
2522 register char *c;
2523
2524 c = name = argv[vo->index];
2525 while (*c)
2526 if (illegalchars[*c++])
2527 return(SMS_BAD_CHAR);
2528 table = vo->table;
2529 /* minor kludge to upcasify machine names */
2530 if (!strcmp(table, "machine"))
2531 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
2532 namefield = vo->namefield;
2533 idfield = vo->idfield;
2534 id = -1;
2535 if (idfield == 0) {
2536 if (!strcmp(argv[vo->index], argv[vo->index - 1]))
2537 return(SMS_EXISTS);
2538## retrieve (id = any(table.namefield where table.namefield = name))
2539 if (id)
2540 return(vo->error);
2541 else
2542 return(SMS_EXISTS);
2543 }
2544## retrieve (id = table.idfield) where table.namefield = name
2545 if (id == -1 || id == *(int *)argv[vo->index - 1])
2546 return(SMS_EXISTS);
2547 else
2548 return(vo->error);
2549##}
2550
2551
2552validate_type(argv, vo)
2553 char *argv[];
2554 register struct valobj *vo;
2555##{
2556## char *typename;
2557## char *value;
2558## int exists;
2559 register char *c;
2560
2561 typename = vo->table;
2562 c = value = argv[vo->index];
2563 while (*c)
2564 if (illegalchars[*c++])
2565 return(SMS_BAD_CHAR);
2566
2567 /* uppercase type fields */
2568 for (c = value; *c; c++) if (islower(*c)) *c = toupper(*c);
2569
2570## range of a is alias
2571## repeat retrieve (exists = any(a.trans where a.name = @typename and
2572## a.type = "TYPE" and
2573## a.trans = @value))
2574 return (exists ? SMS_EXISTS : vo->error);
2575##}
2576
2577/* validate member or type-specific data field */
2578
2579validate_typedata(q, argv, vo)
2580 register struct query *q;
2581 register char *argv[];
2582 register struct valobj *vo;
2583##{
2584## char *name;
2585## char *field_type;
2586## char data_type[129];
2587## int id;
2588## int rowcount;
2589 char *index();
2590 register char *c;
2591
2592 /* get named object */
2593 name = argv[vo->index];
2594
2595 /* get field type string (known to be at index-1) */
2596 field_type = argv[vo->index-1];
2597
2598 /* get corresponding data type associated with field type name */
2599## repeat retrieve (data_type = alias.trans)
2600## where alias.#name = @field_type and alias.type = "TYPEDATA"
2601## inquire_equel (rowcount = "rowcount")
2602 if (rowcount != 1) return(SMS_TYPE);
2603
2604 /* now retrieve the record id corresponding to the named object */
2605 if (index(data_type, ' '))
2606 *index(data_type, ' ') = 0;
2607 if (!strcmp(data_type, "user")) {
2608 /* USER */
2609## repeat retrieve (id = users.users_id) where users.login = @name
2610## inquire_equel (rowcount = "rowcount")
2611 if (rowcount != 1) return(SMS_USER);
2612
2613 } else if (!strcmp(data_type, "list")) {
2614 /* LIST */
2615## repeat retrieve (id = list.list_id) where list.#name = @name
2616## inquire_equel (rowcount = "rowcount")
2617 if (rowcount != 1) {
2618 /* if idfield is non-zero, then if argv[0] matches the string
2619 * that we're trying to resolve, we should get the value of
2620 * values.[idfield] for the id.
2621 */
2622 if (vo->idfield && !strcmp(argv[0], argv[vo->index])) {
2623 set_next_object_id(q->validate->object_id, q->rtable);
2624 name = vo->idfield;
2625## repeat retrieve (id = values.value) where values.#name = @name
2626## inquire_equel(rowcount = "rowcount")
2627 if (rowcount != 1) return(SMS_LIST);
2628 } else
2629 return(SMS_LIST);
2630 }
2631 } else if (!strcmp(data_type, "machine")) {
2632 /* MACHINE */
2633 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
2634## repeat retrieve (id = machine.mach_id) where machine.#name = @name
2635## inquire_equel (rowcount = "rowcount")
2636 if (rowcount != 1) return(SMS_MACHINE);
2637
2638 } else if (!strcmp(data_type, "string")) {
2639 /* STRING */
2640## range of s is strings
2641## repeat retrieve (id = s.string_id) where s.string = @name
2642## inquire_equel (rowcount = "rowcount")
2643 if (rowcount == 0) {
2644 if (q->type != APPEND) return(SMS_STRING);
2645## range of v is values
2646## retrieve (id = v.value) where v.#name = "strings_id"
2647 id++;
2648## replace v (value = id) where v.#name = "strings_id"
2649## append to strings (string_id = id, string = name)
2650 }
2651 } else if (!strcmp(data_type, "none")) {
2652 id = 0;
2653 } else {
2654 return(SMS_TYPE);
2655 }
2656
2657 /* now set value in argv */
2658 *(int *)argv[vo->index] = id;
2659
2660 return (SMS_EXISTS);
2661##}
2662
2663
2664/* This looks up a login name and returns the SMS internal ID. It is used
2665 * by authenticate to put the users_id in the client structure.
2666 */
2667
2668int get_users_id(name)
2669char *name;
2670##{
2671## int id, rowcount;
2672## char *login;
2673
2674 login = name;
2675
2676## range of u is users
2677## repeat retrieve (id = u.#users_id) where u.#login = @login
2678## inquire_equel (rowcount = "rowcount")
2679
2680 if (rowcount == 1)
2681 return(id);
2682 else
2683 return(0);
2684##}
2685
2686
2687/* Check the database at startup time. For now this just resets the
2688 * inprogress flags that the DCM uses.
2689 */
2690
2691sanity_check_database()
2692##{
2693##}
This page took 0.087371 seconds and 5 git commands to generate.