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