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