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