6 * Copyright (C) 1987 by the Massachusetts Institute of Technology
7 * For copying and distribution information, please see the file
13 static char *rcsid_qsupport_dc = "$Header$";
16 #include <mit-copyright.h>
18 #include "mr_server.h"
23 EXEC SQL INCLUDE sqlca;
24 EXEC SQL INCLUDE sqlda;
27 extern char *whoami, *strsave();
28 extern int ingres_errno, mr_errcode;
30 EXEC SQL BEGIN DECLARE SECTION;
33 extern char stmt_buf[];
34 EXEC SQL END DECLARE SECTION;
36 /* Specialized Access Routines */
38 /* access_user - verify that client name equals specified login name
40 * - since field validation routines are called first, a users_id is
41 * now in argv[0] instead of the login name.
44 EXEC SQL WHENEVER SQLERROR CALL ingerr;
46 access_user(q, argv, cl)
51 if (cl->users_id != *(int *)argv[0])
59 /* access_login - verify that client name equals specified login name
61 * argv[0...n] contain search info. q->
64 access_login(q, argv, cl)
69 EXEC SQL BEGIN DECLARE SECTION;
72 EXEC SQL END DECLARE SECTION;
74 build_qual(q->qual, q->argc, argv, qual);
75 EXEC SQL SELECT users_id INTO :id FROM users WHERE :qual;
77 if (sqlca.sqlerrd[2] != 1 || id != cl->users_id)
85 /* access_list - check access for most list operations
87 * Inputs: argv[0] - list_id
89 * argv[2] - member ID (only for queries "amtl" and "dmfl")
90 * argv[7] - group IID (only for query "ulis")
93 * - check that client is a member of the access control list
94 * - OR, if the query is add_member_to_list or delete_member_from_list
95 * and the list is public, allow access if client = member
98 access_list(q, argv, cl)
103 EXEC SQL BEGIN DECLARE SECTION;
104 int list_id, acl_id, flags, gid;
106 EXEC SQL END DECLARE SECTION;
108 int client_id, status;
110 list_id = *(int *)argv[0];
111 EXEC SQL SELECT acl_id, acl_type, gid, publicflg
112 INTO :acl_id, :acl_type, :gid, :flags
114 WHERE list_id = :list_id;
116 if (sqlca.sqlerrd[2] != 1)
119 /* parse client structure */
120 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
123 /* if amtl or dmfl and list is public allow client to add or delete self */
124 if (((!strcmp("amtl", q->shortname) && flags) ||
125 (!strcmp("dmfl", q->shortname))) &&
126 (!strcmp("USER", argv[1]))) {
127 if (*(int *)argv[2] == client_id) return(MR_SUCCESS);
128 /* if update_list, don't allow them to change the GID */
129 } else if (!strcmp("ulis", q->shortname)) {
130 if ((!strcmp(argv[7], UNIQUE_GID) && (gid != -1)) ||
131 (strcmp(argv[7], UNIQUE_GID) && (gid != atoi(argv[7]))))
135 /* check for client in access control list */
136 status = find_member(acl_type, acl_id, client_type, client_id, 0);
137 if (!status) return(MR_PERM);
143 /* access_visible_list - allow access to list only if it is not hidden,
144 * or if the client is on the ACL
146 * Inputs: argv[0] - list_id
147 * cl - client identifier
150 access_visible_list(q, argv, cl)
155 EXEC SQL BEGIN DECLARE SECTION;
156 int list_id, acl_id, flags ;
158 EXEC SQL END DECLARE SECTION;
160 int client_id, status;
162 list_id = *(int *)argv[0];
163 EXEC SQL SELECT hidden, acl_id, acl_type
164 INTO :flags, :acl_id, :acl_type
166 WHERE list_id = :list_id;
167 if (sqlca.sqlerrd[2] != 1)
172 /* parse client structure */
173 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
176 /* check for client in access control list */
177 status = find_member(acl_type, acl_id, client_type, client_id, 0);
185 /* access_vis_list_by_name - allow access to list only if it is not hidden,
186 * or if the client is on the ACL
188 * Inputs: argv[0] - list name
189 * cl - client identifier
192 access_vis_list_by_name(q, argv, cl)
197 EXEC SQL BEGIN DECLARE SECTION;
198 int acl_id, flags, rowcount;
199 char acl_type[9], *listname;
200 EXEC SQL END DECLARE SECTION;
202 int client_id, status;
205 EXEC SQL SELECT hidden, acl_id, acl_type INTO :flags, :acl_id, :acl_type
206 FROM list WHERE name = :listname;
208 rowcount=sqlca.sqlerrd[2];
216 /* parse client structure */
217 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
220 /* check for client in access control list */
221 status = find_member(acl_type, acl_id, client_type, client_id, 0);
229 /* access_member - allow user to access member of type "USER" and name matches
230 * username, or to access member of type "LIST" and list is one that user is
231 * on the acl of, or the list is visible.
234 access_member(q, argv, cl)
239 if (!strcmp(argv[0], "LIST") || !strcmp(argv[0], "RLIST"))
240 return(access_visible_list(q, &argv[1], cl));
242 if (!strcmp(argv[0], "USER") || !strcmp(argv[0], "RUSER")) {
243 if (cl->users_id == *(int *)argv[1])
247 if (!strcmp(argv[0], "KERBEROS") || !strcmp(argv[0], "RKERBERO")) {
248 if (cl->client_id == *(int *)argv[1])
256 /* access_qgli - special access routine for Qualified_get_lists. Allows
257 * access iff argv[0] == "TRUE" and argv[2] == "FALSE".
260 access_qgli(q, argv, cl)
265 if (!strcmp(argv[0], "TRUE") && !strcmp(argv[2], "FALSE"))
271 /* access_service - allow access if user is on ACL of service. Don't
272 * allow access if a wildcard is used.
275 access_service(q, argv, cl)
280 EXEC SQL BEGIN DECLARE SECTION;
282 char *name, acl_type[9];
283 EXEC SQL END DECLARE SECTION;
284 int client_id, status;
285 char *client_type, *c;
288 for(c=name;*c;c++) if(islower(*c)) *c = toupper(*c); /* uppercasify */
289 EXEC SQL SELECT acl_id, acl_type INTO :acl_id, :acl_type FROM servers
291 if (sqlca.sqlerrd[2] > 1)
294 /* parse client structure */
295 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
298 /* check for client in access control list */
299 status = find_member(acl_type, acl_id, client_type, client_id, 0);
300 if (!status) return(MR_PERM);
306 /* access_filesys - verify that client is owner or on owners list of filesystem
310 access_filesys(q, argv, cl)
315 EXEC SQL BEGIN DECLARE SECTION;
316 int users_id, list_id;
318 EXEC SQL END DECLARE SECTION;
319 int status, client_id;
323 EXEC SQL SELECT owner, owners INTO :users_id, :list_id FROM filesys
326 if (sqlca.sqlerrd[2] != 1)
328 if (users_id == cl->users_id)
330 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
332 status = find_member("LIST", list_id, client_type, client_id, 0);
343 /* Setup routine for add_user
345 * Inputs: argv[0] - login
350 * - if argv[1] == UNIQUE_UID then set argv[1] = next(uid)
351 * - if argv[0] == UNIQUE_LOGIN then set argv[0] = "#<uid>"
354 setup_ausr(q, argv, cl)
356 register char *argv[];
360 EXEC SQL BEGIN DECLARE SECTION;
362 EXEC SQL END DECLARE SECTION;
364 if (!strcmp(q->shortname, "uusr") || !strcmp(q->shortname, "uuac"))
368 if (!strcmp(argv[row], UNIQUE_UID) || atoi(argv[row]) == -1) {
369 if (set_next_object_id("uid", "users", 1))
370 return(MR_INGRES_ERR);
371 EXEC SQL SELECT value INTO :nuid FROM numvalues WHERE name = 'uid';
372 if (sqlca.sqlerrd[2] != 1)
374 sprintf(argv[row], "%d", nuid);
377 if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[row]) == -1) {
378 sprintf(argv[0], "#%s", argv[row]);
381 if((mr_errcode=prefetch_value(q,argv,cl))!=MR_SUCCESS)
388 /* setup_dusr - verify that the user is no longer being referenced
389 * and may safely be deleted.
392 int setup_dusr(q, argv)
396 EXEC SQL BEGIN DECLARE SECTION;
398 EXEC SQL END DECLARE SECTION;
400 id = *(int *)argv[0];
402 /* For now, only allow users to be deleted if their status is 0 */
403 EXEC SQL REPEATED SELECT status INTO :flag FROM users
404 WHERE users_id = :id;
405 if (flag != 0 && flag != 4)
408 EXEC SQL REPEATED DELETE FROM quota WHERE entity_id = :id AND type = 'USER';
409 EXEC SQL REPEATED DELETE FROM krbmap WHERE users_id = :id;
410 EXEC SQL REPEATED SELECT member_id INTO :idummy FROM imembers
411 WHERE member_id = :id AND member_type = 'USER';
412 if (sqlca.sqlerrd[2] > 0)
414 EXEC SQL REPEATED SELECT label INTO :cdummy FROM filesys WHERE owner = :id;
415 if (sqlca.sqlerrd[2]> 0)
417 EXEC SQL REPEATED SELECT name INTO :cdummy FROM list
418 WHERE acl_id = :id AND acl_type = 'USER';
419 if (sqlca.sqlerrd[2] > 0)
421 EXEC SQL REPEATED SELECT name INTO :cdummy FROM servers
422 WHERE acl_id = :id AND acl_type = 'USER';
423 if (sqlca.sqlerrd[2] > 0)
425 EXEC SQL REPEATED SELECT acl_id INTO :idummy FROM hostaccess
426 WHERE acl_id = :id AND acl_type = 'USER';
427 if (sqlca.sqlerrd[2] > 0)
435 /* setup_spop: verify that there is already a valid POP machine_id in the
436 * pop_id field. Also take care of keeping track of the post office usage.
438 int setup_spop(q, argv)
442 EXEC SQL BEGIN DECLARE SECTION;
445 EXEC SQL END DECLARE SECTION;
447 id = *(int *)argv[0];
448 EXEC SQL REPEATED SELECT potype, pop_id INTO :type, :mid FROM users
449 WHERE users_id = :id;
450 if(sqlca.sqlerrd[2] = 0)
452 EXEC SQL REPEATED SELECT mach_id INTO :mid FROM machine
453 WHERE mach_id = :mid;
454 if (sqlca.sqlerrd[2] = 0)
456 if (strcmp(strtrim(type), "POP"))
457 set_pop_usage(mid, 1);
462 /* setup_dpob: Take care of keeping track of the post office usage.
464 int setup_dpob(q, argv)
468 EXEC SQL BEGIN DECLARE SECTION;
471 EXEC SQL END DECLARE SECTION;
473 user = *(int *)argv[0];
474 EXEC SQL REPEATED SELECT potype, pop_id INTO :type, :id FROM users
475 WHERE users_id = :user;
476 if (ingres_errno) return(mr_errcode);
478 if (!strcmp(strtrim(type), "POP"))
479 set_pop_usage(id, -1);
484 /* setup_dmac - verify that the machine is no longer being referenced
485 * and may safely be deleted.
488 int setup_dmac(q, argv)
492 EXEC SQL BEGIN DECLARE SECTION;
494 EXEC SQL END DECLARE SECTION;
496 id = *(int *)argv[0];
497 EXEC SQL REPEATED SELECT login INTO :cdummy FROM users
498 WHERE potype='POP' AND pop_id = :id;
499 if (sqlca.sqlerrd[2] > 0)
501 EXEC SQL REPEATED SELECT mach_id INTO :idummy FROM serverhosts
503 if (sqlca.sqlerrd[2] > 0)
505 EXEC SQL REPEATED SELECT mach_id INTO :idummy FROM nfsphys
507 if (sqlca.sqlerrd[2] > 0)
509 EXEC SQL REPEATED SELECT mach_id INTO :idummy FROM hostaccess
511 if (sqlca.sqlerrd[2] > 0)
513 EXEC SQL REPEATED SELECT mach_id INTO :idummy FROM printcap
515 if (sqlca.sqlerrd[2] > 0)
517 EXEC SQL REPEATED SELECT quotaserver INTO :idummy FROM printcap
518 WHERE quotaserver = :id;
519 if (sqlca.sqlerrd[2] > 0)
521 EXEC SQL REPEATED SELECT mach_id INTO :idummy FROM palladium
523 if (sqlca.sqlerrd[2] > 0)
526 EXEC SQL REPEATED DELETE FROM mcmap WHERE mach_id = :id;
527 if (ingres_errno) return(mr_errcode);
532 /* setup_dclu - verify that the cluster is no longer being referenced
533 * and may safely be deleted.
536 int setup_dclu(q, argv)
540 EXEC SQL BEGIN DECLARE SECTION;
542 EXEC SQL END DECLARE SECTION;
544 id = *(int *)argv[0];
545 EXEC SQL REPEATED SELECT mach_id INTO :idummy FROM mcmap
547 if (sqlca.sqlerrd[2] > 0)
549 EXEC SQL REPEATED SELECT clu_id INTO :idummy FROM svc
551 if (sqlca.sqlerrd[2] > 0)
559 /* setup_alis - if argv[5] is non-zero and argv[6] is UNIQUE_ID, then allocate
560 * a new gid and put it in argv[6]. Otherwise if argv[6] is UNIQUE_ID but
561 * argv[5] is not, then remember that UNIQUE_ID is being stored by putting
562 * a -1 there. Remember that this is also used for ulis, with the indexes
563 * at 6 & 7. Also check that the list name does not contain uppercase
564 * characters, control characters, @, or :.
567 static int badlistchars[] = {
568 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
569 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
570 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
571 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, /* 0 - ? */
572 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
573 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, /* P - _ */
574 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
575 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
576 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
577 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
578 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
579 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
580 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
581 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
582 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
583 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
586 int setup_alis(q, argv, cl)
591 EXEC SQL BEGIN DECLARE SECTION;
593 EXEC SQL END DECLARE SECTION;
598 if (!strcmp(q->shortname, "alis"))
600 else if (!strcmp(q->shortname, "ulis"))
603 for (p = (unsigned char *) argv[idx]; *p; p++)
604 if (badlistchars[*p])
607 if (!strcmp(argv[6 + idx], UNIQUE_GID) || atoi(argv[6 + idx]) == -1) {
608 if (atoi(argv[5 + idx])) {
609 if (set_next_object_id("gid", "list", 1))
610 return(MR_INGRES_ERR);
611 EXEC SQL REPEATED SELECT value INTO :ngid FROM numvalues
613 if (ingres_errno) return(mr_errcode);
614 sprintf(argv[6 + idx], "%d", ngid);
616 strcpy(argv[6 + idx], "-1");
620 if((mr_errcode=prefetch_value(q,argv,cl))!=MR_SUCCESS)
627 /* setup_dlis - verify that the list is no longer being referenced
628 * and may safely be deleted.
631 int setup_dlis(q, argv)
635 EXEC SQL BEGIN DECLARE SECTION;
637 EXEC SQL END DECLARE SECTION;
639 id = *(int *)argv[0];
640 EXEC SQL REPEATED SELECT member_id INTO :idummy FROM imembers
641 WHERE member_id = :id AND member_type='LIST';
642 if (sqlca.sqlerrd[2] > 0)
644 EXEC SQL REPEATED SELECT member_id INTO :idummy FROM imembers
646 if (sqlca.sqlerrd[2] > 0)
648 EXEC SQL REPEATED SELECT label INTO :cdummy FROM filesys
650 if (sqlca.sqlerrd[2] > 0)
652 EXEC SQL REPEATED SELECT tag INTO :cdummy FROM capacls
654 if (sqlca.sqlerrd[2] > 0)
656 EXEC SQL REPEATED SELECT name INTO :cdummy FROM list
657 WHERE acl_id = :id AND acl_type='LIST' AND list_id = :id;
658 if (sqlca.sqlerrd[2] > 0)
660 EXEC SQL REPEATED SELECT name INTO :cdummy FROM servers
661 WHERE acl_id = :id AND acl_type='LIST';
662 if (sqlca.sqlerrd[2] > 0)
664 EXEC SQL REPEATED SELECT entity_id INTO :idummy FROM quota
665 WHERE entity_id = :id AND type='GROUP';
666 if (sqlca.sqlerrd[2] > 0)
668 EXEC SQL REPEATED SELECT acl_id INTO :idummy FROM hostaccess
669 WHERE acl_id = :id AND acl_type='LIST';
670 if (sqlca.sqlerrd[2] > 0)
672 EXEC SQL REPEATED SELECT class INTO :cdummy FROM zephyr z
673 WHERE z.xmt_type = 'LIST' AND z.xmt_id = :id
674 OR z.sub_type = 'LIST' AND z.sub_id = :id
675 OR z.iws_type = 'LIST' AND z.iws_id = :id
676 OR z.iui_type = 'LIST' AND z.iui_id = :id;
677 if (sqlca.sqlerrd[2] > 0)
685 /* setup_dsin - verify that the service is no longer being referenced
686 * and may safely be deleted.
689 int setup_dsin(q, argv)
693 EXEC SQL BEGIN DECLARE SECTION;
695 EXEC SQL END DECLARE SECTION;
699 for(c=name;*c;c++) if(islower(*c)) *c = toupper(*c);
700 EXEC SQL REPEATED SELECT service INTO :cdummy FROM serverhosts
701 WHERE service = :name;
702 if (sqlca.sqlerrd[2] > 0)
704 EXEC SQL REPEATED SELECT inprogress INTO :idummy FROM servers
706 if (sqlca.sqlerrd[2] > 0)
714 /* setup_dshi - verify that the service-host is no longer being referenced
715 * and may safely be deleted.
718 int setup_dshi(q, argv)
722 EXEC SQL BEGIN DECLARE SECTION;
725 EXEC SQL END DECLARE SECTION;
728 for(c=name;*c;c++) if(islower(*c)) *c = toupper(*c); /* to uppercase */
729 id = *(int *)argv[1];
730 EXEC SQL REPEATED SELECT inprogress INTO :idummy FROM serverhosts
731 WHERE service = :name AND mach_id = :id;
732 if (sqlca.sqlerrd[2] > 0)
741 ** setup_add_filesys - verify existance of referenced file systems
753 ** * extract directory prefix from name
754 ** * verify mach_id/dir in nfsphys
755 ** * verify access in {r, w, R, W}
757 ** Side effect: sets variable var_phys_id to the ID of the physical
758 ** filesystem (nfsphys_id for NFS, 0 for RVD)
761 ** MR_NFS - specified directory not exported
762 ** MR_FILESYS_ACCESS - invalid filesys access
766 EXEC SQL BEGIN DECLARE SECTION;
767 static int var_phys_id;
768 EXEC SQL END DECLARE SECTION;
770 setup_afil(q, argv, cl)
777 EXEC SQL BEGIN DECLARE SECTION;
779 char ftype[32], *access;
780 EXEC SQL END DECLARE SECTION;
783 mach_id = *(int *)argv[2];
788 sprintf(ftype, "fs_access_%s", type);
789 EXEC SQL SELECT trans INTO :cdummy FROM alias
790 WHERE name = :ftype AND type = 'TYPE' and trans = :access;
791 if (ingres_errno) return(mr_errcode);
792 if (sqlca.sqlerrd[2] == 0) return(MR_FILESYS_ACCESS);
794 if (!strcmp(type, "NFS"))
795 return (check_nfs(mach_id, name, access));
797 if((mr_errcode=prefetch_value(q,argv,cl))!=MR_SUCCESS)
804 /* Verify the arguments, depending on the FStype. Also, if this is an
805 * NFS filesystem, then update any quotas for that filesystem to reflect
809 setup_ufil(q, argv, cl)
816 EXEC SQL BEGIN DECLARE SECTION;
818 char *entity, ftype[32], *access;
820 EXEC SQL END DECLARE SECTION;
823 mach_id = *(int *)argv[3];
826 fid = *(int *)argv[0];
830 sprintf(ftype, "fs_access_%s", type);
831 EXEC SQL SELECT trans INTO :cdummy FROM alias
832 WHERE name = :ftype AND type='TYPE' AND trans = :access;
833 if (ingres_errno) return(mr_errcode);
834 if (sqlca.sqlerrd[2] == 0) return(MR_FILESYS_ACCESS);
836 if (!strcmp(type, "NFS")) {
837 status = check_nfs(mach_id, name, access);
838 EXEC SQL UPDATE quota SET phys_id = :var_phys_id
839 WHERE filsys_id = :fid;
840 if (ingres_errno) return(mr_errcode);
842 } else if (!strcmp(type, "AFS")) {
844 EXEC SQL REPEATED DELETE FROM quota
845 WHERE type = 'ANY' AND filsys_id = :fid;
846 EXEC SQL SELECT SUM (quota) INTO :total FROM quota
847 WHERE filsys_id = :fid AND phys_id != 0;
848 if (ingres_errno) return(mr_errcode);
851 * append quota (quota = total, filsys_id = fid,
852 * phys_id = 0, entity_id = 0, type = "ANY",
853 * modtime = "now", modby = who, modwith = entity)
855 EXEC SQL INSERT INTO quota (quota, filsys_id, phys_id, entity_id,
856 type, modtime, modby, modwith)
857 VALUES (:total, :fid, 0, 0,
858 'ANY', 'now', :who, :entity) ;
859 if (ingres_errno) return(mr_errcode);
862 EXEC SQL UPDATE quota SET phys_id = 0 WHERE filsys_id = :fid;
863 if (ingres_errno) return(mr_errcode);
869 /* Find the NFS physical partition that the named directory is on.
870 * This is done by comparing the dir against the mount point of the
871 * partition. To make sure we get the correct match when there is
872 * more than one, we sort the query in reverse order by dir name.
875 check_nfs(mach_id, name, access)
876 EXEC SQL BEGIN DECLARE SECTION;
878 EXEC SQL END DECLARE SECTION;
882 EXEC SQL BEGIN DECLARE SECTION;
884 EXEC SQL END DECLARE SECTION;
891 EXEC SQL DECLARE csr101 CURSOR FOR
892 SELECT nfsphys_id, TRIM (dir) FROM nfsphys
893 WHERE mach_id = :mach_id
895 EXEC SQL OPEN csr101;
897 EXEC SQL FETCH csr101 INTO :var_phys_id, :dir;
898 if(sqlca.sqlcode != 0) break;
902 if (*cp1++ != *cp2) break;
910 EXEC SQL CLOSE csr101;
917 /* setup_dfil: free any quota records and fsgroup info associated with
918 * a filesystem when it is deleted. Also adjust the allocation numbers.
921 setup_dfil(q, argv, cl)
926 EXEC SQL BEGIN DECLARE SECTION;
928 EXEC SQL END DECLARE SECTION;
930 id = *(int *)argv[0];
931 EXEC SQL REPEATED SELECT SUM (quota) INTO :total FROM quota
932 WHERE filsys_id = :id;
933 EXEC SQL REPEATED UPDATE nfsphys SET allocated = allocated - :total
934 WHERE nfsphys_id = filesys.phys_id AND filesys.filsys_id = :id;
935 /** Is SQL smart enough to do the PRODUCT above? */
936 /** Or should we code it using another SELECT? */
938 EXEC SQL REPEATED DELETE FROM quota WHERE filsys_id = :id;
939 EXEC SQL REPEATED DELETE FROM fsgroup WHERE filsys_id = :id;
940 EXEC SQL REPEATED DELETE FROM fsgroup WHERE group_id = :id;
941 if (ingres_errno) return(mr_errcode);
946 /* setup_dnfp: check to see that the nfs physical partition does not have
947 * any filesystems assigned to it before allowing it to be deleted.
950 setup_dnfp(q, argv, cl)
955 EXEC SQL BEGIN DECLARE SECTION;
958 EXEC SQL END DECLARE SECTION;
960 id = *(int *)argv[0];
962 EXEC SQL REPEATED SELECT label INTO :cdummy FROM filesys fs, nfsphys np
963 WHERE fs.mach_id = :id AND fs.phys_id = np.nfsphys_id
964 AND np.mach_id = :id AND np.dir = :dir;
965 if (sqlca.sqlerrd[2] > 0)
973 /* setup_dqot: Remove allocation from nfsphys before deleting quota.
974 * argv[0] = filsys_id
975 * argv[1] = type if "update_quota" or "delete_quota"
976 * argv[2 or 1] = users_id or list_id
979 setup_dqot(q, argv, cl)
984 EXEC SQL BEGIN DECLARE SECTION;
987 EXEC SQL END DECLARE SECTION;
989 fs = *(int *)argv[0];
990 if (!strcmp(q->name, "update_quota") || !strcmp(q->name, "delete_quota")) {
992 id = *(int *)argv[2];
995 id = *(int *)argv[1];
998 EXEC SQL REPEATED SELECT quota INTO :quota FROM quota
999 WHERE type = :qtype AND entity_id = :id AND filsys_id = :fs;
1000 EXEC SQL REPEATED UPDATE nfsphys
1001 SET allocated = nfsphys.allocated - :quota
1002 WHERE nfsphys_id = filesys.physid AND filesys.filsys_id = :fs;
1004 if (ingres_errno) return(mr_errcode);
1009 /* setup_sshi: don't exclusive lock the machine table during
1010 * set_server_host_internal.
1013 setup_sshi(q, argv, cl)
1019 EXEC SQL set lockmode session where readlock = system;
1024 /* setup add_kerberos_user_mapping: add the string to the string
1025 * table if necessary.
1028 setup_akum(q, argv, cl)
1033 EXEC SQL BEGIN DECLARE SECTION;
1036 EXEC SQL END DECLARE SECTION;
1039 if (name_to_id(name, "STRING", &id) != MR_SUCCESS) {
1040 if (q->type != APPEND) return(MR_STRING);
1041 EXEC SQL SELECT value INTO :id FROM numvalues
1042 WHERE name = 'strings_id';
1044 EXEC SQL UPDATE numvalues SET value = :id
1045 WHERE name = 'strings_id';
1046 EXEC SQL INSERT INTO strings (string_id, string) VALUES (:id, :name);
1047 cache_entry(name, "STRING", id);
1049 if (ingres_errno) return(mr_errcode);
1050 *(int *)argv[1] = id;
1056 /* FOLLOWUP ROUTINES */
1058 /* generic set_modtime routine. This takes the table name from the query,
1059 * and will update the modtime, modby, and modwho fields in the entry in
1060 * the table whose name field matches argv[0].
1063 set_modtime(q, argv, cl)
1068 char *name, *entity, *table;
1071 entity = cl->entity;
1072 who = cl->client_id;
1076 sprintf(stmt_buf,"UPDATE %s SET modtime = 'now', modby = %d, modwith = '%s' WHERE %s.name = LEFT('%s',SIZE(%s.name))",table,who,entity,table,name,table);
1077 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
1082 /* generic set_modtime_by_id routine. This takes the table name from
1083 * the query, and the id name from the validate record,
1084 * and will update the modtime, modby, and modwho fields in the entry in
1085 * the table whose id matches argv[0].
1088 set_modtime_by_id(q, argv, cl)
1093 char *entity, *table, *id_name;
1096 entity = cl->entity;
1097 who = cl->client_id;
1099 id_name = q->validate->object_id;
1101 id = *(int *)argv[0];
1102 sprintf(stmt_buf,"UPDATE %s SET modtime = 'now', modby = %d, \
1103 modwith = '%s' WHERE %s.%s = %d",table,who,entity,table,id_name,id);
1104 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
1109 /* Sets the finger modtime on a user record. The users_id will be in argv[0].
1112 set_finger_modtime(q, argv, cl)
1117 EXEC SQL BEGIN DECLARE SECTION;
1120 EXEC SQL END DECLARE SECTION;
1122 entity = cl->entity;
1123 who = cl->client_id;
1124 users_id = *(int *)argv[0];
1126 EXEC SQL UPDATE users SET fmodtime='now', fmodby = :who, fmodwith = :entity
1127 WHERE users.users_id = :users_id;
1133 /* Sets the pobox modtime on a user record. The users_id will be in argv[0].
1136 set_pobox_modtime(q, argv, cl)
1141 EXEC SQL BEGIN DECLARE SECTION;
1144 EXEC SQL END DECLARE SECTION;
1146 entity = cl->entity;
1147 who = cl->client_id;
1148 users_id = *(int *)argv[0];
1150 EXEC SQL UPDATE users SET pmodtime='now', pmodby = :who, pmodwith = :entity
1151 WHERE users.users_id = :users_id;
1157 /* Like set_modtime, but uppercases the name first.
1160 set_uppercase_modtime(q, argv, cl)
1165 char *name, *entity, *table;
1168 entity = cl->entity;
1169 who = cl->client_id;
1173 sprintf(stmt_buf,"UPDATE %s SET modtime = 'now', modby = %d, modwith = '%s' WHERE %s.name = UPPERCASE(LEFT('%s',SIZE(%s.name)))",table,who,entity,table,name,table);
1174 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
1180 /* Sets the modtime on the machine whose mach_id is in argv[0]. This routine
1181 * is necessary for add_machine_to_cluster becuase the table that query
1182 * operates on is "mcm", not "machine".
1185 set_mach_modtime_by_id(q, argv, cl)
1190 EXEC SQL BEGIN DECLARE SECTION;
1193 EXEC SQL END DECLARE SECTION;
1195 entity = cl->entity;
1196 who = cl->client_id;
1197 id = *(int *)argv[0];
1198 EXEC SQL UPDATE machine SET modtime='now', modby = :who, modwith = :entity
1199 WHERE machine.mach_id = :id;
1205 /* Sets the modtime on the cluster whose mach_id is in argv[0]. This routine
1206 * is necessary for add_cluster_data and delete_cluster_data becuase the
1207 * table that query operates on is "svc", not "cluster".
1210 set_cluster_modtime_by_id(q, argv, cl)
1215 EXEC SQL BEGIN DECLARE SECTION;
1218 EXEC SQL END DECLARE SECTION;
1220 entity = cl->entity;
1221 who = cl->client_id;
1223 id = *(int *)argv[0];
1224 EXEC SQL UPDATE cluster SET modtime='now', modby = :who, modwith = :entity
1225 WHERE cluster.clu_id = :id;
1230 /* sets the modtime on the serverhost where the service name is in argv[0]
1231 * and the mach_id is in argv[1].
1234 set_serverhost_modtime(q, argv, cl)
1239 EXEC SQL BEGIN DECLARE SECTION;
1240 char *entity, *serv;
1242 EXEC SQL END DECLARE SECTION;
1244 entity = cl->entity;
1245 who = cl->client_id;
1248 id = *(int *)argv[1];
1249 EXEC SQL UPDATE serverhosts
1250 SET modtime = 'now', modby = :who, modwith = :entity
1251 WHERE service = :serv AND mach_id = :id;
1256 /* sets the modtime on the nfsphys where the mach_id is in argv[0] and the
1257 * directory name is in argv[1].
1260 set_nfsphys_modtime(q, argv, cl)
1265 EXEC SQL BEGIN DECLARE SECTION;
1268 EXEC SQL END DECLARE SECTION;
1270 entity = cl->entity;
1271 who = cl->client_id;
1273 id = *(int *)argv[0];
1275 EXEC SQL UPDATE nfsphys SET modtime = 'now', modby = :who, modwith = :entity
1276 WHERE dir = :dir AND mach_id = :id;
1281 /* sets the modtime on a filesystem, where argv[0] contains the filesys
1285 set_filesys_modtime(q, argv, cl)
1290 EXEC SQL BEGIN DECLARE SECTION;
1291 char *label, *entity;
1293 EXEC SQL END DECLARE SECTION;
1295 entity = cl->entity;
1296 who = cl->client_id;
1299 if (!strcmp(q->shortname, "ufil"))
1302 EXEC SQL UPDATE filesys SET modtime = 'now', modby = :who,
1303 modwith = :entity, phys_id = :var_phys_id
1304 WHERE label = LEFT(:label,SIZE(label));
1309 /* sets the modtime on a zephyr class, where argv[0] contains the class
1313 set_zephyr_modtime(q, argv, cl)
1318 EXEC SQL BEGIN DECLARE SECTION;
1319 char *class, *entity;
1321 EXEC SQL END DECLARE SECTION;
1323 entity = cl->entity;
1324 who = cl->client_id;
1328 EXEC SQL UPDATE zephyr SET modtime = 'now', modby = :who, modwith = :entity
1329 WHERE class = LEFT(:class,SIZE(class));
1335 /* fixes the modby field. This will be the second to last thing in the
1336 * argv, the argv length is determined from the query structure. It is
1337 * passed as a pointer to an integer. This will either turn it into a
1338 * username, or # + the users_id.
1340 followup_fix_modby(q, sq, v, action, actarg, cl)
1342 register struct save_queue *sq;
1344 register int (*action)();
1345 register int actarg;
1349 char **argv, *malloc();
1353 while (sq_get_data(sq, &argv)) {
1356 status = id_to_name(id, "USER", &argv[i]);
1358 status = id_to_name(-id, "STRING", &argv[i]);
1359 if (status && status != MR_NO_MATCH)
1361 (*action)(q->vcnt, argv, actarg);
1362 for (j = 0; j < q->vcnt; j++)
1371 /* After retrieving a user account, fix the modby field and signature.
1372 * The modby field is the second to last thing in the
1373 * argv, the argv length is determined from the query structure. It is
1374 * passed as a pointer to an integer. This will either turn it into a
1375 * username, or # + the users_id. Only "gua*" queries have a signature,
1376 * these are ones with U_END return values. "gub*" queries also use this
1377 * routine but don't have a signature.
1379 followup_guax(q, sq, v, action, actarg, cl)
1381 register struct save_queue *sq;
1383 register int (*action)();
1384 register int actarg;
1388 char **argv, *malloc();
1390 unsigned char sigbuf[256];
1393 EXEC SQL BEGIN DECLARE SECTION;
1396 EXEC SQL END DECLARE SECTION;
1401 while (sq_get_data(sq, &argv)) {
1404 status = id_to_name(id, "USER", &argv[i]);
1406 status = id_to_name(-id, "STRING", &argv[i]);
1407 if (status && status != MR_NO_MATCH)
1410 if (q->vcnt == U_END && strlen(argv[U_SIGNATURE])) {
1411 login = argv[U_NAME];
1412 EXEC SQL REPEATED SELECT sigdate, sigwho
1413 INTO :timestamp, :who FROM users
1414 WHERE login = :login; /** Use LEFT(...,SIZE(...)) here? **/
1415 /** What about (INGRES) error handling? **/
1416 /** Is this guaranteed to be a singleton select? **/
1418 status = id_to_name(who, "STRING", &kname);
1419 si.timestamp = timestamp;
1420 si.SigInfoVersion = 0; /* XXXXX this isn't used */
1421 kname_parse(si.pname, si.pinst, si.prealm, kname);
1423 si.rawsig = (unsigned char *)argv[U_SIGNATURE];
1424 GDSS_Recompose(&si, sigbuf);
1425 argv[U_SIGNATURE] = strsave(sigbuf);
1428 (*action)(q->vcnt, argv, actarg);
1429 for (j = 0; j < q->vcnt; j++)
1439 ** followup_ausr - add finger and pobox entries, set_user_modtime
1442 ** argv[0] - login (add_user)
1443 ** argv[3] - last name
1444 ** argv[4] - first name
1445 ** argv[5] - middle name
1449 followup_ausr(q, argv, cl)
1454 EXEC SQL BEGIN DECLARE SECTION;
1455 int who, status, id;
1456 char *login, *entity, *src, *dst, *name;
1458 EXEC SQL END DECLARE SECTION;
1460 char databuf[32], *kname_unparse();
1461 EXEC SQL BEGIN DECLARE SECTION;
1463 int sigwho, timestamp;
1464 EXEC SQL END DECLARE SECTION;
1468 /* build fullname */
1469 if (strlen(argv[4]) && strlen(argv[5]))
1470 sprintf(fullname, "%s %s %s", argv[4], argv[5], argv[3]);
1471 else if (strlen(argv[4]))
1472 sprintf(fullname, "%s %s", argv[4], argv[3]);
1474 sprintf(fullname, "%s", argv[3]);
1477 if (q->vcnt == U_END && *argv[U_SIGNATURE]) {
1478 sprintf(databuf, "%s:%s", argv[U_NAME], argv[U_MITID]);
1479 /* skip bytes for timestamp & kname */
1480 si.rawsig = (unsigned char *) rawsig;
1481 status = GDSS_Verify(databuf, strlen(databuf), argv[U_SIGNATURE], &si);
1483 name = kname_unparse(si.pname, si.pinst, si.prealm);
1484 status = name_to_id(name, "STRING", &sigwho);
1485 if (status == MR_NO_MATCH) {
1486 EXEC SQL REPEATED SELECT value INTO :sigwho FROM numvalues
1487 WHERE name='strings_id';
1489 EXEC SQL REPEATED UPDATE numvalues SET value = :sigwho
1490 WHERE name='strings_id';
1491 INSERT INTO strings (string_id, string)
1492 VALUES (:sigwho, :name);
1494 return(gdss2et(status));
1495 timestamp = si.timestamp;
1497 return(gdss2et(status));
1506 who = cl->client_id;
1507 entity = cl->entity;
1509 /* create finger entry, pobox & set modtime on user */
1511 EXEC SQL REPEATED UPDATE users
1512 SET modtime='now', modby=:who, modwith = :entity,
1513 fullname = :fullname, affiliation = type,
1514 signature = :rawsig, sigdate = :timestamp, sigwho = :sigwho,
1515 fmodtime='now', fmodby = :who, fmodwith = :entity,
1516 potype='NONE', pmodtime='now', pmodby = :who, pmodwith = :entity
1517 WHERE login = :login;
1519 EXEC SQL REPEATED UPDATE users
1520 SET modtime='now', modby=:who, modwith = :entity,
1521 fullname = :fullname, affiliation = type,
1522 fmodtime='now', fmodby = :who, fmodwith = :entity,
1523 potype='NONE', pmodtime='now', pmodby = :who, pmodwith = :entity
1524 WHERE login = :login;
1532 ** followup_uusr - do signature, set_user_modtime
1535 ** argv[0] - login (add_user)
1536 ** argv[U_SIGNATURE] - sig
1540 followup_uuac(q, argv, cl)
1545 EXEC SQL BEGIN DECLARE SECTION;
1546 int who, status, id;
1547 char *entity, *name;
1548 EXEC SQL END DECLARE SECTION;
1550 char databuf[32], *kname_unparse();
1551 EXEC SQL BEGIN DECLARE SECTION;
1554 int sigwho, timestamp;
1555 EXEC SQL END DECLARE SECTION;
1559 id = *(int *)argv[0];
1560 who = cl->client_id;
1561 entity = cl->entity;
1564 if (q->vcnt == U_MODTIME && *argv[U_SIGNATURE + 1]) {
1566 status = id_to_name(id, "USER", &login);
1567 sprintf(databuf, "%s:%s", login, argv[U_MITID+1]);
1569 /* skip bytes for timestamp & kname */
1570 si.rawsig = (unsigned char *) rawsig;
1571 status = GDSS_Verify(databuf, strlen(databuf), argv[U_SIGNATURE+1], &si);
1573 name = kname_unparse(si.pname, si.pinst, si.prealm);
1574 status = name_to_id(name, "STRING", &sigwho);
1575 if (status == MR_NO_MATCH) {
1576 EXEC SQL REPEATED SELECT value INTO :sigwho FROM numvalues
1577 WHERE name='strings_id';
1579 EXEC SQL REPEATED UPDATE numvalues SET value = :sigwho
1580 WHERE name='strings_id';
1581 INSERT INTO strings (string_id, string)
1582 VALUES (:sigwho, :name);
1584 return(gdss2et(status));
1585 timestamp = si.timestamp;
1587 return(gdss2et(status));
1595 /* create finger entry, pobox & set modtime on user */
1598 EXEC SQL REPEATED UPDATE users SET modtime='now', modby = :who, modwith = :entity,
1599 signature = :rawsig, sigdate = :timestamp, sigwho = :sigwho
1600 WHERE users_id = :id;
1602 EXEC SQL REPEATED UPDATE users SET modtime='now', modby = :who, modwith = :entity
1603 WHERE users_id = :id;
1609 /* followup_gpob: fixes argv[2] based on the IDs currently there and the
1610 * type in argv[1]. Then completes the upcall to the user.
1612 * argv[2] is of the form "123:234" where the first integer is the machine
1613 * ID if it is a pop box, and the second is the string ID if it is an SMTP
1614 * box. argv[1] should be "POP", "SMTP", or "NONE". Boxes of type NONE
1618 followup_gpob(q, sq, v, action, actarg, cl)
1619 register struct query *q;
1620 register struct save_queue *sq;
1621 register struct validate *v;
1622 register int (*action)();
1626 char **argv, *index();
1628 int mid, sid, status, i;
1631 while (sq_get_data(sq, &argv)) {
1632 mr_trim_args(2, argv);
1634 p = index(argv[2], ':');
1636 mid = atoi(argv[2]);
1639 if (!strcmp(ptype, "POP")) {
1640 status = id_to_name(mid, "MACHINE", &argv[2]);
1641 if (status == MR_NO_MATCH)
1643 } else if (!strcmp(ptype, "SMTP")) {
1644 status = id_to_name(sid, "STRING", &argv[2]);
1645 if (status == MR_NO_MATCH)
1647 } else /* ptype == "NONE" */ {
1650 if (status) return(status);
1652 if (!strcmp(q->shortname, "gpob")) {
1653 sid = atoi(argv[4]);
1655 status = id_to_name(sid, "USER", &argv[4]);
1657 status = id_to_name(-sid, "STRING", &argv[4]);
1659 if (status && status != MR_NO_MATCH) return(status);
1661 (*action)(q->vcnt, argv, actarg);
1663 /* free saved data */
1664 for (i = 0; i < q->vcnt; i++)
1670 return (MR_SUCCESS);
1674 /* followup_glin: fix the ace_name in argv[8]. argv[7] will contain the
1675 * ace_type: "LIST", "USER", or "NONE". Decode the id in argv[8] into the
1676 * proper name based on the type, and repace that string in the argv.
1677 * Also fixes the modby field by called followup_fix_modby.
1680 followup_glin(q, sq, v, action, actarg, cl)
1681 register struct query *q;
1682 register struct save_queue *sq;
1683 register struct validate *v;
1684 register int (*action)();
1688 char **argv, *malloc(), *realloc(), *type;
1689 int id, i, idx, status;
1692 if (!strcmp(q->shortname, "gsin"))
1695 while (sq_get_data(sq, &argv)) {
1696 mr_trim_args(q->vcnt, argv);
1698 id = atoi(argv[i = q->vcnt - 2]);
1700 status = id_to_name(id, "USER", &argv[i]);
1702 status = id_to_name(-id, "STRING", &argv[i]);
1703 if (status && status != MR_NO_MATCH)
1706 id = atoi(argv[idx]);
1707 type = argv[idx - 1];
1709 if (!strcmp(type, "LIST")) {
1710 status = id_to_name(id, "LIST", &argv[idx]);
1711 } else if (!strcmp(type, "USER")) {
1712 status = id_to_name(id, "USER", &argv[idx]);
1713 } else if (!strcmp(type, "KERBEROS")) {
1714 status = id_to_name(id, "STRING", &argv[idx]);
1715 } else if (!strcmp(type, "NONE")) {
1718 argv[idx] = strsave("NONE");
1722 argv[idx] = strsave("???");
1724 if (status && status != MR_NO_MATCH)
1727 if (!strcmp(q->shortname, "glin") && atoi(argv[6]) == -1) {
1728 argv[6] = realloc(argv[6], strlen(UNIQUE_GID) + 1);
1729 strcpy(argv[6], UNIQUE_GID);
1733 (*action)(q->vcnt, argv, actarg);
1735 /* free saved data */
1736 for (i = 0; i < q->vcnt; i++)
1742 return (MR_SUCCESS);
1746 /* followup_gqot: Fix the entity name, directory name & modby fields
1747 * argv[0] = filsys_id
1749 * argv[2] = entity_id
1750 * argv[3] = ascii(quota)
1753 followup_gqot(q, sq, v, action, actarg, cl)
1755 register struct save_queue *sq;
1757 register int (*action)();
1758 register int actarg;
1762 char **argv, *malloc();
1763 EXEC SQL BEGIN DECLARE SECTION;
1766 EXEC SQL END DECLARE SECTION;
1769 if (!strcmp(q->name, "get_quota") ||
1770 !strcmp(q->name, "get_quota_by_filesys"))
1774 while (sq_get_data(sq, &argv)) {
1776 switch (argv[1][0]) {
1778 status = id_to_name(atoi(argv[2]), "USER", &argv[2]);
1782 status = id_to_name(atoi(argv[2]), "LIST", &argv[2]);
1786 argv[2] = strsave("system:anyuser");
1790 argv[2] = malloc(8);
1791 sprintf(argv[2], "%d", id);
1794 id = atoi(argv[idx]);
1796 argv[idx] = malloc(256);
1800 EXEC SQL REPEATED SELECT name INTO :name FROM filesys
1801 WHERE label = :label;
1803 EXEC SQL REPEATED SELECT dir INTO :name FROM nfsphys
1804 WHERE nfsphys_id = :id;
1806 if (sqlca.sqlerrd[2] != 1) {
1807 sprintf(argv[idx], "#%d", id);
1810 id = atoi(argv[idx+3]);
1812 status = id_to_name(id, "USER", &argv[idx+3]);
1814 status = id_to_name(-id, "STRING", &argv[idx+3]);
1815 if (status && status != MR_NO_MATCH)
1817 (*action)(q->vcnt, argv, actarg);
1818 for (j = 0; j < q->vcnt; j++)
1827 /* followup_aqot: Add allocation to nfsphys after creating quota.
1828 * argv[0] = filsys_id
1829 * argv[1] = type if "add_quota" or "update_quota"
1831 * argv[3 or 2] = ascii(quota)
1834 followup_aqot(q, argv, cl)
1839 EXEC SQL BEGIN DECLARE SECTION;
1840 int quota, id, fs, who;
1841 char *entity, *qtype;
1842 EXEC SQL END DECLARE SECTION;
1844 fs = *(int *)argv[0];
1845 if (!strcmp(q->name, "add_quota") || !strcmp(q->name, "update_quota")) {
1847 id = *(int *)argv[2];
1848 quota = atoi(argv[3]);
1851 id = *(int *)argv[1];
1852 quota = atoi(argv[2]);
1854 who = cl->client_id;
1855 entity = cl->entity;
1857 EXEC SQL REPEATED UPDATE quota
1858 SET modtime = 'now', modby = :who, modwith = :entity
1859 WHERE filsys_id = :fs and type = :qtype and entity_id = :id;
1860 EXEC SQL REPEATED UPDATE nfsphys
1861 SET allocated = allocated + :quota
1862 WHERE nfsphys_id = filesys.phys_id AND filesys.filsys_id = :fs;
1863 if (ingres_errno) return(mr_errcode);
1868 followup_gpce(q, sq, v, action, actarg, cl)
1870 register struct save_queue *sq;
1872 register int (*action)();
1873 register int actarg;
1877 char **argv, *malloc();
1881 while (sq_get_data(sq, &argv)) {
1882 id = atoi(argv[PCAP_QSERVER]);
1883 status = id_to_name(id, "MACHINE", &argv[PCAP_QSERVER]);
1884 if (status) return (status);
1887 status = id_to_name(id, "USER", &argv[i]);
1889 status = id_to_name(-id, "STRING", &argv[i]);
1890 if (status && status != MR_NO_MATCH)
1892 (*action)(q->vcnt, argv, actarg);
1893 for (j = 0; j < q->vcnt; j++)
1905 followup_gzcl(q, sq, v, action, actarg, cl)
1906 register struct query *q;
1907 register struct save_queue *sq;
1908 register struct validate *v;
1909 register int (*action)();
1916 while (sq_get_data(sq, &argv)) {
1917 mr_trim_args(q->vcnt, argv);
1919 id = atoi(argv[i = q->vcnt - 2]);
1921 status = id_to_name(id, "USER", &argv[i]);
1923 status = id_to_name(-id, "STRING", &argv[i]);
1924 if (status && status != MR_NO_MATCH)
1927 for (i = 1; i < 8; i+=2) {
1928 id = atoi(argv[i+1]);
1929 if (!strcmp(argv[i], "LIST")) {
1930 status = id_to_name(id, "LIST", &argv[i+1]);
1931 } else if (!strcmp(argv[i], "USER")) {
1932 status = id_to_name(id, "USER", &argv[i+1]);
1933 } else if (!strcmp(argv[i], "KERBEROS")) {
1934 status = id_to_name(id, "STRING", &argv[i+1]);
1935 } else if (!strcmp(argv[i], "NONE")) {
1938 argv[i+1] = strsave("NONE");
1942 argv[i+1] = strsave("???");
1944 if (status && status != MR_NO_MATCH)
1949 (*action)(q->vcnt, argv, actarg);
1951 /* free saved data */
1952 for (i = 0; i < q->vcnt; i++)
1964 followup_gsha(q, sq, v, action, actarg, cl)
1965 register struct query *q;
1966 register struct save_queue *sq;
1967 register struct validate *v;
1968 register int (*action)();
1975 while (sq_get_data(sq, &argv)) {
1976 mr_trim_args(q->vcnt, argv);
1980 status = id_to_name(id, "USER", &argv[4]);
1982 status = id_to_name(-id, "STRING", &argv[4]);
1983 if (status && status != MR_NO_MATCH)
1987 if (!strcmp(argv[1], "LIST")) {
1988 status = id_to_name(id, "LIST", &argv[2]);
1989 } else if (!strcmp(argv[1], "USER")) {
1990 status = id_to_name(id, "USER", &argv[2]);
1991 } else if (!strcmp(argv[1], "KERBEROS")) {
1992 status = id_to_name(id, "STRING", &argv[2]);
1993 } else if (!strcmp(argv[1], "NONE")) {
1996 argv[2] = strsave("NONE");
2000 argv[2] = strsave("???");
2002 if (status && status != MR_NO_MATCH)
2006 (*action)(q->vcnt, argv, actarg);
2008 /* free saved data */
2009 for (i = 0; i < q->vcnt; i++)
2019 /* Special query routines */
2021 /* set_pobox - this does all of the real work.
2022 * argv = user_id, type, box
2023 * if type is POP, then box should be a machine, and its ID should be put in
2024 * pop_id. If type is SMTP, then box should be a string and its ID should
2025 * be put in box_id. If type is NONE, then box doesn't matter.
2028 int set_pobox(q, argv, cl)
2033 EXEC SQL BEGIN DECLARE SECTION;
2035 char *box, potype[9];
2036 EXEC SQL END DECLARE SECTION;
2040 user = *(int *)argv[0];
2042 EXEC SQL REPEATED SELECT pop_id, potype INTO :id, :potype FROM users
2043 WHERE users_id = :user;
2044 if (ingres_errno) return(mr_errcode);
2045 if (!strcmp(strtrim(potype), "POP"))
2046 set_pop_usage(id, -1);
2048 if (!strcmp(argv[1], "POP")) {
2049 status = name_to_id(box, "MACHINE", &id);
2050 if (status == MR_NO_MATCH)
2054 EXEC SQL REPEATED UPDATE users SET potype = 'POP', pop_id = :id
2055 WHERE users_id = :user;
2056 set_pop_usage(id, 1);
2057 } else if (!strcmp(argv[1], "SMTP")) {
2058 if (index(box, '/') || index(box, '|'))
2059 return(MR_BAD_CHAR);
2060 status = name_to_id(box, "STRING", &id);
2061 if (status == MR_NO_MATCH) {
2062 EXEC SQL REPEATED SELECT value INTO :id FROM numvalues
2063 WHERE name='strings_id';
2065 EXEC SQL REPEATED UPDATE numvalues SET value = :id
2066 WHERE name='strings_id';
2067 EXEC SQL INSERT INTO strings (string_id, string)
2071 EXEC SQL REPEATED UPDATE users SET potype='SMTP', box_id = :id
2072 WHERE users_id = :user;
2073 } else /* argv[1] == "NONE" */ {
2074 EXEC SQL REPEATED UPDATE users SET potype='NONE'
2075 WHERE users_id = :user;
2078 set_pobox_modtime(q, argv, cl);
2079 EXEC SQL REPEATED UPDATE tblstats SET updates = updates+1, modtime='now'
2080 WHERE tblstats.table_name='users';
2081 if (ingres_errno) return(mr_errcode);
2086 /* get_list_info: passed a wildcard list name, returns lots of stuff about
2087 * each list. This is tricky: first build a queue of all requested
2088 * data. Rest of processing consists of fixing gid, ace_name, and modby.
2091 get_list_info(q, aargv, cl, action, actarg)
2092 register struct query *q;
2095 register int (*action)();
2098 char *argv[13], *malloc(), *realloc();
2099 EXEC SQL BEGIN DECLARE SECTION;
2100 char *name, acl_type[9], listname[33], active[5], public[5], hidden[5];
2101 char maillist[5], grouplist[5], gid_str[6], acl_name[256], desc[256];
2102 char modtime[27], modby[256], modwith[9];
2103 int id, rowcount, acl_id, hid, modby_id;
2104 EXEC SQL END DECLARE SECTION;
2105 int returned, status;
2106 struct save_queue *sq, *sq_create();
2108 returned = rowcount = 0;
2110 convert_wildcards(name);
2113 EXEC SQL DECLARE csr102 CURSOR FOR SELECT list_id FROM list
2114 WHERE name LIKE :name ESCAPE '*';
2115 EXEC SQL OPEN csr102;
2118 EXEC SQL FETCH csr102 INTO :id;
2119 if(sqlca.sqlcode!=0) break;
2120 sq_save_data(sq, id);
2123 EXEC SQL CLOSE csr102;
2125 if (ingres_errno) return(mr_errcode);
2127 return(MR_NO_MATCH);
2129 argv[0] = listname; argv[1] = active; argv[2] = public; argv[3] = hidden;
2130 argv[4] = maillist; argv[5] = grouplist; argv[6] = gid_str;
2131 argv[7] = acl_type; argv[9] = desc; argv[10] = modtime; argv[12] = modwith;
2133 while (sq_get_data(sq, &id)) {
2137 EXEC SQL REPEATED SELECT name, CHAR(active), CHAR(publicflg),
2138 CHAR(hidden), hidden, CHAR(maillist), CHAR(grouplist), CHAR(gid),
2139 TRIM(acl_type), acl_id, description, CHAR(modtime), modby, modwith
2140 INTO :listname, :active, :public, :hidden, :hid, :maillist,
2141 :grouplist, :gid_str, :acl_type, :acl_id, :desc,
2142 :modtime, :modby_id, :modwith
2143 FROM list WHERE list_id = :id;
2145 if (ingres_errno) return(mr_errcode);
2147 if (atoi(gid_str) == -1)
2148 argv[6] = UNIQUE_GID;
2150 argv[8] = malloc(0);
2151 if (!strcmp(acl_type, "LIST")) {
2152 status = id_to_name(acl_id, "LIST", &argv[8]);
2153 } else if (!strcmp(acl_type, "USER")) {
2154 status = id_to_name(acl_id, "USER", &argv[8]);
2155 } else if (!strcmp(acl_type, "KERBEROS")) {
2156 status = id_to_name(acl_id, "STRING", &argv[8]);
2157 } else if (!strcmp(acl_type, "NONE")) {
2160 argv[8] = strsave("NONE");
2164 argv[8] = strsave("???");
2166 if (status && status != MR_NO_MATCH) return(status);
2168 argv[11] = malloc(0);
2170 status = id_to_name(modby_id, "USER", &argv[11]);
2172 status = id_to_name(-modby_id, "STRING", &argv[11]);
2173 if (status && status != MR_NO_MATCH) return(status);
2175 mr_trim_args(q->vcnt, argv);
2177 (*action)(q->vcnt, argv, actarg);
2183 if (ingres_errno) return(mr_errcode);
2184 return (MR_SUCCESS);
2188 /* Add_member_to_list: do list flattening as we go! MAXLISTDEPTH is
2189 * how many different ancestors a member is allowed to have.
2192 #define MAXLISTDEPTH 1024
2194 int add_member_to_list(q, argv, cl)
2199 EXEC SQL BEGIN DECLARE SECTION;
2200 int id, lid, mid, error, who, ref;
2201 char *mtype, dtype[9], *entity;
2202 EXEC SQL END DECLARE SECTION;
2203 int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a;
2204 int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d;
2206 char *dtypes[MAXLISTDEPTH];
2207 char *iargv[3], *buf;
2209 lid = *(int *)argv[0];
2211 mid = *(int *)argv[2];
2212 /* if the member is already a direct member of the list, punt */
2213 EXEC SQL REPEATED SELECT list_id INTO :idummy FROM imembers
2214 WHERE list_id = :lid AND member_id = :mid
2215 AND member_type = :mtype AND direct = 1;
2216 if (sqlca.sqlerrd[2] > 0)
2218 if (!strcasecmp(mtype, "STRING")) {
2220 status = id_to_name(mid, "STRING", &buf);
2221 if (status) return(status);
2222 if (index(buf, '/') || index(buf, '|')) {
2224 return(MR_BAD_CHAR);
2232 EXEC SQL DECLARE csr103 CURSOR FOR
2233 SELECT list_id, ref_count FROM imembers
2234 WHERE member_id = :lid AND member_type='LIST';
2235 EXEC SQL OPEN csr103;
2237 EXEC SQL FETCH csr103 INTO :id, :ref;
2238 if(sqlca.sqlcode != 0) break;
2240 ancestors[acount++] = id;
2241 if (acount >= MAXLISTDEPTH) break;
2243 EXEC SQL CLOSE csr103;
2244 if (ingres_errno) return(mr_errcode);
2245 if (acount >= MAXLISTDEPTH) {
2246 return(MR_INTERNAL);
2248 descendants[0] = mid;
2253 if (!strcmp(mtype, "LIST")) {
2254 EXEC SQL DECLARE csr104 CURSOR FOR
2255 SELECT member_id, member_type, ref_count
2257 WHERE list_id = :mid;
2258 EXEC SQL OPEN csr104;
2260 EXEC SQL FETCH csr104 INTO :id, :dtype, :ref;
2261 if(sqlca.sqlcode != 0) break;
2264 dtypes[dcount] = "LIST";
2267 dtypes[dcount] = "USER";
2270 dtypes[dcount] = "STRING";
2273 dtypes[dcount] = "KERBEROS";
2280 descendants[dcount++] = id;
2281 if (dcount >= MAXLISTDEPTH) {
2286 EXEC SQL CLOSE csr104;
2287 if (ingres_errno) return(mr_errcode);
2289 return(MR_INTERNAL);
2291 for (a = 0; a < acount; a++) {
2293 for (d = 0; d < dcount; d++) {
2294 mid = descendants[d];
2296 if (mid == lid && !strcmp(mtype, "LIST")) {
2297 return(MR_LISTLOOP);
2299 EXEC SQL REPEATED SELECT ref_count INTO :idummy FROM imembers
2300 WHERE list_id = :lid AND member_id = :mid
2301 AND member_type = :mtype;
2302 ref = aref[a] * dref[d];
2303 if (sqlca.sqlerrd[2] > 0) {
2304 if (a == 0 && d == 0) {
2305 EXEC SQL UPDATE imembers
2306 SET ref_count = ref_count+ref, direct=1
2307 WHERE list_id = :lid AND member_id = :mid
2308 AND member_type = :mtype;
2310 EXEC SQL UPDATE imembers
2311 SET ref_count = ref_count+ref
2312 WHERE list_id = :lid AND member_id = :mid
2313 AND member_type = :mtype;
2316 incremental_clear_before();
2317 if (a == 0 && d == 0) {
2318 EXEC SQL INSERT INTO imembers
2319 (list_id, member_id, direct, member_type, ref_count)
2320 VALUES (:lid, :mid, 1, :mtype, 1);
2322 EXEC SQL INSERT INTO imembers
2323 (list_id, member_id, member_type, ref_count)
2324 VALUES (:lid, :mid, :mtype, 1);
2326 iargv[0] = (char *)lid;
2328 iargv[2] = (char *)mid;
2329 incremental_after("members", 0, iargv);
2333 lid = *(int *)argv[0];
2334 entity = cl->entity;
2335 who = cl->client_id;
2336 EXEC SQL REPEATED UPDATE list
2337 SET modtime='now', modby = :who, modwith = :entity
2338 WHERE list_id = :lid;
2339 if (ingres_errno) return(mr_errcode);
2344 /* Delete_member_from_list: do list flattening as we go!
2347 int delete_member_from_list(q, argv, cl)
2352 EXEC SQL BEGIN DECLARE SECTION;
2353 int id, lid, mid, cnt, error, who, ref;
2354 char *mtype, dtype[9], *entity;
2355 EXEC SQL END DECLARE SECTION;
2356 int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a;
2357 int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d;
2358 char *dtypes[MAXLISTDEPTH];
2361 lid = *(int *)argv[0];
2363 mid = *(int *)argv[2];
2364 /* if the member is not a direct member of the list, punt */
2365 EXEC SQL REPEATED SELECT list_id INTO :idummy FROM imembers
2366 WHERE list_id = :lid AND member_id = :mid
2367 AND member_type = :mtype AND direct = 1;
2368 if (ingres_errno) return(mr_errcode);
2369 if (sqlca.sqlcode == 100)
2370 return(MR_NO_MATCH);
2374 EXEC SQL DECLARE csr105 CURSOR FOR
2375 SELECT list_id, ref_count FROM imembers
2376 WHERE member_id = :lid AND member_type = 'LIST';
2377 EXEC SQL OPEN csr105;
2379 EXEC SQL FETCH csr105 INTO :id, :ref;
2380 if(sqlca.sqlcode!=0) break;
2382 ancestors[acount++] = id;
2383 if (acount >= MAXLISTDEPTH) break;
2385 EXEC SQL CLOSE csr105;
2388 if (acount >= MAXLISTDEPTH)
2389 return(MR_INTERNAL);
2390 descendants[0] = mid;
2395 if (!strcmp(mtype, "LIST")) {
2396 EXEC SQL DECLARE csr106 CURSOR FOR
2397 SELECT member_id, member_type, ref_count FROM imembers
2398 WHERE list_id = :mid;
2399 EXEC SQL OPEN csr106;
2401 EXEC SQL FETCH csr106 INTO :id, :dtype, :ref;
2402 if(sqlca.sqlcode!=0) break;
2405 dtypes[dcount] = "LIST";
2408 dtypes[dcount] = "USER";
2411 dtypes[dcount] = "STRING";
2414 dtypes[dcount] = "KERBEROS";
2421 descendants[dcount++] = id;
2422 if (dcount >= MAXLISTDEPTH) break;
2424 EXEC SQL CLOSE csr106;
2428 return(MR_INTERNAL);
2430 for (a = 0; a < acount; a++) {
2432 for (d = 0; d < dcount; d++) {
2433 mid = descendants[d];
2435 if (mid == lid && !strcmp(mtype, "LIST")) {
2436 return(MR_LISTLOOP);
2438 EXEC SQL REPEATED SELECT ref_count INTO :cnt FROM imembers
2439 WHERE list_id = :lid AND member_id = :mid AND member_type = :mtype;
2440 ref = aref[a] * dref[d];
2442 iargv[0] = (char *)lid;
2444 iargv[2] = (char *)mid;
2445 incremental_before("members", 0, iargv);
2446 EXEC SQL DELETE FROM imembers
2447 WHERE list_id = :lid AND member_id = :mid
2448 AND member_type= :mtype;
2449 incremental_clear_after();
2450 } else if (a == 0 && d == 0) {
2451 EXEC SQL UPDATE imembers
2452 SET ref_count = refcount - :ref, direct = 0
2453 WHERE list_id = :lid AND member_id = :mid
2454 AND member_type = :mtype;
2456 EXEC SQL UPDATE imembers
2457 SET ref_count=refcount-:ref
2458 WHERE list_id = :lid AND member_id = :mid
2459 AND member_type = :mtype;
2463 lid = *(int *)argv[0];
2464 entity = cl->entity;
2465 who = cl->client_id;
2466 EXEC SQL UPDATE list SET modtime = 'now', modby = :who, modwith = :entity
2467 WHERE list_id = :lid;
2468 if (ingres_errno) return(mr_errcode);
2473 /* get_ace_use - given a type and a name, return a type and a name.
2474 * The ace_type is one of "LIST", "USER", "RLIST", or "RUSER" in argv[0],
2475 * and argv[1] will contain the ID of the entity in question. The R*
2476 * types mean to recursively look at every containing list, not just
2477 * when the object in question is a direct member. On return, the
2478 * usage type will be one of LIST, SERVICE, FILESYS, QUOTA, QUERY, or ZEPHYR.
2481 int get_ace_use(q, argv, cl, action, actarg)
2489 EXEC SQL BEGIN DECLARE SECTION;
2491 int aid, listid, id;
2492 EXEC SQL END DECLARE SECTION;
2493 struct save_queue *sq, *sq_create();
2496 aid = *(int *)argv[1];
2497 if (!strcmp(atype, "LIST") || !strcmp(atype, "USER") ||
2498 !strcmp(atype, "KERBEROS")) {
2499 return(get_ace_internal(atype, aid, action, actarg));
2503 if (!strcmp(atype, "RLIST")) {
2504 sq_save_data(sq, aid);
2505 /* get all the list_id's of containing lists */
2506 EXEC SQL DECLARE csr107 CURSOR FOR
2507 SELECT list_id FROM imembers
2508 WHERE member_type='LIST' AND member_id = :aid;
2509 EXEC SQL OPEN csr107;
2511 EXEC SQL FETCH csr107 INTO :listid;
2512 if(sqlca.sqlcode != 0) break;
2513 sq_save_unique_data(sq, listid);
2515 EXEC SQL CLOSE csr107;
2516 /* now process each one */
2517 while (sq_get_data(sq, &id)) {
2518 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2523 if (!strcmp(atype, "RUSER")) {
2524 EXEC SQL DECLARE csr108 CURSOR FOR
2525 SELECT list_id FROM imembers
2526 WHERE member_type='USER' AND member_id = :aid;
2527 EXEC SQL OPEN csr108;
2529 EXEC SQL FETCH csr108 INTO :listid;
2530 if(sqlca.sqlcode != 0) break;
2531 sq_save_data(sq, listid);
2533 EXEC SQL CLOSE csr108;
2534 /* now process each one */
2535 while (sq_get_data(sq, &id)) {
2536 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2539 if (get_ace_internal("USER", aid, action, actarg) == MR_SUCCESS)
2543 if (!strcmp(atype, "RKERBERO")) {
2544 EXEC SQL DECLARE csr109 CURSOR FOR
2545 SELECT list_id FROM imembers
2546 WHERE member_type='KERBEROS' AND member_id = :aid;
2547 EXEC SQL OPEN csr109;
2549 EXEC SQL FETCH csr109 INTO :listid;
2550 if(sqlca.sqlcode != 0) break;
2551 sq_save_data(sq, listid);
2553 EXEC SQL CLOSE csr109;
2554 /* now process each one */
2555 while (sq_get_data(sq, &id)) {
2556 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2559 if (get_ace_internal("KERBEROS", aid, action, actarg) == MR_SUCCESS)
2564 if (ingres_errno) return(mr_errcode);
2565 if (!found) return(MR_NO_MATCH);
2570 /* This looks up a single list or user for ace use. atype must be "USER"
2571 * or "LIST", and aid is the ID of the corresponding object. This is used
2572 * by get_ace_use above.
2575 get_ace_internal(atype, aid, action, actarg)
2576 EXEC SQL BEGIN DECLARE SECTION;
2579 EXEC SQL END DECLARE SECTION;
2585 EXEC SQL BEGIN DECLARE SECTION;
2587 EXEC SQL END DECLARE SECTION;
2590 if (!strcmp(atype, "LIST")) {
2591 rargv[0] = "FILESYS";
2592 EXEC SQL DECLARE csr110 CURSOR FOR
2593 SELECT label FROM filesys
2594 WHERE owners = :aid;
2595 EXEC SQL OPEN csr110;
2597 EXEC SQL FETCH csr110 INTO :name;
2598 if(sqlca.sqlcode != 0) break;
2599 (*action)(2, rargv, actarg);
2602 EXEC SQL CLOSE csr110;
2605 EXEC SQL DECLARE csr111 CURSOR FOR
2606 SELECT capability FROM capacls
2607 WHERE list_id = :aid ;
2608 EXEC SQL OPEN csr111;
2610 EXEC SQL FETCH csr111 INTO :name ;
2611 if(sqlca.sqlcode != 0) break;
2612 (*action)(2, rargv, actarg);
2615 EXEC SQL CLOSE csr111;
2616 } else if (!strcmp(atype, "USER")) {
2617 rargv[0] = "FILESYS";
2618 EXEC SQL DECLARE csr112 CURSOR FOR
2619 SELECT label FROM filesys
2621 EXEC SQL OPEN csr112;
2623 EXEC SQL FETCH csr112 INTO :name ;
2624 if(sqlca.sqlcode != 0) break;
2625 (*action)(2, rargv, actarg);
2628 EXEC SQL CLOSE csr112;
2632 EXEC SQL DECLARE csr113 CURSOR FOR
2633 SELECT name FROM list
2634 WHERE acl_type = :atype AND acl_id = :aid;
2635 EXEC SQL OPEN csr113;
2637 EXEC SQL FETCH csr113 INTO :name;
2638 if(sqlca.sqlcode != 0) break;
2639 (*action)(2, rargv, actarg);
2642 EXEC SQL CLOSE csr113;
2644 rargv[0] = "SERVICE";
2645 EXEC SQL DECLARE csr114 CURSOR FOR
2646 SELECT name FROM servers
2647 WHERE acl_type = :atype AND acl_id = :aid;
2648 EXEC SQL OPEN csr114;
2650 EXEC SQL FETCH csr114 INTO :name;
2651 if(sqlca.sqlcode != 0) break;
2652 (*action)(2, rargv, actarg);
2655 EXEC SQL CLOSE csr114;
2657 rargv[0] = "HOSTACCESS";
2658 EXEC SQL DECLARE csr115 CURSOR FOR
2659 SELECT name FROM machine, hostaccess
2660 WHERE mach_id = hostaccess.mach_id AND hostaccess.acl_type = :atype
2661 AND hostaccess.acl_id = :aid;
2662 EXEC SQL OPEN csr115;
2664 EXEC SQL FETCH csr115 INTO :name;
2665 if(sqlca.sqlcode != 0) break;
2666 (*action)(2, rargv, actarg);
2669 EXEC SQL CLOSE csr115;
2671 rargv[0] = "ZEPHYR";
2672 EXEC SQL DECLARE csr116 CURSOR FOR
2673 SELECT class FROM zephyr
2674 WHERE zephyr.xmt_type = :atype AND zephyr.xmt_id = :aid
2675 OR zephyr.sub_type = :atype AND zephyr.sub_id = :aid
2676 OR zephyr.iws_type = :atype AND zephyr.iws_id = :aid
2677 OR zephyr.iui_type = :atype AND zephyr.iui_id = :aid;
2678 EXEC SQL OPEN csr116;
2680 EXEC SQL FETCH csr116 INTO :name;
2681 if(sqlca.sqlcode != 0) break;
2682 (*action)(2, rargv, actarg);
2685 EXEC SQL CLOSE csr116;
2687 if (!found) return(MR_NO_MATCH);
2692 /* get_lists_of_member - given a type and a name, return the name and flags
2693 * of all of the lists of the given member. The member_type is one of
2694 * "LIST", "USER", "STRING", "RLIST", "RUSER", or "RSTRING" in argv[0],
2695 * and argv[1] will contain the ID of the entity in question. The R*
2696 * types mean to recursively look at every containing list, not just
2697 * when the object in question is a direct member.
2700 int get_lists_of_member(q, argv, cl, action, actarg)
2707 int found = 0, direct = 1;
2709 EXEC SQL BEGIN DECLARE SECTION;
2711 int aid, listid, id;
2712 char name[33], active[5], public[5], hidden[5], maillist[5], grouplist[5];
2713 EXEC SQL END DECLARE SECTION;
2716 aid = *(int *)argv[1];
2717 if (!strcmp(atype, "RLIST")) {
2721 if (!strcmp(atype, "RUSER")) {
2725 if (!strcmp(atype, "RSTRING")) {
2729 if (!strcmp(atype, "RKERBEROS")) {
2738 rargv[4] = maillist;
2739 rargv[5] = grouplist;
2741 EXEC SQL DECLARE csr117a CURSOR FOR
2742 SELECT name, CHAR(active), CHAR(publicflg), CHAR(hidden),
2743 CHAR(maillist), CHAR(grouplist)
2744 FROM list l, imembers m
2745 WHERE l.list_id = m.list_id AND m.direct = 1
2746 AND m.member_type = :atype AND m.member_id = :aid;
2747 EXEC SQL OPEN csr117a;
2749 EXEC SQL FETCH csr117a
2750 INTO :name, :active, :public, :hidden, :maillist, :grouplist;
2751 if(sqlca.sqlcode != 0) break;
2752 (*action)(6, rargv, actarg);
2755 EXEC SQL CLOSE csr117a;
2757 EXEC SQL DECLARE csr117b CURSOR FOR
2758 SELECT name, CHAR(active), CHAR(publicflg), CHAR(hidden),
2759 CHAR(maillist), CHAR(grouplist)
2760 FROM list l, imembers m
2761 WHERE l.list_id = m.list_id
2762 AND m.member_type = :atype AND m.member_id = :aid;
2763 EXEC SQL OPEN csr117b;
2765 EXEC SQL FETCH csr117b
2766 INTO :name, :active, :public, :hidden, :maillist, :grouplist;
2767 if(sqlca.sqlcode != 0) break;
2768 (*action)(6, rargv, actarg);
2771 EXEC SQL CLOSE csr117b;
2774 if (ingres_errno) return(mr_errcode);
2775 if (!found) return(MR_NO_MATCH);
2780 /* qualified_get_lists: passed "TRUE", "FALSE", or "DONTCARE" for each of
2781 * the five flags associated with each list. It will return the name of
2782 * each list that meets the quailifications. It does this by building a
2783 * where clause based on the arguments, then doing a retrieve.
2786 static char *lflags[5] = { "active", "publicflg", "hidden", "maillist", "group" };
2788 int qualified_get_lists(q, argv, cl, action, actarg)
2795 return(qualified_get(q, argv, action, actarg, "l.list_id != 0",
2796 "l", "name", lflags));
2800 /* get_members_of_list - this gets only direct members */
2802 get_members_of_list(q, argv, cl, action, actarg)
2809 return(gmol_internal(q, argv, cl, action, actarg, 1));
2812 /* get_end_members_of_list - this gets direct or indirect members */
2814 get_end_members_of_list(q, argv, cl, action, actarg)
2821 return(gmol_internal(q, argv, cl, action, actarg, 0));
2824 /** gmol_internal - optimized query for retrieval of list members
2825 ** used by both get_members_of_list and get_end_members_of_list
2828 ** argv[0] - list_id
2831 ** - retrieve USER members, then LIST members, then STRING members
2834 gmol_internal(q, argv, cl, action, actarg, flag)
2842 EXEC SQL BEGIN DECLARE SECTION;
2843 int list_id, member_id, direct;
2844 char member_name[129], member_type[9];
2845 EXEC SQL END DECLARE SECTION;
2848 struct save_queue *sq;
2850 /* true/false flag indicates whether to display only direct members. */
2856 list_id = *(int *)argv[0];
2860 EXEC SQL DECLARE csr118 CURSOR FOR
2861 SELECT member_type, member_id FROM imembers
2862 WHERE list_id = :list_id AND direct > :direct;
2863 EXEC SQL OPEN csr118;
2865 EXEC SQL FETCH csr118 INTO :member_type, :member_id;
2866 if (sqlca.sqlcode != 0) break;
2869 sq_save_data(sq, ((int)member_type[0] << 24) | (member_id & 0xffffff));
2871 EXEC SQL CLOSE csr118;
2873 if (members <= 49) {
2874 targv[1] = malloc(0);
2875 while (sq_remove_data(sq, &member_id)) {
2876 switch (member_id >> 24) {
2879 id_to_name(member_id & 0xffffff, "USER", &targv[1]);
2880 (*action)(2, targv, actarg);
2884 id_to_name(member_id & 0xffffff, "LIST", &targv[1]);
2885 (*action)(2, targv, actarg);
2888 targv[0] = "STRING";
2889 id_to_name(member_id & 0xffffff, "STRING", &targv[1]);
2890 (*action)(2, targv, actarg);
2893 targv[0] = "KERBEROS";
2894 id_to_name(member_id & 0xffffff, "STRING", &targv[1]);
2895 (*action)(2, targv, actarg);
2899 return(MR_INTERNAL);
2908 targv[1] = member_name;
2910 EXEC SQL DECLARE csr119 CURSOR FOR
2911 SELECT users.login FROM users, imembers
2912 WHERE imembers.list_id = :list_id AND imembers.member_type = 'USER'
2913 AND imembers.member_id = users.users_id AND imembers.direct > :direct
2915 EXEC SQL OPEN csr119;
2917 EXEC SQL FETCH csr119 INTO :member_name;
2918 if(sqlca.sqlcode != 0) break;
2919 (*action)(2, targv, actarg);
2921 EXEC SQL CLOSE csr119;
2922 if (ingres_errno) return(mr_errcode);
2925 EXEC SQL DECLARE csr120 CURSOR FOR
2926 SELECT list.name FROM list, imembers
2927 WHERE imembers.list_id = :list_id AND imembers.member_type='LIST'
2928 AND imembers.member_id = list.list_id AND imembers.direct > :direct
2930 EXEC SQL OPEN csr120;
2932 EXEC SQL FETCH csr120 INTO :member_name;
2933 if(sqlca.sqlcode != 0) break;
2934 (*action)(2, targv, actarg);
2936 EXEC SQL CLOSE csr120;
2937 if (ingres_errno) return(mr_errcode);
2939 targv[0] = "STRING";
2940 EXEC SQL DECLARE csr121 CURSOR FOR
2941 SELECT strings.string FROM strings, imembers
2942 WHERE imembers.list_id = :list_id AND imembers.member_type='STRING'
2943 AND imembers.member_id = strings.string_id
2944 AND imembers.direct > :direct
2946 EXEC SQL OPEN csr121;
2948 EXEC SQL FETCH csr121 INTO :member_name;
2949 if(sqlca.sqlcode != 0) break;
2950 (*action)(2, targv, actarg);
2952 EXEC SQL CLOSE csr121;
2953 if (ingres_errno) return(mr_errcode);
2955 targv[0] = "KERBEROS";
2956 EXEC SQL DECLARE csr122 CURSOR FOR
2957 SELECT strings.string FROM strings, imembers
2958 WHERE imembers.list_id = :list_id AND imembers.member_type='KERBEROS'
2959 AND imembers.member_id = strings.string_id
2960 AND imembers.direct > :direct
2962 EXEC SQL OPEN csr122;
2964 EXEC SQL FETCH csr122 INTO :member_name;
2965 if(sqlca.sqlcode != 0) break;
2966 (*action)(2, targv, actarg);
2968 EXEC SQL CLOSE csr122;
2969 if (ingres_errno) return(mr_errcode);
2975 /* count_members_of_list: this is a simple query, but it cannot be done
2976 * through the dispatch table.
2979 int count_members_of_list(q, argv, cl, action, actarg)
2986 EXEC SQL BEGIN DECLARE SECTION;
2988 EXEC SQL END DECLARE SECTION;
2989 char *rargv[1], countbuf[5];
2991 list = *(int *)argv[0];
2992 rargv[0] = countbuf;
2993 EXEC SQL REPEATED SELECT count (*) INTO :ct FROM imembers
2994 WHERE list_id = :list AND direct=1;
2995 if (ingres_errno) return(mr_errcode);
2996 sprintf(countbuf, "%d", ct);
2997 (*action)(1, rargv, actarg);
3002 /* qualified_get_server: passed "TRUE", "FALSE", or "DONTCARE" for each of
3003 * the three flags associated with each service. It will return the name of
3004 * each service that meets the quailifications. It does this by building a
3005 * where clause based on the arguments, then doing a retrieve.
3008 static char *sflags[3] = { "enable", "inprogress", "harderror" };
3010 int qualified_get_server(q, argv, cl, action, actarg)
3017 return(qualified_get(q, argv, action, actarg, "s.name != ''",
3018 "s", "name", sflags));
3022 /* generic qualified get routine, used by qualified_get_lists,
3023 * qualified_get_server, and qualified_get_serverhost.
3025 * start - a simple where clause, must not be empty
3026 * range - the name of the range variable
3027 * field - the field to return
3028 * flags - an array of strings, names of the flag variables
3031 int qualified_get(q, argv, action, actarg, start, range, field, flags)
3041 char name[33], qual[256];
3043 char *rargv[1], buf[32];
3045 strcpy(qual, start);
3046 for (i = 0; i < q->argc; i++) {
3047 if (!strcmp(argv[i], "TRUE")) {
3048 sprintf(buf, " and %s.%s != 0", range, flags[i]);
3049 (void) strcat(qual, buf);
3050 } else if (!strcmp(argv[i], "FALSE")) {
3051 sprintf(buf, " and %s.%s = 0", range, flags[i]);
3052 (void) strcat(qual, buf);
3056 rargv[0] = SQLDA->sqlvar[0].sqldata;
3057 sprintf(stmt_buf,"SELECT %s.%s FROM %s %s WHERE %s",q->rtable,field,q->rtable,q->rvar,qual);
3058 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3060 return(MR_INTERNAL);
3061 EXEC SQL DECLARE csr123 CURSOR FOR stmt;
3062 EXEC SQL OPEN csr123;
3064 EXEC SQL FETCH csr123 USING DESCRIPTOR :SQLDA;
3065 if(sqlca.sqlcode != 0) break;
3067 (*action)(1, rargv, actarg);
3069 EXEC SQL CLOSE csr123;
3070 if (ingres_errno) return(mr_errcode);
3072 return(MR_NO_MATCH);
3077 /* qualified_get_serverhost: passed "TRUE", "FALSE", or "DONTCARE" for each of
3078 * the five flags associated with each serverhost. It will return the name of
3079 * each service and host that meets the quailifications. It does this by
3080 * building a where clause based on the arguments, then doing a retrieve.
3083 static char *shflags[6] = { "service", "enable", "override", "success",
3084 "inprogress", "hosterror" };
3086 int qualified_get_serverhost(q, argv, cl, action, actarg)
3093 EXEC SQL BEGIN DECLARE SECTION;
3094 char sname[33], mname[33], qual[256];
3095 EXEC SQL END DECLARE SECTION;
3096 char *rargv[2], buf[32];
3099 /** the uppercase() function is INGRES-specific */
3100 sprintf(qual, "machine.mach_id = serverhosts.mach_id AND \
3101 serverhosts.service = uppercase('%s')",
3103 for (i = 1; i < q->argc; i++) {
3104 if (!strcmp(argv[i], "TRUE")) {
3105 sprintf(buf, " AND serverhosts.%s != 0", shflags[i]);
3107 } else if (!strcmp(argv[i], "FALSE")) {
3108 sprintf(buf, " AND serverhosts.%s = 0", shflags[i]);
3115 EXEC SQL DECLARE csr124 CURSOR FOR
3116 SELECT serverhosts.service, machine.name FROM serverhosts, machine
3118 EXEC SQL OPEN csr124;
3120 EXEC SQL FETCH csr124 INTO :sname, :mname;
3121 if(sqlca.sqlcode != 0) break;
3123 (*action)(2, rargv, actarg);
3125 EXEC SQL CLOSE csr124;
3127 if (ingres_errno) return(mr_errcode);
3129 return(MR_NO_MATCH);
3134 /* register_user - change user's login name and allocate a pobox, group,
3135 * filesystem, and quota for them. The user's status must start out as 0,
3136 * and is left as 2. Arguments are: user's UID, new login name, and user's
3137 * type for filesystem allocation (MR_FS_STUDENT, MR_FS_FACULTY,
3138 * MR_FS_STAFF, MR_FS_MISC).
3141 register_user(q, argv, cl)
3146 EXEC SQL BEGIN DECLARE SECTION;
3147 char *login, dir[65], *entity, directory[129], machname[33];
3148 int who, rowcount, mid, uid, users_id, flag, utype, nid, list_id, quota;
3149 int size, alloc, pid, ostatus, nstatus, gidval, fsidval, npidval;
3150 static int m_id = 0, def_quota = 0;
3151 EXEC SQL END DECLARE SECTION;
3152 char buffer[256], *aargv[3];
3154 entity = cl->entity;
3155 who = cl->client_id;
3157 uid = atoi(argv[0]);
3159 utype = atoi(argv[2]);
3162 EXEC SQL REPEATED SELECT users_id, status INTO :users_id, :ostatus
3164 WHERE uid = :uid AND (status=0 OR status=5 OR status=6);
3166 if (sqlca.sqlerrd[2] == 0)
3167 return(MR_NO_MATCH);
3168 if (sqlca.sqlerrd[2] > 1)
3169 return(MR_NOT_UNIQUE);
3171 /* check new login name */
3172 EXEC SQL REPEATED SELECT login INTO :cdummy FROM users
3173 WHERE login = LEFT(:login,SIZE(login)) AND users_id != :users_id;
3174 if (ingres_errno) return(mr_errcode);
3175 if (sqlca.sqlerrd[2] > 0) return(MR_IN_USE);
3176 EXEC SQL REPEATED SELECT name INTO :cdummy FROM list
3177 WHERE name = LEFT(:login,SIZE(name));
3178 if (ingres_errno) return(mr_errcode);
3179 if (sqlca.sqlerrd[2] > 0) return(MR_IN_USE);
3180 EXEC SQL REPEATED SELECT label INTO :cdummy FROM filesys
3181 WHERE label = LEFT(:login,SIZE(label));
3182 if (ingres_errno) return(mr_errcode);
3183 if (sqlca.sqlerrd[2] > 0) return(MR_IN_USE);
3184 com_err(whoami, 0, "login name OK");
3186 /* choose place for pobox, put in mid */
3187 EXEC SQL DECLARE csr130 CURSOR FOR
3188 SELECT sh.mach_id, m.name FROM serverhosts sh, machine m
3189 WHERE sh.service='POP' AND sh.mach_id=m.mach_id
3190 AND sh.value2 - sh.value1 =
3191 (SELECT MAX(value2 - value1) FROM serverhosts
3192 WHERE service = 'POP');
3193 EXEC SQL OPEN csr130;
3194 EXEC SQL FETCH csr130 INTO :mid, :machname;
3195 if (sqlca.sqlerrd[2] == 0) {
3196 EXEC SQL CLOSE csr130;
3197 if (ingres_errno) return(mr_errcode);
3198 return(MR_NO_POBOX);
3200 EXEC SQL CLOSE csr130;
3201 if (ingres_errno) return(mr_errcode);
3204 /* change login name, set pobox */
3205 sprintf(buffer, "users.users_id = %d", users_id);
3206 incremental_before("users", buffer, 0);
3208 if (ostatus == 5 || ostatus == 6)
3210 EXEC SQL REPEATED UPDATE users SET login = :login, status = :nstatus,
3211 modtime='now', modby = :who, modwith = :entity, potype='POP',
3212 pop_id = :mid, pmodtime='now', pmodby = :who, pmodwith = :entity
3213 WHERE users_id = :users_id;
3215 if (ingres_errno) return(mr_errcode);
3216 if (sqlca.sqlerrd[2] != 1)
3217 return(MR_INTERNAL);
3218 set_pop_usage(mid, 1);
3219 com_err(whoami, 0, "set login name to %s and pobox to %s", login,
3221 incremental_after("users", buffer, 0);
3223 /* create group list */
3224 if (set_next_object_id("gid", "list", 1))
3226 if (set_next_object_id("list_id", "list", 0))
3228 EXEC SQL REPEATED SELECT value INTO :list_id FROM numvalues
3229 WHERE name='list_id';
3230 if (ingres_errno) return(mr_errcode);
3231 if (sqlca.sqlerrd[2] != 1)
3232 return(MR_INTERNAL);
3233 incremental_clear_before();
3234 EXEC SQL SELECT value INTO :gidval FROM numvalues WHERE name = 'gid';
3235 EXEC SQL REPEATED INSERT INTO list
3236 (name, list_id, active, publicflg, hidden, maillist, grouplist,
3237 gid, description, acl_type, acl_id,
3238 modtime, modby, modwith)
3239 VALUES (:login, :list_id, 1, 0, 0, 0, 1,
3240 :gidval, 'User Group', 'USER', :users_id,
3241 'now', :who, :entity);
3242 if (ingres_errno) return(mr_errcode);
3243 if (sqlca.sqlerrd[2] != 1)
3244 return(MR_INTERNAL);
3245 sprintf(buffer, "list_id = %d", list_id);
3246 incremental_after("list", buffer, 0);
3247 aargv[0] = (char *) list_id;
3249 aargv[2] = (char *) users_id;
3250 incremental_clear_before();
3251 EXEC SQL REPEATED INSERT INTO imembers
3252 (list_id, member_type, member_id, ref_count, direct)
3253 VALUES (:list_id, 'USER', :users_id, 1, 1);
3254 if (ingres_errno) return(mr_errcode);
3255 if (sqlca.sqlerrd[2] != 1)
3256 return(MR_INTERNAL);
3257 incremental_after("members", 0, aargv);
3260 /* Cell Name (I know, it shouldn't be hard coded...) */
3261 strcpy(machname, "ATHENA.MIT.EDU");
3262 EXEC SQL SELECT mach_id INTO :m_id FROM machine
3263 WHERE name = :machname;
3266 /* create filesystem */
3267 if (set_next_object_id("filsys_id", "filesys", 0))
3269 incremental_clear_before();
3270 if (islower(login[0]) && islower(login[1])) {
3271 sprintf(directory, "/afs/athena.mit.edu/user/%c/%c/%s",
3272 login[0], login[1], login);
3274 sprintf(directory, "/afs/athena.mit.edu/user/other/%s", login);
3277 EXEC SQL SELECT value INTO :fsidval FROM numvalues
3278 WHERE numvalues.name='filsys_id';
3279 EXEC SQL REPEATED INSERT INTO filesys
3280 (filsys_id, phys_id, label, type, mach_id, name,
3281 mount, access, comments, owner, owners, createflg,
3282 lockertype, modtime, modby, modwith)
3284 (:fsidval, 0, :login, 'AFS', :m_id, :directory,
3285 '/mit/'+:login, 'w', 'User Locker', :users_id, :list_id, 1,
3286 'HOMEDIR', 'now', :who, :entity);
3288 if (ingres_errno) return(mr_errcode);
3289 if (sqlca.sqlerrd[2] != 1)
3290 return(MR_INTERNAL);
3291 sprintf(buffer,"fs.filsys_id = %d",fsidval);
3292 incremental_after("filesys", buffer, 0);
3295 if (def_quota == 0) {
3296 EXEC SQL REPEATED SELECT value INTO :quota FROM numvalues
3297 WHERE name='def_quota';
3298 if (ingres_errno) return(mr_errcode);
3299 if (sqlca.sqlerrd[2] != 1)
3300 return(MR_NO_QUOTA);
3302 incremental_clear_before();
3303 EXEC SQL REPEATED INSERT INTO quota
3304 (entity_id, filsys_id, type, quota, phys_id, modtime, modby, modwith)
3306 (0, :fsidval, 'ANY', :def_quota, 0, 'now', :who, :entity);
3307 if (ingres_errno) return(mr_errcode);
3308 if (sqlca.sqlerrd[2] != 1)
3309 return(MR_INTERNAL);
3313 sprintf(buffer, "q.entity_id = 0 and q.filsys_id = %d and q.type = 'ANY'", fsidval);
3314 incremental_after("quota", buffer, aargv);
3315 com_err(whoami, 0, "quota of %d assigned", def_quota);
3316 if (ingres_errno) return(mr_errcode);
3318 cache_entry(login, "USER", users_id);
3320 EXEC SQL REPEATED UPDATE tblstats SET updates=updates+1, modtime='now'
3321 WHERE table_name='users';
3322 EXEC SQL REPEATED UPDATE tblstats SET appends=appends+1, modtime='now'
3323 WHERE table_name='list' OR table_name='filesys' OR table_name='quota';
3324 if (ingres_errno) return(mr_errcode);
3330 /** set_pop_usage - incr/decr usage count for pop server in serverhosts talbe
3334 ** delta (will be +/- 1)
3337 ** - incr/decr value field in serverhosts table for pop/mach_id
3341 static int set_pop_usage(id, cnt)
3342 EXEC SQL BEGIN DECLARE SECTION;
3345 EXEC SQL END DECLARE SECTION;
3347 EXEC SQL REPEATED UPDATE serverhosts SET value1 = value1 + :cnt
3348 WHERE serverhosts.service = 'POP' AND serverhosts.mach_id = :id;
3350 if (ingres_errno) return(mr_errcode);
3356 /* Validation Routines */
3358 validate_row(q, argv, v)
3359 register struct query *q;
3361 register struct validate *v;
3363 EXEC SQL BEGIN DECLARE SECTION;
3367 EXEC SQL END DECLARE SECTION;
3369 /* build where clause */
3370 build_qual(v->qual, v->argc, argv, qual);
3372 if (log_flags & LOG_VALID)
3373 /* tell the logfile what we're doing */
3374 com_err(whoami, 0, "validating row: %s", qual);
3376 /* look for the record */
3377 sprintf(stmt_buf,"SELECT COUNT (*) FROM %s WHERE %s",q->rtable,qual);
3378 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3380 return(MR_INTERNAL);
3381 EXEC SQL DECLARE csr126 CURSOR FOR stmt;
3382 EXEC SQL OPEN csr126;
3383 EXEC SQL FETCH csr126 USING DESCRIPTOR :SQLDA;
3384 EXEC SQL CLOSE csr126;
3385 rowcount = *(int *)SQLDA->sqlvar[0].sqldata;
3387 if (ingres_errno) return(mr_errcode);
3388 if (rowcount == 0) return(MR_NO_MATCH);
3389 if (rowcount > 1) return(MR_NOT_UNIQUE);
3393 validate_fields(q, argv, vo, n)
3395 register char *argv[];
3396 register struct valobj *vo;
3399 register int status;
3404 if (log_flags & LOG_VALID)
3405 com_err(whoami, 0, "validating %s in %s: %s",
3406 vo->namefield, vo->table, argv[vo->index]);
3407 status = validate_name(argv, vo);
3411 if (log_flags & LOG_VALID)
3412 com_err(whoami, 0, "validating %s in %s: %s",
3413 vo->idfield, vo->table, argv[vo->index]);
3414 status = validate_id(q, argv, vo);
3418 if (log_flags & LOG_VALID)
3419 com_err(whoami, 0, "validating date: %s", argv[vo->index]);
3420 status = validate_date(argv, vo);
3424 if (log_flags & LOG_VALID)
3425 com_err(whoami, 0, "validating %s type: %s",
3426 vo->table, argv[vo->index]);
3427 status = validate_type(argv, vo);
3431 if (log_flags & LOG_VALID)
3432 com_err(whoami, 0, "validating typed data (%s): %s",
3433 argv[vo->index - 1], argv[vo->index]);
3434 status = validate_typedata(q, argv, vo);
3438 if (log_flags & LOG_VALID)
3439 com_err(whoami, 0, "validating rename %s in %s",
3440 argv[vo->index], vo->table);
3441 status = validate_rename(argv, vo);
3445 if (log_flags & LOG_VALID)
3446 com_err(whoami, 0, "validating chars: %s", argv[vo->index]);
3447 status = validate_chars(argv[vo->index]);
3455 status = lock_table(vo);
3459 status = convert_wildcards(argv[vo->index]);
3463 status = convert_wildcards_uppercase(argv[vo->index]);
3468 if (status != MR_EXISTS) return(status);
3472 if (ingres_errno) return(mr_errcode);
3477 /* validate_chars: verify that there are no illegal characters in
3478 * the string. Legal characters are printing chars other than
3479 * ", *, ?, \, [ and ].
3481 static int illegalchars[] = {
3482 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
3483 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
3484 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
3485 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
3486 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* : - O */
3487 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* P - _ */
3488 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
3489 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
3490 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3491 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3492 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3493 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3494 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3495 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3496 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3497 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3504 if (illegalchars[*s++])
3505 return(MR_BAD_CHAR);
3510 validate_id(q, argv, vo)
3513 register struct valobj *vo;
3515 EXEC SQL BEGIN DECLARE SECTION;
3516 char *name, *tbl, *namefield, *idfield;
3518 EXEC SQL END DECLARE SECTION;
3522 name = argv[vo->index];
3524 namefield = vo->namefield;
3525 idfield = vo->idfield;
3527 if ((!strcmp(tbl, "users") && !strcmp(namefield, "login")) ||
3528 !strcmp(tbl, "machine") ||
3529 !strcmp(tbl, "filesys") ||
3530 !strcmp(tbl, "list") ||
3531 !strcmp(tbl, "cluster") ||
3532 !strcmp(tbl, "strings")) {
3533 if (!strcmp(tbl, "machine"))
3534 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3535 status = name_to_id(name, tbl, &id);
3537 *(int *)argv[vo->index] = id;
3539 } else if (status == MR_NO_MATCH && !strcmp(tbl, "strings") &&
3540 (q->type == APPEND || q->type == UPDATE)) {
3541 EXEC SQL SELECT value INTO :id FROM numvalues
3542 WHERE name = 'strings_id';
3544 EXEC SQL UPDATE numvalues SET value = :id WHERE name = 'string_id';
3545 EXEC SQL INSERT INTO strings (string_id, string) VALUES (:id, :name);
3546 cache_entry(name, "STRING", id);
3547 *(int *)argv[vo->index] = id;
3549 } else if (status == MR_NO_MATCH || status == MR_NOT_UNIQUE)
3555 if (!strcmp(namefield, "uid")) {
3556 sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s = %s",idfield,tbl,namefield,name);
3558 sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s = '%s'",idfield,tbl,namefield,name);
3560 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3562 return(MR_INTERNAL);
3563 EXEC SQL DECLARE csr127 CURSOR FOR stmt;
3564 EXEC SQL OPEN csr127;
3566 EXEC SQL FETCH csr127 USING DESCRIPTOR :SQLDA;
3567 if(sqlca.sqlcode == 0) {
3569 EXEC SQL FETCH csr127 USING DESCRIPTOR :SQLDA;
3570 if(sqlca.sqlcode == 0) rowcount++;
3572 EXEC SQL CLOSE csr127;
3576 if (rowcount != 1) return(vo->error);
3577 bcopy(SQLDA->sqlvar[0].sqldata,argv[vo->index],sizeof(int));
3581 validate_name(argv, vo)
3583 register struct valobj *vo;
3585 EXEC SQL BEGIN DECLARE SECTION;
3586 char *name, *tbl, *namefield;
3588 EXEC SQL END DECLARE SECTION;
3591 name = argv[vo->index];
3593 namefield = vo->namefield;
3594 if (!strcmp(tbl, "servers") && !strcmp(namefield, "name")) {
3595 for (c = name; *c; c++)
3599 sprintf(stmt_buf,"SELECT DISTINCT COUNT(*) FROM %s WHERE %s.%s = '%s'",
3600 tbl,tbl,namefield,name);
3601 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3603 return(MR_INTERNAL);
3604 EXEC SQL DECLARE csr128 CURSOR FOR stmt;
3605 EXEC SQL OPEN csr128;
3606 EXEC SQL FETCH csr128 USING DESCRIPTOR :SQLDA;
3607 rowcount = *(int *)SQLDA->sqlvar[0].sqldata;
3608 EXEC SQL CLOSE csr128;
3610 if (ingres_errno) return(mr_errcode);
3611 return ((rowcount == 1) ? MR_EXISTS : vo->error);
3614 validate_date(argv, vo)
3618 EXEC SQL BEGIN DECLARE SECTION;
3622 EXEC SQL END DECLARE SECTION;
3624 idate = argv[vo->index];
3625 EXEC SQL SELECT interval('years',date(:idate)-date('today')) INTO :dd;
3627 if (sqlca.sqlcode != 0 || dd > 5.0) return(MR_DATE);
3632 validate_rename(argv, vo)
3636 EXEC SQL BEGIN DECLARE SECTION;
3637 char *name, *tbl, *namefield, *idfield;
3639 EXEC SQL END DECLARE SECTION;
3643 c = name = argv[vo->index];
3645 if (illegalchars[*c++])
3646 return(MR_BAD_CHAR);
3648 /* minor kludge to upcasify machine names */
3649 if (!strcmp(tbl, "machine"))
3650 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3651 namefield = vo->namefield;
3652 idfield = vo->idfield;
3655 if (!strcmp(argv[vo->index], argv[vo->index - 1]))
3657 sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s = LEFT('%s',SIZE(%s))",
3658 namefield,tbl,namefield,name,namefield);
3659 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3661 return(MR_INTERNAL);
3662 EXEC SQL DECLARE csr129 CURSOR FOR stmt;
3663 EXEC SQL OPEN csr129;
3664 EXEC SQL FETCH csr129 USING DESCRIPTOR :SQLDA;
3665 if(sqlca.sqlcode == 0) id=1; else id=0;
3666 EXEC SQL CLOSE csr129;
3668 if (ingres_errno) return(mr_errcode);
3674 status = name_to_id(name, tbl, &id);
3675 if (status == MR_NO_MATCH || id == *(int *)argv[vo->index - 1])
3682 validate_type(argv, vo)
3684 register struct valobj *vo;
3686 EXEC SQL BEGIN DECLARE SECTION;
3689 EXEC SQL END DECLARE SECTION;
3692 typename = vo->table;
3693 c = val = argv[vo->index];
3695 if (illegalchars[*c++])
3696 return(MR_BAD_CHAR);
3699 /* uppercase type fields */
3700 for (c = val; *c; c++) if (islower(*c)) *c = toupper(*c);
3702 EXEC SQL SELECT trans INTO :cdummy FROM alias
3703 WHERE name = :typename AND type='TYPE' AND trans = :val;
3704 if (ingres_errno) return(mr_errcode);
3705 return (sqlca.sqlerrd[2] ? MR_EXISTS : vo->error);
3708 /* validate member or type-specific data field */
3710 validate_typedata(q, argv, vo)
3711 register struct query *q;
3712 register char *argv[];
3713 register struct valobj *vo;
3715 EXEC SQL BEGIN DECLARE SECTION;
3718 char data_type[129];
3720 EXEC SQL END DECLARE SECTION;
3725 /* get named object */
3726 name = argv[vo->index];
3728 /* get field type string (known to be at index-1) */
3729 field_type = argv[vo->index-1];
3731 /* get corresponding data type associated with field type name */
3732 EXEC SQL SELECT trans INTO :data_type FROM alias
3733 WHERE name = :field_type AND type='TYPEDATA';
3734 if (ingres_errno) return(mr_errcode);
3735 if (sqlca.sqlerrd[2] != 1) return(MR_TYPE);
3737 /* now retrieve the record id corresponding to the named object */
3738 if (index(data_type, ' '))
3739 *index(data_type, ' ') = 0;
3740 if (!strcmp(data_type, "user")) {
3742 status = name_to_id(name, data_type, &id);
3743 if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
3745 if (status) return(status);
3746 } else if (!strcmp(data_type, "list")) {
3748 status = name_to_id(name, data_type, &id);
3749 if (status && status == MR_NOT_UNIQUE)
3751 if (status == MR_NO_MATCH) {
3752 /* if idfield is non-zero, then if argv[0] matches the string
3753 * that we're trying to resolve, we should get the value of
3754 * numvalues.[idfield] for the id.
3756 if (vo->idfield && !strcmp(argv[0], argv[vo->index])) {
3757 set_next_object_id(q->validate->object_id, q->rtable, 0);
3759 EXEC SQL REPEATED SELECT value INTO :id FROM numvalues
3761 if (sqlca.sqlerrd[2] != 1) return(MR_LIST);
3764 } else if (status) return(status);
3765 } else if (!strcmp(data_type, "machine")) {
3767 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3768 status = name_to_id(name, data_type, &id);
3769 if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
3771 if (status) return(status);
3772 } else if (!strcmp(data_type, "string")) {
3774 status = name_to_id(name, data_type, &id);
3775 if (status && status == MR_NOT_UNIQUE)
3777 if (status == MR_NO_MATCH) {
3778 if (q->type != APPEND && q->type != UPDATE) return(MR_STRING);
3779 EXEC SQL SELECT value INTO :id FROM numvalues WHERE name = 'strings_id';
3781 EXEC SQL UPDATE numvalues SET value = :id WHERE name = 'strings_id';
3782 EXEC SQL INSERT INTO strings (string_id, string) VALUES (:id, :name);
3783 cache_entry(name, "STRING", id);
3784 } else if (status) return(status);
3785 } else if (!strcmp(data_type, "none")) {
3791 /* now set value in argv */
3792 *(int *)argv[vo->index] = id;
3798 /* Lock the table named by the validation object */
3803 sprintf(stmt_buf,"UPDATE %s SET modtime='now' WHERE %s.%s = 0",
3804 vo->table,vo->table,vo->idfield);
3805 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
3806 if (ingres_errno) return(mr_errcode);
3807 if (sqlca.sqlerrd[2] != 1)
3814 /* Check the database at startup time. For now this just resets the
3815 * inprogress flags that the DCM uses.
3818 sanity_check_database()
3823 /* Dynamic SQL support routines */
3824 MR_SQLDA_T *mr_alloc_SQLDA()
3827 short *null_indicators;
3830 if((it=(MR_SQLDA_T *)malloc(sizeof(MR_SQLDA_T)))==NULL) {
3831 com_err(whoami, MR_NO_MEM, "setting up SQLDA");
3835 if((null_indicators=(short *)calloc(QMAXARGS,sizeof(short)))==NULL) {
3836 com_err(whoami, MR_NO_MEM, "setting up SQLDA null indicators");
3840 for(j=0; j<QMAXARGS; j++) {
3841 if((it->sqlvar[j].sqldata=malloc(sizeof(short)+QMAXARGSIZE))==NULL) {
3842 com_err(whoami, MR_NO_MEM, "setting up SQLDA variables");
3845 it->sqlvar[j].sqllen=QMAXARGSIZE;
3846 it->sqlvar[j].sqlind=null_indicators+j;
3847 null_indicators[j]=0;
3854 /* Use this after FETCH USING DESCRIPTOR one or more
3855 * result columns may contain NULLs. This routine is
3856 * not currently needed, since db/schema creates all
3857 * columns with a NOT NULL WITH DEFAULT clause.
3859 * This is currently dead flesh, since no Moira columns
3860 * allow null values; all use default values.
3862 mr_fix_nulls_in_SQLDA(da)
3865 register IISQLVAR *var;
3869 for(j=0, var=da->sqlvar; j<da->sqld; j++, var++) {
3870 switch(var->sqltype) {
3871 case -IISQ_CHA_TYPE:
3875 case -IISQ_INT_TYPE:
3877 intp=(int *)var->sqldata;
3885 /* prefetch_value():
3886 * This routine fetches an appropriate value from the numvalues table.
3887 * It is a little hack to get around the fact that SQL doesn't let you
3888 * do something like INSERT INTO table (foo) VALUES (other_table.bar).
3890 * It is called from the query table as (*v->pre_rtn)(q,Argv,cl) or
3891 * from within a setup_...() routine with the appropriate arguments.
3893 * Correct functioning of this routine may depend on the assumption
3894 * that this query is an APPEND.
3897 prefetch_value(q,argv,cl)
3902 EXEC SQL BEGIN DECLARE SECTION;
3903 char *name = q->validate->object_id;
3905 EXEC SQL END DECLARE SECTION;
3906 int status, limit, argc;
3908 /* set next object id, limiting it if necessary */
3909 if(!strcmp(name, "uid") || !strcmp(name, "gid"))
3910 limit = 1; /* So far as I know, this isn't needed. Just CMA. */
3913 if((status = set_next_object_id(name, q->rtable, limit)) != MR_SUCCESS)
3916 /* fetch object id */
3917 EXEC SQL SELECT value INTO :value FROM numvalues WHERE name=:name;
3918 if(ingres_errno) return(mr_errcode);
3919 if(sqlca.sqlerrd[2] != 1) return(MR_INTERNAL);
3921 argc = q->argc + q->vcnt; /* end of Argv for APPENDs */
3922 sprintf(argv[argc],"%d",value); /** Could save this step by changing tlist from %s to %d **/
3927 /* prefetch_filesys():
3928 * Fetches the phys_id from filesys based on the filsys_id in argv[0].
3929 * Appends the filsys_id and the phys_id to the argv so they can be
3930 * referenced in an INSERT into a table other than filesys. Also
3931 * see comments at prefetch_value().
3933 * Assumes the existence of a row where filsys_id = argv[0], since a
3934 * filesys label has already been resolved to a filsys_id.
3936 prefetch_filesys(q,argv,cl)
3941 EXEC SQL BEGIN DECLARE SECTION;
3943 EXEC SQL END DECLARE SECTION;
3946 fid = *(int *)argv[0];
3947 EXEC SQL SELECT phys_id INTO :phid FROM filesys WHERE filsys_id = :fid;
3948 if(ingres_errno) return(mr_errcode);
3950 argc=q->argc+q->vcnt;
3951 sprintf(argv[argc++],"%d",fid);
3952 sprintf(argv[argc],"%d",phid);
3957 /* Convert normal Unix-style wildcards to SQL voodoo */
3958 convert_wildcards(arg)
3961 static char buffer[QMAXARGSIZE];
3962 register char *s, *d;
3964 for(d=buffer,s=arg;*s;s++) {
3966 case '*': *d++='%'; *d++='%'; break;
3967 case '?': *d++='_'; break;
3970 case ']': *d++='*'; *d++ = *s; break;
3971 case '%': *d++='*'; *d++='%'; *d++='%'; break;
3972 default: *d++ = *s; break;
3977 /* Copy back into argv */
3983 /* This version includes uppercase conversion, for things like gmac.
3984 * This is necessary because "LIKE" doesn't work with "uppercase()".
3985 * Including it in a wildcard routine saves making two passes over
3986 * the argument string.
3988 convert_wildcards_uppercase(arg)
3991 static char buffer[QMAXARGSIZE];
3992 register char *s, *d;
3994 for(d=buffer,s=arg;*s;s++) {
3996 case '*': *d++='%'; *d++='%'; break;
3997 case '?': *d++='_'; break;
4000 case ']': *d++='*'; *d++ = *s; break;
4001 case '%': *d++='*'; *d++='%'; *d++='%'; break;
4002 default: *d++=toupper(*s); break; /* This is the only diff. */
4007 /* Copy back into argv */
4013 /* eof:qsupport.dc */