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