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