]> andersk Git - moira.git/blame - server/qsupport.qc
Move zephyr notification stuff into call to critical_alert
[moira.git] / server / qsupport.qc
CommitLineData
05cdd922 1/*
2 * $Source$
3 * $Author$
4 * $Header$
5 *
6 * Copyright (C) 1987 by the Massachusetts Institute of Technology
7 *
05cdd922 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
05cdd922 18
822a6eba 19extern char *whoami, *strsave();
20
05cdd922 21
22/* Specialized Access Routines */
23
822a6eba 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 */
05cdd922 29
30access_user(q, argv, cl)
31 struct query *q;
32 char *argv[];
33 client *cl;
822a6eba 34{
35 if (cl->users_id != *(int *)argv[0])
36 return(SMS_PERM);
37 else
38 return(SMS_SUCCESS);
39}
05cdd922 40
05cdd922 41
30967516 42
822a6eba 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)
30967516 49 struct query *q;
50 char *argv[];
51 client *cl;
52##{
822a6eba 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);
30967516 63##}
64
822a6eba 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 */
05cdd922 78
79access_list(q, argv, cl)
80 struct query *q;
81 char *argv[];
82 client *cl;
83##{
822a6eba 84## int list_id, acl_id, flags, rowcount;
85## char acl_type[9];
05cdd922 86 char *client_type;
822a6eba 87 int client_id, status;
05cdd922 88
89 list_id = *(int *)argv[0];
822a6eba 90## repeat retrieve (acl_id = list.#acl_id, acl_type = list.#acl_type,
91## flags = list.#public)
05cdd922 92## where list.#list_id = @list_id
822a6eba 93## inquire_equel(rowcount = "rowcount")
94 if (rowcount != 1)
95 return(SMS_INTERNAL);
05cdd922 96
97 /* parse client structure */
822a6eba 98 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
99 return(status);
05cdd922 100
101 /* if amtl or dmfl and list is public allow client to add or delete self */
822a6eba 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);
05cdd922 105 }
106
107 /* check for client in access control list */
822a6eba 108 status = find_member(acl_type, acl_id, client_type, client_id, 0);
109 if (!status) return(SMS_PERM);
05cdd922 110
111 return(SMS_SUCCESS);
112##}
92a943d6 113
a6cb4d4c 114
822a6eba 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)
a6cb4d4c 123 struct query *q;
124 char *argv[];
125 client *cl;
126##{
822a6eba 127## int list_id, acl_id, flags, rowcount;
128## char acl_type[9];
129 char *client_type;
130 int client_id, status;
a6cb4d4c 131
132 list_id = *(int *)argv[0];
822a6eba 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);
a6cb4d4c 151##}
152
92a943d6 153
822a6eba 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)
92a943d6 162 struct query *q;
163 char *argv[];
164 client *cl;
92a943d6 165##{
822a6eba 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);
92a943d6 181
822a6eba 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);
92a943d6 192##}
05cdd922 193
822a6eba 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)
05cdd922 201 struct query *q;
822a6eba 202 char *argv[];
05cdd922 203 client *cl;
822a6eba 204{
205 if (!strcmp(argv[0], "LIST") || !strcmp(argv[0], "RLIST"))
206 return(access_visible_list(q, &argv[1], cl));
05cdd922 207
822a6eba 208 if (!strcmp(argv[0], "USER") || !strcmp(argv[0], "RUSER")) {
209 if (!strcmp(cl->kname.name, argv[1]))
210 return(SMS_SUCCESS);
05cdd922 211 }
212
822a6eba 213 return(SMS_PERM);
214}
05cdd922 215
05cdd922 216
822a6eba 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 */
05cdd922 235
822a6eba 236access_service(q, argv, cl)
05cdd922 237 struct query *q;
238 char *argv[];
822a6eba 239 client *cl;
05cdd922 240##{
822a6eba 241## int acl_id, rowcount;
242## char *name, acl_type[9];
243 int client_id, status;
244 char *client_type;
05cdd922 245
822a6eba 246 name = argv[0];
247## repeat retrieve (acl_id = servers.#acl_id, acl_type = servers.#acl_type)
44bd6f44 248## where servers.#name = uppercase(@name)
822a6eba 249## inquire_equel(rowcount = "rowcount")
250 if (rowcount > 1)
251 return(SMS_PERM);
05cdd922 252
822a6eba 253 /* parse client structure */
254 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
255 return(status);
92a943d6 256
822a6eba 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);
05cdd922 260
92a943d6 261 return(SMS_SUCCESS);
262##}
263
822a6eba 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)
92a943d6 271 struct query *q;
272 char *argv[];
822a6eba 273 client *cl;
92a943d6 274##{
822a6eba 275## int rowcount, users_id, list_id;
276## char *name;
277 int status, client_id;
278 char *client_type;
92a943d6 279
822a6eba 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);
05cdd922 295##}
822a6eba 296
297
05cdd922 298\f
822a6eba 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 */
c2408bd5 311
822a6eba 312setup_ausr(q, argv, cl)
c2408bd5 313 struct query *q;
822a6eba 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 }
c2408bd5 328
822a6eba 329 if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[1]) == -1) {
330 sprintf(argv[0], "#%s", argv[1]);
331 }
c2408bd5 332
822a6eba 333 return(SMS_SUCCESS);
334##}
c2408bd5 335
c2408bd5 336
822a6eba 337/* setup_dusr - verify that the user is no longer being referenced
338 * and may safely be deleted.
339 */
c2408bd5 340
822a6eba 341int setup_dusr(q, argv)
342 struct query *q;
343 char **argv;
344##{
345## int flag, id;
346
347 id = *(int *)argv[0];
44bd6f44 348## repeat delete nfsquota where nfsquota.users_id = @id
822a6eba 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);
44bd6f44 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);
c2408bd5 368 else
369 return(SMS_SUCCESS);
822a6eba 370##}
c2408bd5 371
822a6eba 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;
c2408bd5 379##{
822a6eba 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))
4f16dc86 388## where u.users_id = @id
822a6eba 389 if (!flag)
390 return(SMS_MACHINE);
391 if (strcmp(type, "POP"))
392 set_pop_usage(id, 1);
393 return(SMS_SUCCESS);
394##}
c2408bd5 395
c2408bd5 396
822a6eba 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
c2408bd5 409
822a6eba 410 if (strcmp(type, "POP"))
411 set_pop_usage(id, -1);
c2408bd5 412 return(SMS_SUCCESS);
413##}
414
c2408bd5 415
822a6eba 416/* setup_dmac - verify that the machine is no longer being referenced
417 * and may safely be deleted.
418 */
c2408bd5 419
822a6eba 420int setup_dmac(q, argv)
05cdd922 421 struct query *q;
822a6eba 422 char **argv;
05cdd922 423##{
822a6eba 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);
44bd6f44 441
442## repeat delete mcmap where mcmap.mach_id = @id
443 return(SMS_SUCCESS);
05cdd922 444##}
445
05cdd922 446
822a6eba 447/* setup_dclu - verify that the cluster is no longer being referenced
448 * and may safely be deleted.
449 */
05cdd922 450
822a6eba 451int setup_dclu(q, argv)
05cdd922 452 struct query *q;
822a6eba 453 char **argv;
05cdd922 454##{
822a6eba 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);
05cdd922 466##}
467
05cdd922 468
822a6eba 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 */
05cdd922 475
822a6eba 476int setup_alis(q, argv)
477struct query *q;
478char **argv;
05cdd922 479##{
822a6eba 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 }
05cdd922 499
05cdd922 500 return(SMS_SUCCESS);
501##}
a6cb4d4c 502
822a6eba 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)
a6cb4d4c 509 struct query *q;
822a6eba 510 char **argv;
a6cb4d4c 511##{
822a6eba 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
4f16dc86 529## list.acl_type = "LIST" and list.list_id != @id))
822a6eba 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);
44bd6f44 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);
822a6eba 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##}
a6cb4d4c 550
a6cb4d4c 551
822a6eba 552/* setup_dsin - verify that the service is no longer being referenced
553 * and may safely be deleted.
554 */
a6cb4d4c 555
822a6eba 556int setup_dsin(q, argv)
557 struct query *q;
558 char **argv;
559##{
560## int flag;
561## char *name;
562
563 name = argv[0];
44bd6f44 564## repeat retrieve (flag = any(serverhosts.service
565## where serverhosts.service=uppercase(@name)))
822a6eba 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
a6cb4d4c 572 return(SMS_SUCCESS);
822a6eba 573##}
a6cb4d4c 574
a6cb4d4c 575
822a6eba 576/* setup_dshi - verify that the service-host is no longer being referenced
577 * and may safely be deleted.
578 */
a6cb4d4c 579
822a6eba 580int setup_dshi(q, argv)
581 struct query *q;
582 char **argv;
583##{
584## int flag, id;
585## char *name;
a6cb4d4c 586
822a6eba 587 name = argv[0];
588 id = *(int *)argv[1];
589## repeat retrieve (flag=serverhosts.inprogress)
44bd6f44 590## where serverhosts.service=uppercase(@name) and serverhosts.mach_id=@id
822a6eba 591 if (flag)
592 return(SMS_IN_USE);
593 else
594 return(SMS_SUCCESS);
a6cb4d4c 595##}
822a6eba 596
597
a6cb4d4c 598/**
822a6eba 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
a6cb4d4c 606 **
607 ** Description:
822a6eba 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)
a6cb4d4c 617 **
822a6eba 618 ** Errors:
619 ** SMS_NFS - specified directory not exported
620 ** SMS_FILESYS_ACCESS - invalid filesys access
a6cb4d4c 621 **
622 **/
623
822a6eba 624##static int var_phys_id;
a6cb4d4c 625
822a6eba 626setup_afil(q, argv)
a6cb4d4c 627 struct query *q;
628 char *argv[];
629{
822a6eba 630 char *type;
631 int mach_id;
632 char *name;
633 char *access;
a6cb4d4c 634
a6cb4d4c 635 type = argv[1];
636 mach_id = *(int *)argv[2];
822a6eba 637 name = argv[3];
638 access = argv[5];
639 var_phys_id = 0;
a6cb4d4c 640
822a6eba 641 if (!strcmp(type, "NFS"))
642 return (check_nfs(mach_id, name, access));
643 else
644 return(SMS_SUCCESS);
645}
05cdd922 646
30967516 647
822a6eba 648setup_ufil(q, argv)
30967516 649 struct query *q;
650 char *argv[];
822a6eba 651{
652 char *type;
653 int mach_id;
654 char *name;
655 char *access;
30967516 656
822a6eba 657 type = argv[2];
658 mach_id = *(int *)argv[3];
659 name = argv[4];
660 access = argv[6];
661 var_phys_id = 0;
a6cb4d4c 662
822a6eba 663 if (!strcmp(type, "NFS"))
664 return (check_nfs(mach_id, name, access));
665 else
666 return(SMS_SUCCESS);
667}
30967516 668
a6cb4d4c 669
822a6eba 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 */
a6cb4d4c 675
822a6eba 676##check_nfs(mach_id, name, access)
a6cb4d4c 677## int mach_id;
822a6eba 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;
a6cb4d4c 686
822a6eba 687 caccess = (isupper(*access)) ? tolower(*access) : *access;
688 if (caccess != 'r' && caccess != 'w') return(SMS_FILESYS_ACCESS);
a6cb4d4c 689
822a6eba 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;
a6cb4d4c 702## endretrieve
703 }
704## }
705
822a6eba 706 return(status);
30967516 707##}
a6cb4d4c 708
92a943d6 709
822a6eba 710/* setup_dfil: free any quota records associated with a filesystem
711 * when it is deleted.
712 */
92a943d6 713
822a6eba 714setup_dfil(q, argv, cl)
715 struct query *q;
716 char **argv;
717 client *cl;
718##{
719## int id;
92a943d6 720
822a6eba 721 id = *(int *)argv[0];
722## range of q is nfsquota
44bd6f44 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
92a943d6 727
822a6eba 728## repeat delete q where q.filsys_id = @id
92a943d6 729 return(SMS_SUCCESS);
730##}
30967516 731
822a6eba 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;
92a943d6 740 client *cl;
92a943d6 741##{
822a6eba 742## int id, exists;
92a943d6 743
822a6eba 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);
92a943d6 748 return(SMS_SUCCESS);
749##}
4b890cc4 750
4b890cc4 751
822a6eba 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)
4b890cc4 785 struct query *q;
786 char *argv[];
822a6eba 787 client *cl;
4b890cc4 788##{
822a6eba 789## char *name, *entity, *table;
790## int who;
4b890cc4 791
822a6eba 792 entity = cl->entity;
793 who = cl->users_id;
794 table = q->rtable;
795 name = argv[0];
4b890cc4 796
822a6eba 797## replace table (modtime = "now", modby = who, modwith = entity)
798## where table.#name = name
4b890cc4 799 return(SMS_SUCCESS);
800##}
801
822a6eba 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)
4b890cc4 809 struct query *q;
822a6eba 810 char **argv;
811 client *cl;
4b890cc4 812##{
822a6eba 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;
4b890cc4 820
822a6eba 821 id = *(int *)argv[0];
822## replace table (modtime = "now", modby = who, modwith = entity)
823## where table.id_name = id
4b890cc4 824 return(SMS_SUCCESS);
825##}
826
822a6eba 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)
4b890cc4 832 struct query *q;
833 char *argv[];
822a6eba 834 client *cl;
4b890cc4 835##{
822a6eba 836## int users_id, who;
837## char *entity;
838
839 entity = cl->entity;
840 who = cl->users_id;
841 users_id = *(int *)argv[0];
4b890cc4 842
822a6eba 843## repeat replace u (fmodtime = "now", fmodby = @who, fmodwith = @entity)
844## where u.#users_id = @users_id
4b890cc4 845 return(SMS_SUCCESS);
846##}
05cdd922 847
822a6eba 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)
05cdd922 853 struct query *q;
822a6eba 854 char **argv;
855 client *cl;
05cdd922 856##{
822a6eba 857## int users_id, who;
858## char *entity;
05cdd922 859
822a6eba 860 entity = cl->entity;
861 who = cl->users_id;
862 users_id = *(int *)argv[0];
05cdd922 863
822a6eba 864## repeat replace users (pmodtime = "now", pmodby = @who, pmodwith = @entity)
865## where users.#users_id = @users_id
866 return(SMS_SUCCESS);
867##}
05cdd922 868
05cdd922 869
822a6eba 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;
05cdd922 885
822a6eba 886 host = argv[0];
887## repeat replace m (modtime = "now", modby = @who, modwith = @entity)
888## where m.name = uppercase(@host)
05cdd922 889 return(SMS_SUCCESS);
890##}
05cdd922 891
822a6eba 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)
05cdd922 899 struct query *q;
05cdd922 900 char **argv;
822a6eba 901 client *cl;
902##{
903## char *entity;
904## int who, id;
05cdd922 905
822a6eba 906 entity = cl->entity;
907 who = cl->users_id;
05cdd922 908
822a6eba 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##}
05cdd922 915
05cdd922 916
822a6eba 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
05cdd922 937 return(SMS_SUCCESS);
938##}
939
822a6eba 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)
92a943d6 946 struct query *q;
822a6eba 947 char **argv;
948 client *cl;
92a943d6 949##{
822a6eba 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)
44bd6f44 959## where sh.service = uppercase(@serv) and sh.mach_id = @id
822a6eba 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;
92a943d6 970 char **argv;
822a6eba 971 client *cl;
972##{
973## char *entity, *dir;
974## int who, id;
92a943d6 975
822a6eba 976 entity = cl->entity;
977 who = cl->users_id;
92a943d6 978
822a6eba 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##}
92a943d6 985
92a943d6 986
822a6eba 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
92a943d6 1008 return(SMS_SUCCESS);
1009##}
05cdd922 1010
822a6eba 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;
05cdd922 1020##{
822a6eba 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;
05cdd922 1051## char *name;
05cdd922 1052
822a6eba 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);
30967516 1071##}
1072
822a6eba 1073
30967516 1074/**
822a6eba 1075 ** followup_ausr - add finger and pobox entries, set_user_modtime
30967516 1076 **
1077 ** Inputs:
822a6eba 1078 ** argv[0] - login (add_user)
1079 ** argv[3] - last name
1080 ** argv[4] - first name
1081 ** argv[5] - middle name
30967516 1082 **
1083 **/
1084
822a6eba 1085followup_ausr(q, argv, cl)
30967516 1086 struct query *q;
822a6eba 1087 char *argv[];
1088 client *cl;
30967516 1089##{
822a6eba 1090## int who;
1091## char *login, *entity;
1092## char fullname[129];
30967516 1093
822a6eba 1094 login = argv[0];
1095 who = cl->users_id;
1096 entity = cl->entity;
30967516 1097
822a6eba 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]);
30967516 1105
822a6eba 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
30967516 1112
05cdd922 1113 return(SMS_SUCCESS);
1114##}
1115
822a6eba 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
44bd6f44 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
822a6eba 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"))
4f16dc86 1209 idx = 12;
822a6eba 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.
92a943d6 1267 **
1268 ** Inputs:
1269 ** argv[0] - list_id
822a6eba 1270 ** argv[1] - member_type
1271 ** argv[2] - member_id
92a943d6 1272 **
1273 **/
1274
822a6eba 1275followup_amtl(q, argv, cl)
92a943d6 1276 struct query *q;
1277 char *argv[];
822a6eba 1278 client *cl;
92a943d6 1279##{
92a943d6 1280## int list_id;
822a6eba 1281## int member_id;
1282## int exists, who;
1283## char *entity;
92a943d6 1284
1285 list_id = *(int *)argv[0];
822a6eba 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
92a943d6 1292
822a6eba 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);
92a943d6 1296
822a6eba 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
92a943d6 1306 return(SMS_SUCCESS);
1307##}
1308
822a6eba 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)();
92a943d6 1345 int actarg;
822a6eba 1346 client *cl;
92a943d6 1347##{
822a6eba 1348## char *name;
1349## int rowcount, id;
1350 char **argv;
1351 int i;
92a943d6 1352
822a6eba 1353 while (sq_get_data(sq, &argv)) {
1354 sms_trim_args(q->vcnt, argv);
92a943d6 1355
822a6eba 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 }
92a943d6 1385
822a6eba 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);
92a943d6 1395 return(SMS_SUCCESS);
1396##}
1397
05cdd922 1398
822a6eba 1399/* followup_gsha:
1400 */
1401
1402followup_gsha(q, sq, v, action, actarg, cl)
05cdd922 1403 register struct query *q;
822a6eba 1404 register struct save_queue *sq;
1405 register struct validate *v;
1406 register int (*action)();
1407 int actarg;
1408 client *cl;
05cdd922 1409##{
822a6eba 1410## char *name;
1411## int rowcount, id;
1412 char **argv;
1413 int i;
05cdd922 1414
822a6eba 1415 while (sq_get_data(sq, &argv)) {
1416 sms_trim_args(q->vcnt, argv);
05cdd922 1417
822a6eba 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 }
05cdd922 1445
822a6eba 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##}
05cdd922 1457
05cdd922 1458
822a6eba 1459\f
1460/* Special query routines */
30967516 1461
822a6eba 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"
30967516 1513 return(SMS_SUCCESS);
1514##}
1515
30967516 1516
822a6eba 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
44bd6f44 1519 * data. Rest of processing consists of fixing gid, ace_name, and modby.
822a6eba 1520 */
1521
1522get_list_info(q, aargv, cl, action, actarg)
30967516 1523 register struct query *q;
822a6eba 1524 char **aargv;
1525 client *cl;
1526 register int (*action)();
1527 int actarg;
30967516 1528##{
822a6eba 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();
30967516 1536
822a6eba 1537 returned = rowcount = 0;
1538 name = aargv[0];
30967516 1539
822a6eba 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 }
30967516 1595
822a6eba 1596 sq_destroy(sq);
1597## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
1598## where tblstats.#table = "list"
30967516 1599
822a6eba 1600 return (SMS_SUCCESS);
1601##}
1602
1603
44bd6f44 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],
822a6eba 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
44bd6f44 1612int get_ace_use(q, argv, cl, action, actarg)
822a6eba 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")) {
44bd6f44 1627 return(get_ace_internal(atype, aid, action, actarg));
822a6eba 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)) {
44bd6f44 1643 if (get_ace_internal("LIST", id, action, actarg) == SMS_SUCCESS)
822a6eba 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)) {
44bd6f44 1663 if (get_ace_internal("LIST", id, action, actarg) == SMS_SUCCESS)
822a6eba 1664 found++;
1665 }
44bd6f44 1666 if (get_ace_internal("USER", aid, action, actarg) == SMS_SUCCESS)
822a6eba 1667 found++;
1668 }
05cdd922 1669
822a6eba 1670 sq_destroy(sq);
1671 if (!found) return(SMS_NO_MATCH);
05cdd922 1672 return(SMS_SUCCESS);
1673##}
92a943d6 1674
822a6eba 1675
44bd6f44 1676/* This looks up a single list or user for ace use. atype must be "USER"
822a6eba 1677 * or "LIST", and aid is the ID of the corresponding object. This is used
44bd6f44 1678 * by get_ace_use above.
822a6eba 1679 */
1680
44bd6f44 1681##get_ace_internal(atype, aid, action, actarg)
822a6eba 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)
92a943d6 1760 struct query *q;
1761 char *argv[];
822a6eba 1762 client *cl;
1763 int (*action)();
1764 int actarg;
92a943d6 1765##{
822a6eba 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 }
92a943d6 1778
822a6eba 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 }
92a943d6 1796
822a6eba 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 }
92a943d6 1818
822a6eba 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++;
92a943d6 1839 }
55534a87 1840
822a6eba 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
55534a87 1848
822a6eba 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## }
92a943d6 1878
822a6eba 1879 if (!found) return(SMS_NO_MATCH);
92a943d6 1880 return(SMS_SUCCESS);
1881##}
1882
822a6eba 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
c2408bd5 1905 **
1906 ** Inputs:
1907 ** argv[0] - list_id
1908 **
1909 ** Description:
1910 ** - retrieve USER members, then LIST members, then STRING members
c2408bd5 1911 **/
1912
822a6eba 1913get_members_of_list(q, argv, cl, action, actarg)
c2408bd5 1914 struct query *q;
1915 char *argv[];
822a6eba 1916 client *cl;
c2408bd5 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
92a943d6 1932## sort by #member_name
c2408bd5 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
92a943d6 1941## sort by #member_name
c2408bd5 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
92a943d6 1950## sort by #member_name
c2408bd5 1951## {
1952 (*action)(2, targv, actarg);
1953## }
1954
822a6eba 1955## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
1956## where tblstats.#table = "members"
c2408bd5 1957 return(SMS_SUCCESS);
1958##}
1959
92a943d6 1960
822a6eba 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)
92a943d6 1966 struct query *q;
1967 char *argv[];
822a6eba 1968 client *cl;
92a943d6 1969 int (*action)();
1970 int actarg;
1971##{
822a6eba 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##}
92a943d6 1984
92a943d6 1985
822a6eba 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 */
92a943d6 1991
822a6eba 1992static char *sflags[3] = { "enable", "inprogress", "harderror" };
a6cb4d4c 1993
822a6eba 1994int qualified_get_server(q, argv, cl, action, actarg)
a6cb4d4c 1995 struct query *q;
1996 char *argv[];
822a6eba 1997 client *cl;
a6cb4d4c 1998 int (*action)();
1999 int actarg;
822a6eba 2000{
2001 return(qualified_get(q, argv, action, actarg, "s.name != \"\"",
2002 "s", "name", sflags));
2003}
a6cb4d4c 2004
a6cb4d4c 2005
822a6eba 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 */
c2408bd5 2014
822a6eba 2015int qualified_get(q, argv, action, actarg, start, range, field, flags)
c2408bd5 2016 struct query *q;
2017 char *argv[];
2018 int (*action)();
2019 int actarg;
822a6eba 2020 char *start;
2021 char *range;
2022 char *field;
2023 char *flags[];
c2408bd5 2024##{
822a6eba 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);
c2408bd5 2047## }
822a6eba 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##}
c2408bd5 2055
c2408bd5 2056
822a6eba 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 */
c2408bd5 2062
822a6eba 2063static char *shflags[6] = { "service", "enable", "override", "success",
2064 "inprogress", "hosterror" };
a6cb4d4c 2065
822a6eba 2066int qualified_get_serverhost(q, argv, cl, action, actarg)
a6cb4d4c 2067 struct query *q;
2068 char *argv[];
822a6eba 2069 client *cl;
a6cb4d4c 2070 int (*action)();
2071 int actarg;
2072##{
822a6eba 2073## char sname[33], mname[33], qual[256];
2074 char *rargv[2], buf[32];
2075## int rowcount, i;
2076
44bd6f44 2077 sprintf(qual, "machine.mach_id = sh.mach_id and sh.service = uppercase(\"%s\")",
822a6eba 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);
a6cb4d4c 2094## }
822a6eba 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##}
a6cb4d4c 2102
a6cb4d4c 2103
822a6eba 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);
4f16dc86 2147## repeat retrieve (flag = any(l.#name where l.#name = @login))
822a6eba 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)
44bd6f44 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")
822a6eba 2159## inquire_equel(rowcount = "rowcount");
2160 if (rowcount == 0)
44bd6f44 2161 return(SMS_NO_POBOX);
822a6eba 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"))
44bd6f44 2178 return(SMS_NO_ID);
822a6eba 2179 if (set_next_object_id("list_id", "list"))
44bd6f44 2180 return(SMS_NO_ID);
822a6eba 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"
44bd6f44 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)
822a6eba 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 }
a6cb4d4c 2214## }
822a6eba 2215 if (maxsize == 0)
44bd6f44 2216 return(SMS_NO_FILESYS);
822a6eba 2217
2218 /* create filesystem */
2219 if (set_next_object_id("filsys_id", "filesys"))
44bd6f44 2220 return(SMS_NO_ID);
822a6eba 2221## repeat append filesys (filsys_id = values.value, phys_id = @pid,
2222## label = @login, type = "NFS", mach_id = @m_id,
4f16dc86 2223## name = @directory + "/" + @login,
2224## mount = "/mit/" + @login,
822a6eba 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,
4f16dc86 2234 directory, login);
822a6eba 2235
2236 /* set quota */
2237## repeat retrieve (quota = values.value) where values.name = "def_quota"
2238## inquire_equel(rowcount = "rowcount");
2239 if (rowcount != 1)
44bd6f44 2240 return(SMS_NO_QUOTA);
822a6eba 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
4f16dc86 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"
822a6eba 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)
44bd6f44 2286## where sh.service = "POP" and sh.#mach_id = @mach_id
a6cb4d4c 2287
2288 return(SMS_SUCCESS);
2289##}
822a6eba 2290
2291
c2408bd5 2292\f
05cdd922 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
b4182127 2314 if (log_flags & LOG_RES)
2315 /* tell the logfile what we're doing */
2316 com_err(whoami, 0, "validating row: %s", qual);
2317
05cdd922 2318 /* look for the record */
2319## range of rvar is table
2320## retrieve (rowcount = count(rvar.name where qual))
05cdd922 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;
05cdd922 2333
2334 while (--n >= 0) {
2335 switch (vo->type) {
2336 case V_NAME:
92a943d6 2337 if (log_flags & LOG_RES)
b4182127 2338 com_err(whoami, 0, "validating %s in %s: %s",
05cdd922 2339 vo->namefield, vo->table, argv[vo->index]);
05cdd922 2340 status = validate_name(argv, vo);
2341 break;
2342
2343 case V_ID:
92a943d6 2344 if (log_flags & LOG_RES)
b4182127 2345 com_err(whoami, 0, "validating %s in %s: %s",
05cdd922 2346 vo->idfield, vo->table, argv[vo->index]);
05cdd922 2347 status = validate_id(argv, vo);
2348 break;
2349
92a943d6 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
05cdd922 2356 case V_TYPE:
92a943d6 2357 if (log_flags & LOG_RES)
b4182127 2358 com_err(whoami, 0, "validating %s type: %s",
05cdd922 2359 vo->table, argv[vo->index]);
05cdd922 2360 status = validate_type(argv, vo);
2361 break;
2362
2363 case V_TYPEDATA:
92a943d6 2364 if (log_flags & LOG_RES)
2365 com_err(whoami, 0, "validating typed data (%s): %s",
2366 argv[vo->index - 1], argv[vo->index]);
05cdd922 2367 status = validate_typedata(q, argv, vo);
2368 break;
2369
822a6eba 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]);
05cdd922 2381 break;
2382
92a943d6 2383 case V_SORT:
2384 status = SMS_EXISTS;
2385 break;
2386
05cdd922 2387 }
2388
2389 if (status != SMS_EXISTS) return(status);
2390 vo++;
2391 }
2392
2393 return(SMS_SUCCESS);
2394}
2395
822a6eba 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
05cdd922 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;
122ec372 2440 register char *c;
05cdd922 2441
2442 name = argv[vo->index];
2443 table = vo->table;
122ec372 2444 /* minor kludge to upcasify machine names */
822a6eba 2445 if (!strcmp(table, "machine"))
122ec372 2446 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
05cdd922 2447 namefield = vo->namefield;
2448 idfield = vo->idfield;
822a6eba 2449 if (!strcmp(namefield, "uid")) {
9119288e 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 }
05cdd922 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;
44bd6f44 2469 register char *c;
05cdd922 2470
2471 name = argv[vo->index];
2472 table = vo->table;
2473 namefield = vo->namefield;
44bd6f44 2474 if (!strcmp(table, "servers") && !strcmp(namefield, "name")) {
2475 for (c = name; *c; c++)
2476 if (islower(*c))
2477 *c = toupper(*c);
2478 }
05cdd922 2479## retrieve (rowcount = countu(table.namefield
2480## where table.namefield = name))
2481 return ((rowcount == 1) ? SMS_EXISTS : vo->error);
2482##}
2483
92a943d6 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);
44bd6f44 2497 return(SMS_EXISTS);
92a943d6 2498##}
2499
822a6eba 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
05cdd922 2537validate_type(argv, vo)
2538 char *argv[];
2539 register struct valobj *vo;
2540##{
2541## char *typename;
2542## char *value;
822a6eba 2543## int exists;
05cdd922 2544 register char *c;
2545
2546 typename = vo->table;
822a6eba 2547 c = value = argv[vo->index];
2548 while (*c)
2549 if (illegalchars[*c++])
2550 return(SMS_BAD_CHAR);
05cdd922 2551
2552 /* uppercase type fields */
2553 for (c = value; *c; c++) if (islower(*c)) *c = toupper(*c);
2554
2555## range of a is alias
822a6eba 2556## repeat retrieve (exists = any(a.trans where a.name = @typename and
05cdd922 2557## a.type = "TYPE" and
2558## a.trans = @value))
822a6eba 2559 return (exists ? SMS_EXISTS : vo->error);
05cdd922 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;
822a6eba 2571## char data_type[129];
05cdd922 2572## int id;
05cdd922 2573## int rowcount;
822a6eba 2574 char *index();
a6cb4d4c 2575 register char *c;
05cdd922 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 */
822a6eba 2590 if (index(data_type, ' '))
2591 *index(data_type, ' ') = 0;
05cdd922 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")
822a6eba 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])) {
4f16dc86 2608 set_next_object_id(q->validate->object_id, q->rtable);
822a6eba 2609 name = vo->idfield;
4f16dc86 2610## repeat retrieve (id = values.value) where values.#name = @name
822a6eba 2611## inquire_equel(rowcount = "rowcount")
2612 if (rowcount != 1) return(SMS_LIST);
2613 } else
2614 return(SMS_LIST);
2615 }
05cdd922 2616 } else if (!strcmp(data_type, "machine")) {
2617 /* MACHINE */
a6cb4d4c 2618 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
05cdd922 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
822a6eba 2626## repeat retrieve (id = s.string_id) where s.string = @name
05cdd922 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"
822a6eba 2634## append to strings (string_id = id, string = name)
05cdd922 2635 }
822a6eba 2636 } else if (!strcmp(data_type, "none")) {
2637 id = 0;
05cdd922 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
05cdd922 2648
822a6eba 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 */
05cdd922 2652
822a6eba 2653int get_users_id(name)
2654char *name;
2655##{
2656## int id, rowcount;
2657## char *login;
05cdd922 2658
822a6eba 2659 login = name;
05cdd922 2660
822a6eba 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##}
05cdd922 2670
05cdd922 2671
822a6eba 2672/* Check the database at startup time. For now this just resets the
2673 * inprogress flags that the DCM uses.
2674 */
05cdd922 2675
822a6eba 2676sanity_check_database()
2677##{
2678## replace servers (inprogress = 0)
2679## replace serverhosts (inprogress = 0)
05cdd922 2680##}
This page took 0.452696 seconds and 5 git commands to generate.