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