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;
597 if (!strcmp(q->shortname, "alis"))
599 else if (!strcmp(q->shortname, "ulis"))
602 for (p = (unsigned char *) argv[idx]; *p; p++)
603 if (badlistchars[*p])
606 if (!strcmp(argv[6 + idx], UNIQUE_GID) || atoi(argv[6 + idx]) == -1) {
607 if (atoi(argv[5 + idx])) {
608 if (set_next_object_id("gid", "list", 1))
609 return(MR_INGRES_ERR);
610 EXEC SQL REPEATED SELECT value INTO :ngid FROM numvalues
612 if (ingres_errno) return(mr_errcode);
613 sprintf(argv[6 + idx], "%d", ngid);
615 strcpy(argv[6 + idx], "-1");
619 if((mr_errcode=prefetch_value(q,argv,cl))!=MR_SUCCESS)
626 /* setup_dlis - verify that the list is no longer being referenced
627 * and may safely be deleted.
630 int setup_dlis(q, argv)
634 EXEC SQL BEGIN DECLARE SECTION;
636 EXEC SQL END DECLARE SECTION;
638 id = *(int *)argv[0];
639 EXEC SQL REPEATED SELECT member_id INTO :idummy FROM imembers
640 WHERE member_id = :id AND member_type='LIST';
641 if (sqlca.sqlerrd[2] > 0)
643 EXEC SQL REPEATED SELECT member_id INTO :idummy FROM imembers
645 if (sqlca.sqlerrd[2] > 0)
647 EXEC SQL REPEATED SELECT label INTO :cdummy FROM filesys
649 if (sqlca.sqlerrd[2] > 0)
651 EXEC SQL REPEATED SELECT tag INTO :cdummy FROM capacls
653 if (sqlca.sqlerrd[2] > 0)
655 EXEC SQL REPEATED SELECT name INTO :cdummy FROM list
656 WHERE acl_id = :id AND acl_type='LIST' AND list_id = :id;
657 if (sqlca.sqlerrd[2] > 0)
659 EXEC SQL REPEATED SELECT name INTO :cdummy FROM servers
660 WHERE acl_id = :id AND acl_type='LIST';
661 if (sqlca.sqlerrd[2] > 0)
663 EXEC SQL REPEATED SELECT entity_id INTO :idummy FROM quota
664 WHERE entity_id = :id AND type='GROUP';
665 if (sqlca.sqlerrd[2] > 0)
667 EXEC SQL REPEATED SELECT acl_id INTO :idummy FROM hostaccess
668 WHERE acl_id = :id AND acl_type='LIST';
669 if (sqlca.sqlerrd[2] > 0)
671 EXEC SQL REPEATED SELECT class INTO :cdummy FROM zephyr z
672 WHERE z.xmt_type = 'LIST' AND z.xmt_id = :id
673 OR z.sub_type = 'LIST' AND z.sub_id = :id
674 OR z.iws_type = 'LIST' AND z.iws_id = :id
675 OR z.iui_type = 'LIST' AND z.iui_id = :id;
676 if (sqlca.sqlerrd[2] > 0)
684 /* setup_dsin - verify that the service is no longer being referenced
685 * and may safely be deleted.
688 int setup_dsin(q, argv)
692 EXEC SQL BEGIN DECLARE SECTION;
694 EXEC SQL END DECLARE SECTION;
698 for(c=name;*c;c++) if(islower(*c)) *c = toupper(*c);
699 EXEC SQL REPEATED SELECT service INTO :cdummy FROM serverhosts
700 WHERE service = :name;
701 if (sqlca.sqlerrd[2] > 0)
703 EXEC SQL REPEATED SELECT inprogress INTO :idummy FROM servers
705 if (sqlca.sqlerrd[2] > 0)
713 /* setup_dshi - verify that the service-host is no longer being referenced
714 * and may safely be deleted.
717 int setup_dshi(q, argv)
721 EXEC SQL BEGIN DECLARE SECTION;
724 EXEC SQL END DECLARE SECTION;
727 for(c=name;*c;c++) if(islower(*c)) *c = toupper(*c); /* to uppercase */
728 id = *(int *)argv[1];
729 EXEC SQL REPEATED SELECT inprogress INTO :idummy FROM serverhosts
730 WHERE service = :name AND mach_id = :id;
731 if (sqlca.sqlerrd[2] > 0)
740 ** setup_add_filesys - verify existance of referenced file systems
752 ** * extract directory prefix from name
753 ** * verify mach_id/dir in nfsphys
754 ** * verify access in {r, w, R, W}
756 ** Side effect: sets variable var_phys_id to the ID of the physical
757 ** filesystem (nfsphys_id for NFS, 0 for RVD)
760 ** MR_NFS - specified directory not exported
761 ** MR_FILESYS_ACCESS - invalid filesys access
765 EXEC SQL BEGIN DECLARE SECTION;
766 static int var_phys_id;
767 EXEC SQL END DECLARE SECTION;
769 setup_afil(q, argv, cl)
776 EXEC SQL BEGIN DECLARE SECTION;
778 char ftype[32], *access;
779 EXEC SQL END DECLARE SECTION;
782 mach_id = *(int *)argv[2];
787 sprintf(ftype, "fs_access_%s", type);
788 EXEC SQL SELECT trans INTO :cdummy FROM alias
789 WHERE name = :ftype AND type = 'TYPE' and trans = :access;
790 if (ingres_errno) return(mr_errcode);
791 if (sqlca.sqlerrd[2] == 0) return(MR_FILESYS_ACCESS);
793 if (!strcmp(type, "NFS"))
794 return (check_nfs(mach_id, name, access));
796 if((mr_errcode=prefetch_value(q,argv,cl))!=MR_SUCCESS)
803 /* Verify the arguments, depending on the FStype. Also, if this is an
804 * NFS filesystem, then update any quotas for that filesystem to reflect
808 setup_ufil(q, argv, cl)
815 EXEC SQL BEGIN DECLARE SECTION;
817 char *entity, ftype[32], *access;
819 EXEC SQL END DECLARE SECTION;
822 mach_id = *(int *)argv[3];
825 fid = *(int *)argv[0];
829 sprintf(ftype, "fs_access_%s", type);
830 EXEC SQL SELECT trans INTO :cdummy FROM alias
831 WHERE name = :ftype AND type='TYPE' AND trans = :access;
832 if (ingres_errno) return(mr_errcode);
833 if (sqlca.sqlerrd[2] == 0) return(MR_FILESYS_ACCESS);
835 if (!strcmp(type, "NFS")) {
836 status = check_nfs(mach_id, name, access);
837 EXEC SQL UPDATE quota SET phys_id = :var_phys_id
838 WHERE filsys_id = :fid;
839 if (ingres_errno) return(mr_errcode);
841 } else if (!strcmp(type, "AFS")) {
843 EXEC SQL REPEATED DELETE FROM quota
844 WHERE type = 'ANY' AND filsys_id = :fid;
845 EXEC SQL SELECT SUM (quota) INTO :total FROM quota
846 WHERE filsys_id = :fid AND phys_id != 0;
847 if (ingres_errno) return(mr_errcode);
850 * append quota (quota = total, filsys_id = fid,
851 * phys_id = 0, entity_id = 0, type = "ANY",
852 * modtime = "now", modby = who, modwith = entity)
854 EXEC SQL INSERT INTO quota (quota, filsys_id, phys_id, entity_id,
855 type, modtime, modby, modwith)
856 VALUES (:total, :fid, 0, 0,
857 'ANY', 'now', :who, :entity) ;
858 if (ingres_errno) return(mr_errcode);
861 EXEC SQL UPDATE quota SET phys_id = 0 WHERE filsys_id = :fid;
862 if (ingres_errno) return(mr_errcode);
868 /* Find the NFS physical partition that the named directory is on.
869 * This is done by comparing the dir against the mount point of the
870 * partition. To make sure we get the correct match when there is
871 * more than one, we sort the query in reverse order by dir name.
874 check_nfs(mach_id, name, access)
875 EXEC SQL BEGIN DECLARE SECTION;
877 EXEC SQL END DECLARE SECTION;
881 EXEC SQL BEGIN DECLARE SECTION;
883 EXEC SQL END DECLARE SECTION;
890 EXEC SQL DECLARE csr101 CURSOR FOR
891 SELECT nfsphys_id, TRIM (dir) FROM nfsphys
892 WHERE mach_id = :mach_id
894 EXEC SQL OPEN csr101;
896 EXEC SQL FETCH csr101 INTO :var_phys_id, :dir;
897 if(sqlca.sqlcode != 0) break;
901 if (*cp1++ != *cp2) break;
909 EXEC SQL CLOSE csr101;
916 /* setup_dfil: free any quota records and fsgroup info associated with
917 * a filesystem when it is deleted. Also adjust the allocation numbers.
920 setup_dfil(q, argv, cl)
925 EXEC SQL BEGIN DECLARE SECTION;
927 EXEC SQL END DECLARE SECTION;
929 id = *(int *)argv[0];
930 EXEC SQL REPEATED SELECT SUM (quota) INTO :total FROM quota
931 WHERE filsys_id = :id;
932 EXEC SQL REPEATED UPDATE nfsphys SET allocated = allocated - :total
933 WHERE nfsphys_id = filesys.phys_id AND filesys.filsys_id = :id;
934 /** Is SQL smart enough to do the PRODUCT above? */
935 /** Or should we code it using another SELECT? */
937 EXEC SQL REPEATED DELETE FROM quota WHERE filsys_id = :id;
938 EXEC SQL REPEATED DELETE FROM fsgroup WHERE filsys_id = :id;
939 EXEC SQL REPEATED DELETE FROM fsgroup WHERE group_id = :id;
940 if (ingres_errno) return(mr_errcode);
945 /* setup_aftg: needed only because using the query table would
946 * create an invalid SQL statement. *sigh* Basically just validates
947 * that the first argument has type 'FSGROUP' in table 'filesys'.
950 setup_aftg(q, argv, cl)
955 EXEC SQL SELECT filsys_id INTO :idummy FROM filesys
956 WHERE type='FSGROUP';
958 if (sqlca.sqlcode != 0)
959 return(MR_NO_MATCH); /* Is there a better error code to return? */
965 /* setup_dnfp: check to see that the nfs physical partition does not have
966 * any filesystems assigned to it before allowing it to be deleted.
969 setup_dnfp(q, argv, cl)
974 EXEC SQL BEGIN DECLARE SECTION;
977 EXEC SQL END DECLARE SECTION;
979 id = *(int *)argv[0];
981 EXEC SQL REPEATED SELECT label INTO :cdummy FROM filesys fs, nfsphys np
982 WHERE fs.mach_id = :id AND fs.phys_id = np.nfsphys_id
983 AND np.mach_id = :id AND np.dir = :dir;
984 if (sqlca.sqlerrd[2] > 0)
992 /* setup_dqot: Remove allocation from nfsphys before deleting quota.
993 * argv[0] = filsys_id
994 * argv[1] = type if "update_quota" or "delete_quota"
995 * argv[2 or 1] = users_id or list_id
998 setup_dqot(q, argv, cl)
1003 EXEC SQL BEGIN DECLARE SECTION;
1006 EXEC SQL END DECLARE SECTION;
1008 fs = *(int *)argv[0];
1009 if (!strcmp(q->name, "update_quota") || !strcmp(q->name, "delete_quota")) {
1011 id = *(int *)argv[2];
1014 id = *(int *)argv[1];
1017 EXEC SQL REPEATED SELECT quota INTO :quota FROM quota
1018 WHERE type = :qtype AND entity_id = :id AND filsys_id = :fs;
1019 EXEC SQL REPEATED UPDATE nfsphys
1020 SET allocated = nfsphys.allocated - :quota
1021 WHERE nfsphys_id = filesys.physid AND filesys.filsys_id = :fs;
1023 if (ingres_errno) return(mr_errcode);
1028 /* setup_sshi: don't exclusive lock the machine table during
1029 * set_server_host_internal.
1032 setup_sshi(q, argv, cl)
1038 EXEC SQL set lockmode session where readlock = system;
1043 /* setup add_kerberos_user_mapping: add the string to the string
1044 * table if necessary.
1047 setup_akum(q, argv, cl)
1052 EXEC SQL BEGIN DECLARE SECTION;
1055 EXEC SQL END DECLARE SECTION;
1058 if (name_to_id(name, "STRING", &id) != MR_SUCCESS) {
1059 if (q->type != APPEND) return(MR_STRING);
1060 EXEC SQL SELECT value INTO :id FROM numvalues
1061 WHERE name = 'strings_id';
1063 EXEC SQL UPDATE numvalues SET value = :id
1064 WHERE name = 'strings_id';
1065 EXEC SQL INSERT INTO strings (string_id, string) VALUES (:id, :name);
1066 cache_entry(name, "STRING", id);
1068 if (ingres_errno) return(mr_errcode);
1069 *(int *)argv[1] = id;
1075 /* FOLLOWUP ROUTINES */
1077 /* generic set_modtime routine. This takes the table name from the query,
1078 * and will update the modtime, modby, and modwho fields in the entry in
1079 * the table whose name field matches argv[0].
1082 set_modtime(q, argv, cl)
1087 char *name, *entity, *table;
1090 entity = cl->entity;
1091 who = cl->client_id;
1095 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);
1096 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
1101 /* generic set_modtime_by_id routine. This takes the table name from
1102 * the query, and the id name from the validate record,
1103 * and will update the modtime, modby, and modwho fields in the entry in
1104 * the table whose id matches argv[0].
1107 set_modtime_by_id(q, argv, cl)
1112 char *entity, *table, *id_name;
1115 entity = cl->entity;
1116 who = cl->client_id;
1118 id_name = q->validate->object_id;
1120 id = *(int *)argv[0];
1121 sprintf(stmt_buf,"UPDATE %s SET modtime = 'now', modby = %d, \
1122 modwith = '%s' WHERE %s.%s = %d",table,who,entity,table,id_name,id);
1123 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
1128 /* Sets the finger modtime on a user record. The users_id will be in argv[0].
1131 set_finger_modtime(q, argv, cl)
1136 EXEC SQL BEGIN DECLARE SECTION;
1139 EXEC SQL END DECLARE SECTION;
1141 entity = cl->entity;
1142 who = cl->client_id;
1143 users_id = *(int *)argv[0];
1145 EXEC SQL UPDATE users SET fmodtime='now', fmodby = :who, fmodwith = :entity
1146 WHERE users.users_id = :users_id;
1152 /* Sets the pobox modtime on a user record. The users_id will be in argv[0].
1155 set_pobox_modtime(q, argv, cl)
1160 EXEC SQL BEGIN DECLARE SECTION;
1163 EXEC SQL END DECLARE SECTION;
1165 entity = cl->entity;
1166 who = cl->client_id;
1167 users_id = *(int *)argv[0];
1169 EXEC SQL UPDATE users SET pmodtime='now', pmodby = :who, pmodwith = :entity
1170 WHERE users.users_id = :users_id;
1176 /* Like set_modtime, but uppercases the name first.
1179 set_uppercase_modtime(q, argv, cl)
1184 char *name, *entity, *table;
1187 entity = cl->entity;
1188 who = cl->client_id;
1192 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);
1193 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
1199 /* Sets the modtime on the machine whose mach_id is in argv[0]. This routine
1200 * is necessary for add_machine_to_cluster becuase the table that query
1201 * operates on is "mcm", not "machine".
1204 set_mach_modtime_by_id(q, argv, cl)
1209 EXEC SQL BEGIN DECLARE SECTION;
1212 EXEC SQL END DECLARE SECTION;
1214 entity = cl->entity;
1215 who = cl->client_id;
1216 id = *(int *)argv[0];
1217 EXEC SQL UPDATE machine SET modtime='now', modby = :who, modwith = :entity
1218 WHERE machine.mach_id = :id;
1224 /* Sets the modtime on the cluster whose mach_id is in argv[0]. This routine
1225 * is necessary for add_cluster_data and delete_cluster_data becuase the
1226 * table that query operates on is "svc", not "cluster".
1229 set_cluster_modtime_by_id(q, argv, cl)
1234 EXEC SQL BEGIN DECLARE SECTION;
1237 EXEC SQL END DECLARE SECTION;
1239 entity = cl->entity;
1240 who = cl->client_id;
1242 id = *(int *)argv[0];
1243 EXEC SQL UPDATE cluster SET modtime='now', modby = :who, modwith = :entity
1244 WHERE cluster.clu_id = :id;
1249 /* sets the modtime on the serverhost where the service name is in argv[0]
1250 * and the mach_id is in argv[1].
1253 set_serverhost_modtime(q, argv, cl)
1258 EXEC SQL BEGIN DECLARE SECTION;
1259 char *entity, *serv;
1261 EXEC SQL END DECLARE SECTION;
1263 entity = cl->entity;
1264 who = cl->client_id;
1267 id = *(int *)argv[1];
1268 EXEC SQL UPDATE serverhosts
1269 SET modtime = 'now', modby = :who, modwith = :entity
1270 WHERE service = :serv AND mach_id = :id;
1275 /* sets the modtime on the nfsphys where the mach_id is in argv[0] and the
1276 * directory name is in argv[1].
1279 set_nfsphys_modtime(q, argv, cl)
1284 EXEC SQL BEGIN DECLARE SECTION;
1287 EXEC SQL END DECLARE SECTION;
1289 entity = cl->entity;
1290 who = cl->client_id;
1292 id = *(int *)argv[0];
1294 EXEC SQL UPDATE nfsphys SET modtime = 'now', modby = :who, modwith = :entity
1295 WHERE dir = :dir AND mach_id = :id;
1300 /* sets the modtime on a filesystem, where argv[0] contains the filesys
1304 set_filesys_modtime(q, argv, cl)
1309 EXEC SQL BEGIN DECLARE SECTION;
1310 char *label, *entity;
1312 EXEC SQL END DECLARE SECTION;
1314 entity = cl->entity;
1315 who = cl->client_id;
1318 if (!strcmp(q->shortname, "ufil"))
1321 EXEC SQL UPDATE filesys SET modtime = 'now', modby = :who,
1322 modwith = :entity, phys_id = :var_phys_id
1323 WHERE label = LEFT(:label,SIZE(label));
1328 /* sets the modtime on a zephyr class, where argv[0] contains the class
1332 set_zephyr_modtime(q, argv, cl)
1337 EXEC SQL BEGIN DECLARE SECTION;
1338 char *class, *entity;
1340 EXEC SQL END DECLARE SECTION;
1342 entity = cl->entity;
1343 who = cl->client_id;
1347 EXEC SQL UPDATE zephyr SET modtime = 'now', modby = :who, modwith = :entity
1348 WHERE class = LEFT(:class,SIZE(class));
1354 /* fixes the modby field. This will be the second to last thing in the
1355 * argv, the argv length is determined from the query structure. It is
1356 * passed as a pointer to an integer. This will either turn it into a
1357 * username, or # + the users_id.
1359 followup_fix_modby(q, sq, v, action, actarg, cl)
1361 register struct save_queue *sq;
1363 register int (*action)();
1364 register int actarg;
1368 char **argv, *malloc();
1372 while (sq_get_data(sq, &argv)) {
1375 status = id_to_name(id, "USER", &argv[i]);
1377 status = id_to_name(-id, "STRING", &argv[i]);
1378 if (status && status != MR_NO_MATCH)
1380 (*action)(q->vcnt, argv, actarg);
1381 for (j = 0; j < q->vcnt; j++)
1390 /* After retrieving a user account, fix the modby field and signature.
1391 * The modby field is the second to last thing in the
1392 * argv, the argv length is determined from the query structure. It is
1393 * passed as a pointer to an integer. This will either turn it into a
1394 * username, or # + the users_id. Only "gua*" queries have a signature,
1395 * these are ones with U_END return values. "gub*" queries also use this
1396 * routine but don't have a signature.
1398 followup_guax(q, sq, v, action, actarg, cl)
1400 register struct save_queue *sq;
1402 register int (*action)();
1403 register int actarg;
1407 char **argv, *malloc();
1409 unsigned char sigbuf[256];
1412 EXEC SQL BEGIN DECLARE SECTION;
1415 EXEC SQL END DECLARE SECTION;
1420 while (sq_get_data(sq, &argv)) {
1423 status = id_to_name(id, "USER", &argv[i]);
1425 status = id_to_name(-id, "STRING", &argv[i]);
1426 if (status && status != MR_NO_MATCH)
1429 if (q->vcnt == U_END && strlen(argv[U_SIGNATURE])) {
1430 login = argv[U_NAME];
1431 EXEC SQL REPEATED SELECT sigdate, sigwho FROM users
1432 INTO :timestamp, :who
1433 WHERE login = :login; /** Use LEFT(...,SIZE(...)) here? **/
1434 /** What about (INGRES) error handling? **/
1435 /** Is this guaranteed to be a singleton select? **/
1437 status = id_to_name(who, "STRING", &kname);
1438 si.timestamp = timestamp;
1439 si.SigInfoVersion = 0; /* XXXXX this isn't used */
1440 kname_parse(si.pname, si.pinst, si.prealm, kname);
1442 si.rawsig = (unsigned char *)argv[U_SIGNATURE];
1443 GDSS_Recompose(&si, sigbuf);
1444 argv[U_SIGNATURE] = strsave(sigbuf);
1447 (*action)(q->vcnt, argv, actarg);
1448 for (j = 0; j < q->vcnt; j++)
1458 ** followup_ausr - add finger and pobox entries, set_user_modtime
1461 ** argv[0] - login (add_user)
1462 ** argv[3] - last name
1463 ** argv[4] - first name
1464 ** argv[5] - middle name
1468 followup_ausr(q, argv, cl)
1473 EXEC SQL BEGIN DECLARE SECTION;
1474 int who, status, id;
1475 char *login, *entity, *src, *dst, *name;
1477 EXEC SQL END DECLARE SECTION;
1479 char databuf[32], *kname_unparse();
1480 EXEC SQL BEGIN DECLARE SECTION;
1482 int sigwho, timestamp;
1483 EXEC SQL END DECLARE SECTION;
1487 /* build fullname */
1488 if (strlen(argv[4]) && strlen(argv[5]))
1489 sprintf(fullname, "%s %s %s", argv[4], argv[5], argv[3]);
1490 else if (strlen(argv[4]))
1491 sprintf(fullname, "%s %s", argv[4], argv[3]);
1493 sprintf(fullname, "%s", argv[3]);
1496 if (q->vcnt == U_END && *argv[U_SIGNATURE]) {
1497 sprintf(databuf, "%s:%s", argv[U_NAME], argv[U_MITID]);
1498 /* skip bytes for timestamp & kname */
1499 si.rawsig = (unsigned char *) rawsig;
1500 status = GDSS_Verify(databuf, strlen(databuf), argv[U_SIGNATURE], &si);
1502 name = kname_unparse(si.pname, si.pinst, si.prealm);
1503 status = name_to_id(name, "STRING", &sigwho);
1504 if (status == MR_NO_MATCH) {
1505 EXEC SQL REPEATED SELECT value INTO sigwho FROM numvalues
1506 WHERE name='strings_id';
1508 EXEC SQL REPEATED UPDATE numvalues SET value = :sigwho
1509 WHERE name='strings_id';
1510 INSERT INTO strings (string_id, string)
1511 VALUES (:sigwho, :name);
1513 return(gdss2et(status));
1514 timestamp = si.timestamp;
1516 return(gdss2et(status));
1525 who = cl->client_id;
1526 entity = cl->entity;
1528 /* create finger entry, pobox & set modtime on user */
1530 EXEC SQL REPEATED UPDATE users
1531 SET modtime='now', modby=:who, modwith = :entity,
1532 fullname = :fullname, affiliation = type,
1533 signature = :rawsig, sigdate = :timestamp, sigwho = :sigwho,
1534 fmodtime='now', fmodby = :who, fmodwith = :entity,
1535 potype='NONE', pmodtime='now', pmodby = :who, pmodwith = :entity
1536 WHERE login = :login;
1538 EXEC SQL REPEATED UPDATE users
1539 SET modtime='now', modby=:who, modwith = :entity,
1540 fullname = :fullname, affiliation = type,
1541 fmodtime='now', fmodby = :who, fmodwith = :entity,
1542 potype='NONE', pmodtime='now', pmodby = :who, pmodwith = :entity
1543 WHERE login = :login;
1551 ** followup_uusr - do signature, set_user_modtime
1554 ** argv[0] - login (add_user)
1555 ** argv[U_SIGNATURE] - sig
1559 followup_uuac(q, argv, cl)
1564 EXEC SQL BEGIN DECLARE SECTION;
1565 int who, status, id;
1566 char *entity, *name;
1567 EXEC SQL END DECLARE SECTION;
1569 char databuf[32], *kname_unparse();
1570 EXEC SQL BEGIN DECLARE SECTION;
1573 int sigwho, timestamp;
1574 EXEC SQL END DECLARE SECTION;
1578 id = *(int *)argv[0];
1579 who = cl->client_id;
1580 entity = cl->entity;
1583 if (q->vcnt == U_MODTIME && *argv[U_SIGNATURE + 1]) {
1585 status = id_to_name(id, "USER", &login);
1586 sprintf(databuf, "%s:%s", login, argv[U_MITID+1]);
1588 /* skip bytes for timestamp & kname */
1589 si.rawsig = (unsigned char *) rawsig;
1590 status = GDSS_Verify(databuf, strlen(databuf), argv[U_SIGNATURE+1], &si);
1592 name = kname_unparse(si.pname, si.pinst, si.prealm);
1593 status = name_to_id(name, "STRING", &sigwho);
1594 if (status == MR_NO_MATCH) {
1595 EXEC SQL REPEATED SELECT value INTO sigwho FROM numvalues
1596 WHERE name='strings_id';
1598 EXEC SQL REPEATED UPDATE numvalues SET value = :sigwho
1599 WHERE name='strings_id';
1600 INSERT INTO strings (string_id, string)
1601 VALUES (:sigwho, :name);
1603 return(gdss2et(status));
1604 timestamp = si.timestamp;
1606 return(gdss2et(status));
1614 /* create finger entry, pobox & set modtime on user */
1617 EXEC SQL REPEATED UPDATE users SET modtime='now', modby = :who, modwith = :entity
1618 signature = :rawsig, sigdate = :timestamp, sigwho = :sigwho
1619 WHERE users_id = :id;
1621 EXEC SQL REPEATED UPDATE users SET modtime='now', modby = :who, modwith = :entity
1622 WHERE users_id = :id;
1628 /* followup_gpob: fixes argv[2] based on the IDs currently there and the
1629 * type in argv[1]. Then completes the upcall to the user.
1631 * argv[2] is of the form "123:234" where the first integer is the machine
1632 * ID if it is a pop box, and the second is the string ID if it is an SMTP
1633 * box. argv[1] should be "POP", "SMTP", or "NONE". Boxes of type NONE
1637 followup_gpob(q, sq, v, action, actarg, cl)
1638 register struct query *q;
1639 register struct save_queue *sq;
1640 register struct validate *v;
1641 register int (*action)();
1645 char **argv, *index();
1647 int mid, sid, status, i;
1650 while (sq_get_data(sq, &argv)) {
1651 mr_trim_args(2, argv);
1653 p = index(argv[2], ':');
1655 mid = atoi(argv[2]);
1658 if (!strcmp(ptype, "POP")) {
1659 status = id_to_name(mid, "MACHINE", &argv[2]);
1660 if (status == MR_NO_MATCH)
1662 } else if (!strcmp(ptype, "SMTP")) {
1663 status = id_to_name(sid, "STRING", &argv[2]);
1664 if (status == MR_NO_MATCH)
1666 } else /* ptype == "NONE" */ {
1669 if (status) return(status);
1671 if (!strcmp(q->shortname, "gpob")) {
1672 sid = atoi(argv[4]);
1674 status = id_to_name(sid, "USER", &argv[4]);
1676 status = id_to_name(-sid, "STRING", &argv[4]);
1678 if (status && status != MR_NO_MATCH) return(status);
1680 (*action)(q->vcnt, argv, actarg);
1682 /* free saved data */
1683 for (i = 0; i < q->vcnt; i++)
1689 return (MR_SUCCESS);
1693 /* followup_glin: fix the ace_name in argv[8]. argv[7] will contain the
1694 * ace_type: "LIST", "USER", or "NONE". Decode the id in argv[8] into the
1695 * proper name based on the type, and repace that string in the argv.
1696 * Also fixes the modby field by called followup_fix_modby.
1699 followup_glin(q, sq, v, action, actarg, cl)
1700 register struct query *q;
1701 register struct save_queue *sq;
1702 register struct validate *v;
1703 register int (*action)();
1707 char **argv, *malloc(), *realloc(), *type;
1708 int id, i, idx, status;
1711 if (!strcmp(q->shortname, "gsin"))
1714 while (sq_get_data(sq, &argv)) {
1715 mr_trim_args(q->vcnt, argv);
1717 id = atoi(argv[i = q->vcnt - 2]);
1719 status = id_to_name(id, "USER", &argv[i]);
1721 status = id_to_name(-id, "STRING", &argv[i]);
1722 if (status && status != MR_NO_MATCH)
1725 id = atoi(argv[idx]);
1726 type = argv[idx - 1];
1728 if (!strcmp(type, "LIST")) {
1729 status = id_to_name(id, "LIST", &argv[idx]);
1730 } else if (!strcmp(type, "USER")) {
1731 status = id_to_name(id, "USER", &argv[idx]);
1732 } else if (!strcmp(type, "KERBEROS")) {
1733 status = id_to_name(id, "STRING", &argv[idx]);
1734 } else if (!strcmp(type, "NONE")) {
1737 argv[idx] = strsave("NONE");
1741 argv[idx] = strsave("???");
1743 if (status && status != MR_NO_MATCH)
1746 if (!strcmp(q->shortname, "glin") && atoi(argv[6]) == -1) {
1747 argv[6] = realloc(argv[6], strlen(UNIQUE_GID) + 1);
1748 strcpy(argv[6], UNIQUE_GID);
1752 (*action)(q->vcnt, argv, actarg);
1754 /* free saved data */
1755 for (i = 0; i < q->vcnt; i++)
1761 return (MR_SUCCESS);
1765 /* followup_gqot: Fix the entity name, directory name & modby fields
1766 * argv[0] = filsys_id
1768 * argv[2] = entity_id
1769 * argv[3] = ascii(quota)
1772 followup_gqot(q, sq, v, action, actarg, cl)
1774 register struct save_queue *sq;
1776 register int (*action)();
1777 register int actarg;
1781 char **argv, *malloc();
1782 EXEC SQL BEGIN DECLARE SECTION;
1785 EXEC SQL END DECLARE SECTION;
1788 if (!strcmp(q->name, "get_quota") ||
1789 !strcmp(q->name, "get_quota_by_filesys"))
1793 while (sq_get_data(sq, &argv)) {
1795 switch (argv[1][0]) {
1797 status = id_to_name(atoi(argv[2]), "USER", &argv[2]);
1801 status = id_to_name(atoi(argv[2]), "LIST", &argv[2]);
1805 argv[2] = strsave("system:anyuser");
1809 argv[2] = malloc(8);
1810 sprintf(argv[2], "%d", id);
1813 id = atoi(argv[idx]);
1815 argv[idx] = malloc(256);
1819 EXEC SQL REPEATED SELECT name INTO :name FROM filesys
1820 WHERE label = :label;
1822 EXEC SQL REPEATED SELECT dir INTO :name FROM nfsphys
1823 WHERE nfsphys_id = :id;
1825 if (sqlca.sqlerrd[2] != 1) {
1826 sprintf(argv[idx], "#%d", id);
1829 id = atoi(argv[idx+3]);
1831 status = id_to_name(id, "USER", &argv[idx+3]);
1833 status = id_to_name(-id, "STRING", &argv[idx+3]);
1834 if (status && status != MR_NO_MATCH)
1836 (*action)(q->vcnt, argv, actarg);
1837 for (j = 0; j < q->vcnt; j++)
1846 /* followup_aqot: Add allocation to nfsphys after creating quota.
1847 * argv[0] = filsys_id
1848 * argv[1] = type if "add_quota" or "update_quota"
1850 * argv[3 or 2] = ascii(quota)
1853 followup_aqot(q, argv, cl)
1858 EXEC SQL BEGIN DECLARE SECTION;
1859 int quota, id, fs, who;
1860 char *entity, *qtype;
1861 EXEC SQL END DECLARE SECTION;
1863 fs = *(int *)argv[0];
1864 if (!strcmp(q->name, "add_quota") || !strcmp(q->name, "update_quota")) {
1866 id = *(int *)argv[2];
1867 quota = atoi(argv[3]);
1870 id = *(int *)argv[1];
1871 quota = atoi(argv[2]);
1873 who = cl->client_id;
1874 entity = cl->entity;
1876 EXEC SQL REPEATED UPDATE quota
1877 SET modtime = 'now', modby = :who, modwith = :entity
1878 WHERE filsys_id = :fs and type = :qtype and entity_id = :id;
1879 EXEC SQL REPEATED UPDATE nfsphys
1880 SET allocated = allocated + :quota
1881 WHERE nfsphys_id = filesys.phys_id AND filesys.filsys_id = :fs;
1882 if (ingres_errno) return(mr_errcode);
1887 followup_gpce(q, sq, v, action, actarg, cl)
1889 register struct save_queue *sq;
1891 register int (*action)();
1892 register int actarg;
1896 char **argv, *malloc();
1900 while (sq_get_data(sq, &argv)) {
1901 id = atoi(argv[PCAP_QSERVER]);
1902 status = id_to_name(id, "MACHINE", &argv[PCAP_QSERVER]);
1903 if (status) return (status);
1906 status = id_to_name(id, "USER", &argv[i]);
1908 status = id_to_name(-id, "STRING", &argv[i]);
1909 if (status && status != MR_NO_MATCH)
1911 (*action)(q->vcnt, argv, actarg);
1912 for (j = 0; j < q->vcnt; j++)
1924 followup_gzcl(q, sq, v, action, actarg, cl)
1925 register struct query *q;
1926 register struct save_queue *sq;
1927 register struct validate *v;
1928 register int (*action)();
1935 while (sq_get_data(sq, &argv)) {
1936 mr_trim_args(q->vcnt, argv);
1938 id = atoi(argv[i = q->vcnt - 2]);
1940 status = id_to_name(id, "USER", &argv[i]);
1942 status = id_to_name(-id, "STRING", &argv[i]);
1943 if (status && status != MR_NO_MATCH)
1946 for (i = 1; i < 8; i+=2) {
1947 id = atoi(argv[i+1]);
1948 if (!strcmp(argv[i], "LIST")) {
1949 status = id_to_name(id, "LIST", &argv[i+1]);
1950 } else if (!strcmp(argv[i], "USER")) {
1951 status = id_to_name(id, "USER", &argv[i+1]);
1952 } else if (!strcmp(argv[i], "KERBEROS")) {
1953 status = id_to_name(id, "STRING", &argv[i+1]);
1954 } else if (!strcmp(argv[i], "NONE")) {
1957 argv[i+1] = strsave("NONE");
1961 argv[i+1] = strsave("???");
1963 if (status && status != MR_NO_MATCH)
1968 (*action)(q->vcnt, argv, actarg);
1970 /* free saved data */
1971 for (i = 0; i < q->vcnt; i++)
1983 followup_gsha(q, sq, v, action, actarg, cl)
1984 register struct query *q;
1985 register struct save_queue *sq;
1986 register struct validate *v;
1987 register int (*action)();
1994 while (sq_get_data(sq, &argv)) {
1995 mr_trim_args(q->vcnt, argv);
1999 status = id_to_name(id, "USER", &argv[4]);
2001 status = id_to_name(-id, "STRING", &argv[4]);
2002 if (status && status != MR_NO_MATCH)
2006 if (!strcmp(argv[1], "LIST")) {
2007 status = id_to_name(id, "LIST", &argv[2]);
2008 } else if (!strcmp(argv[1], "USER")) {
2009 status = id_to_name(id, "USER", &argv[2]);
2010 } else if (!strcmp(argv[1], "KERBEROS")) {
2011 status = id_to_name(id, "STRING", &argv[2]);
2012 } else if (!strcmp(argv[1], "NONE")) {
2015 argv[2] = strsave("NONE");
2019 argv[2] = strsave("???");
2021 if (status && status != MR_NO_MATCH)
2025 (*action)(q->vcnt, argv, actarg);
2027 /* free saved data */
2028 for (i = 0; i < q->vcnt; i++)
2038 /* Special query routines */
2040 /* set_pobox - this does all of the real work.
2041 * argv = user_id, type, box
2042 * if type is POP, then box should be a machine, and its ID should be put in
2043 * pop_id. If type is SMTP, then box should be a string and its ID should
2044 * be put in box_id. If type is NONE, then box doesn't matter.
2047 int set_pobox(q, argv, cl)
2052 EXEC SQL BEGIN DECLARE SECTION;
2054 char *box, potype[9];
2055 EXEC SQL END DECLARE SECTION;
2059 user = *(int *)argv[0];
2061 EXEC SQL REPEATED SELECT pop_id, potype INTO :id, :potype FROM users
2062 WHERE users_id = :user;
2063 if (ingres_errno) return(mr_errcode);
2064 if (!strcmp(strtrim(potype), "POP"))
2065 set_pop_usage(id, -1);
2067 if (!strcmp(argv[1], "POP")) {
2068 status = name_to_id(box, "MACHINE", &id);
2069 if (status == MR_NO_MATCH)
2073 EXEC SQL REPEATED UPDATE users SET potype = 'POP', pop_id = :id
2074 WHERE users_id = :user;
2075 set_pop_usage(id, 1);
2076 } else if (!strcmp(argv[1], "SMTP")) {
2077 if (index(box, '/') || index(box, '|'))
2078 return(MR_BAD_CHAR);
2079 status = name_to_id(box, "STRING", &id);
2080 if (status == MR_NO_MATCH) {
2081 EXEC SQL REPEATED SELECT value INTO :id FROM numvalues
2082 WHERE name='strings_id';
2084 EXEC SQL REPEATED UPDATE numvalues SET value = :id
2085 WHERE name='strings_id';
2086 EXEC SQL INSERT INTO strings (string_id, string)
2090 EXEC SQL REPEATED UPDATE users SET potype='SMTP', box_id = :id
2091 WHERE users_id = :user;
2092 } else /* argv[1] == "NONE" */ {
2093 EXEC SQL REPEATED UPDATE users SET potype='NONE'
2094 WHERE users_id = :user;
2097 set_pobox_modtime(q, argv, cl);
2098 EXEC SQL REPEATED UPDATE tblstats SET updates = updates+1, modtime='now'
2099 WHERE tblstats.table_name='users';
2100 if (ingres_errno) return(mr_errcode);
2105 /* get_list_info: passed a wildcard list name, returns lots of stuff about
2106 * each list. This is tricky: first build a queue of all requested
2107 * data. Rest of processing consists of fixing gid, ace_name, and modby.
2110 get_list_info(q, aargv, cl, action, actarg)
2111 register struct query *q;
2114 register int (*action)();
2117 char *argv[13], *malloc(), *realloc();
2118 EXEC SQL BEGIN DECLARE SECTION;
2119 char *name, acl_type[9], listname[33], active[5], public[5], hidden[5];
2120 char maillist[5], grouplist[5], gid_str[6], acl_name[256], desc[256];
2121 char modtime[27], modby[256], modwith[9];
2122 int id, rowcount, acl_id, hid, modby_id;
2123 EXEC SQL END DECLARE SECTION;
2124 int returned, status;
2125 struct save_queue *sq, *sq_create();
2127 returned = rowcount = 0;
2129 convert_wildcards(name);
2132 EXEC SQL DECLARE csr102 CURSOR FOR SELECT list_id FROM list
2133 WHERE name LIKE :name ESCAPE '*';
2134 EXEC SQL OPEN csr102;
2137 EXEC SQL FETCH csr102 INTO :id;
2138 if(sqlca.sqlcode!=0) break;
2139 sq_save_data(sq, id);
2142 EXEC SQL CLOSE csr102;
2144 if (ingres_errno) return(mr_errcode);
2146 return(MR_NO_MATCH);
2148 argv[0] = listname; argv[1] = active; argv[2] = public; argv[3] = hidden;
2149 argv[4] = maillist; argv[5] = grouplist; argv[6] = gid_str;
2150 argv[7] = acl_type; argv[9] = desc; argv[10] = modtime; argv[12] = modwith;
2152 while (sq_get_data(sq, &id)) {
2156 EXEC SQL REPEATED SELECT name, CHAR(active), CHAR(publicflg),
2157 CHAR(hidden), hidden, CHAR(maillist), CHAR(grouplist), CHAR(gid),
2158 TRIM(acl_type), acl_id, description, CHAR(modtime), modby, modwith
2159 INTO :listname, :active, :public, :hidden, :hid, :maillist,
2160 :grouplist, :gid_str, :acl_type, :acl_id, :desc,
2161 :modtime, :modby_id, :modwith
2162 FROM list WHERE list_id = :id;
2164 if (ingres_errno) return(mr_errcode);
2166 if (atoi(gid_str) == -1)
2167 argv[6] = UNIQUE_GID;
2169 argv[8] = malloc(0);
2170 if (!strcmp(acl_type, "LIST")) {
2171 status = id_to_name(acl_id, "LIST", &argv[8]);
2172 } else if (!strcmp(acl_type, "USER")) {
2173 status = id_to_name(acl_id, "USER", &argv[8]);
2174 } else if (!strcmp(acl_type, "KERBEROS")) {
2175 status = id_to_name(acl_id, "STRING", &argv[8]);
2176 } else if (!strcmp(acl_type, "NONE")) {
2179 argv[8] = strsave("NONE");
2183 argv[8] = strsave("???");
2185 if (status && status != MR_NO_MATCH) return(status);
2187 argv[11] = malloc(0);
2189 status = id_to_name(modby_id, "USER", &argv[11]);
2191 status = id_to_name(-modby_id, "STRING", &argv[11]);
2192 if (status && status != MR_NO_MATCH) return(status);
2194 mr_trim_args(q->vcnt, argv);
2196 (*action)(q->vcnt, argv, actarg);
2202 if (ingres_errno) return(mr_errcode);
2203 return (MR_SUCCESS);
2207 /* Add_member_to_list: do list flattening as we go! MAXLISTDEPTH is
2208 * how many different ancestors a member is allowed to have.
2211 #define MAXLISTDEPTH 1024
2213 int add_member_to_list(q, argv, cl)
2218 EXEC SQL BEGIN DECLARE SECTION;
2219 int id, lid, mid, error, who, ref;
2220 char *mtype, dtype[9], *entity;
2221 EXEC SQL END DECLARE SECTION;
2222 int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a;
2223 int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d;
2225 char *dtypes[MAXLISTDEPTH];
2226 char *iargv[3], *buf;
2228 lid = *(int *)argv[0];
2230 mid = *(int *)argv[2];
2231 /* if the member is already a direct member of the list, punt */
2232 EXEC SQL REPEATED SELECT list_id INTO :idummy FROM imembers
2233 WHERE list_id = :lid AND member_id = :mid
2234 AND member_type = :mtype AND direct = 1;
2235 if (sqlca.sqlerrd[2] > 0)
2237 if (!strcasecmp(mtype, "STRING")) {
2239 status = id_to_name(mid, "STRING", &buf);
2240 if (status) return(status);
2241 if (index(buf, '/') || index(buf, '|')) {
2243 return(MR_BAD_CHAR);
2251 EXEC SQL DECLARE csr103 CURSOR FOR
2252 SELECT list_id, ref_count FROM imembers
2253 WHERE member_id = :lid AND member_type='LIST';
2254 EXEC SQL OPEN csr103;
2256 EXEC SQL FETCH csr103 INTO :id, :ref;
2257 if(sqlca.sqlcode != 0) break;
2259 ancestors[acount++] = id;
2260 if (acount >= MAXLISTDEPTH) break;
2262 EXEC SQL CLOSE csr103;
2263 if (ingres_errno) return(mr_errcode);
2264 if (acount >= MAXLISTDEPTH) {
2265 return(MR_INTERNAL);
2267 descendants[0] = mid;
2272 if (!strcmp(mtype, "LIST")) {
2273 EXEC SQL DECLARE csr104 CURSOR FOR
2274 SELECT member_id, member_type, ref_count
2276 WHERE list_id = :mid;
2277 EXEC SQL OPEN csr104;
2279 EXEC SQL FETCH csr104 INTO :id, :dtype, :ref;
2280 if(sqlca.sqlcode != 0) break;
2283 dtypes[dcount] = "LIST";
2286 dtypes[dcount] = "USER";
2289 dtypes[dcount] = "STRING";
2292 dtypes[dcount] = "KERBEROS";
2299 descendants[dcount++] = id;
2300 if (dcount >= MAXLISTDEPTH) {
2305 EXEC SQL CLOSE csr104;
2306 if (ingres_errno) return(mr_errcode);
2308 return(MR_INTERNAL);
2310 for (a = 0; a < acount; a++) {
2312 for (d = 0; d < dcount; d++) {
2313 mid = descendants[d];
2315 if (mid == lid && !strcmp(mtype, "LIST")) {
2316 return(MR_LISTLOOP);
2318 EXEC SQL REPEATED SELECT ref_count INTO :idummy FROM imembers
2319 WHERE list_id = :lid AND member_id = :mid
2320 AND member_type = :mtype;
2321 ref = aref[a] * dref[d];
2322 if (sqlca.sqlerrd[2] > 0) {
2323 if (a == 0 && d == 0) {
2324 EXEC SQL UPDATE imembers
2325 SET ref_count = ref_count+ref, direct=1
2326 WHERE list_id = :lid AND member_id = :mid
2327 AND member_type = :mtype;
2329 EXEC SQL UPDATE imembers
2330 SET ref_count = ref_count+ref
2331 WHERE list_id = :lid AND member_id = :mid
2332 AND member_type = :mtype;
2335 incremental_clear_before();
2336 if (a == 0 && d == 0) {
2337 EXEC SQL INSERT INTO imembers
2338 (list_id, member_id, direct, member_type, ref_count)
2339 VALUES (:lid, :mid, 1, :mtype, 1);
2341 EXEC SQL INSERT INTO imembers
2342 (list_id, member_id, member_type, ref_count)
2343 VALUES (:lid, :mid, :mtype, 1);
2345 iargv[0] = (char *)lid;
2347 iargv[2] = (char *)mid;
2348 incremental_after("members", 0, iargv);
2352 lid = *(int *)argv[0];
2353 entity = cl->entity;
2354 who = cl->client_id;
2355 EXEC SQL REPEATED UPDATE list
2356 SET modtime='now', modby = :who, modwith = :entity
2357 WHERE list_id = :lid;
2358 if (ingres_errno) return(mr_errcode);
2363 /* Delete_member_from_list: do list flattening as we go!
2366 int delete_member_from_list(q, argv, cl)
2371 EXEC SQL BEGIN DECLARE SECTION;
2372 int id, lid, mid, cnt, error, who, ref;
2373 char *mtype, dtype[9], *entity;
2374 EXEC SQL END DECLARE SECTION;
2375 int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a;
2376 int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d;
2377 char *dtypes[MAXLISTDEPTH];
2380 lid = *(int *)argv[0];
2382 mid = *(int *)argv[2];
2383 /* if the member is not a direct member of the list, punt */
2384 EXEC SQL REPEATED SELECT list_id INTO :idummy FROM imembers
2385 WHERE list_id = :lid AND member_id = :mid
2386 AND member_type = :mtype AND direct = 1;
2387 if (ingres_errno) return(mr_errcode);
2388 if (sqlca.sqlcode == 100)
2389 return(MR_NO_MATCH);
2393 EXEC SQL DECLARE csr105 CURSOR FOR
2394 SELECT list_id, ref_count FROM imembers
2395 WHERE member_id = :lid AND member_type = 'LIST';
2396 EXEC SQL OPEN csr105;
2398 EXEC SQL FETCH csr105 INTO :id, :ref;
2399 if(sqlca.sqlcode!=0) break;
2401 ancestors[acount++] = id;
2402 if (acount >= MAXLISTDEPTH) break;
2404 EXEC SQL CLOSE csr105;
2407 if (acount >= MAXLISTDEPTH)
2408 return(MR_INTERNAL);
2409 descendants[0] = mid;
2414 if (!strcmp(mtype, "LIST")) {
2415 EXEC SQL DECLARE csr106 CURSOR FOR
2416 SELECT member_id, member_type, ref_count FROM imembers
2417 WHERE list_id = :mid;
2418 EXEC SQL OPEN csr106;
2420 EXEC SQL FETCH csr106 INTO :id, :dtype, :ref;
2421 if(sqlca.sqlcode!=0) break;
2424 dtypes[dcount] = "LIST";
2427 dtypes[dcount] = "USER";
2430 dtypes[dcount] = "STRING";
2433 dtypes[dcount] = "KERBEROS";
2440 descendants[dcount++] = id;
2441 if (dcount >= MAXLISTDEPTH) break;
2443 EXEC SQL CLOSE csr106;
2447 return(MR_INTERNAL);
2449 for (a = 0; a < acount; a++) {
2451 for (d = 0; d < dcount; d++) {
2452 mid = descendants[d];
2454 if (mid == lid && !strcmp(mtype, "LIST")) {
2455 return(MR_LISTLOOP);
2457 EXEC SQL REPEATED SELECT ref_count INTO :cnt FROM imembers
2458 WHERE list_id = :lid AND member_id = :mid AND member_type = :mtype;
2459 ref = aref[a] * dref[d];
2461 iargv[0] = (char *)lid;
2463 iargv[2] = (char *)mid;
2464 incremental_before("members", 0, iargv);
2465 EXEC SQL DELETE FROM imembers
2466 WHERE list_id = :lid AND member_id = :mid
2467 AND member_type= :mtype;
2468 incremental_clear_after();
2469 } else if (a == 0 && d == 0) {
2470 EXEC SQL UPDATE imembers
2471 SET ref_count = refcount - :ref, direct = 0
2472 WHERE list_id = :lid AND member_id = :mid
2473 AND member_type = :mtype;
2475 EXEC SQL UPDATE imembers
2476 SET ref_count=refcount-:ref
2477 WHERE list_id = :lid AND member_id = :mid
2478 AND member_type = :mtype;
2482 lid = *(int *)argv[0];
2483 entity = cl->entity;
2484 who = cl->client_id;
2485 EXEC SQL UPDATE list SET modtime = 'now', modby = :who, modwith = :entity
2486 WHERE list_id = :lid;
2487 if (ingres_errno) return(mr_errcode);
2492 /* get_ace_use - given a type and a name, return a type and a name.
2493 * The ace_type is one of "LIST", "USER", "RLIST", or "RUSER" in argv[0],
2494 * and argv[1] will contain the ID of the entity in question. The R*
2495 * types mean to recursively look at every containing list, not just
2496 * when the object in question is a direct member. On return, the
2497 * usage type will be one of LIST, SERVICE, FILESYS, QUOTA, QUERY, or ZEPHYR.
2500 int get_ace_use(q, argv, cl, action, actarg)
2508 EXEC SQL BEGIN DECLARE SECTION;
2510 int aid, listid, id;
2511 EXEC SQL END DECLARE SECTION;
2512 struct save_queue *sq, *sq_create();
2515 aid = *(int *)argv[1];
2516 if (!strcmp(atype, "LIST") || !strcmp(atype, "USER") ||
2517 !strcmp(atype, "KERBEROS")) {
2518 return(get_ace_internal(atype, aid, action, actarg));
2522 if (!strcmp(atype, "RLIST")) {
2523 sq_save_data(sq, aid);
2524 /* get all the list_id's of containing lists */
2525 EXEC SQL DECLARE csr107 CURSOR FOR
2526 SELECT list_id FROM imembers
2527 WHERE member_type='LIST' AND member_id = :aid;
2528 EXEC SQL OPEN csr107;
2530 EXEC SQL FETCH csr107 INTO :listid;
2531 if(sqlca.sqlcode != 0) break;
2532 sq_save_unique_data(sq, listid);
2534 EXEC SQL CLOSE csr107;
2535 /* now process each one */
2536 while (sq_get_data(sq, &id)) {
2537 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2542 if (!strcmp(atype, "RUSER")) {
2543 EXEC SQL DECLARE csr108 CURSOR FOR
2544 SELECT list_id FROM imembers
2545 WHERE member_type='USER' AND member_id = :aid;
2546 EXEC SQL OPEN csr108;
2548 EXEC SQL FETCH csr108 INTO :listid;
2549 if(sqlca.sqlcode != 0) break;
2550 sq_save_data(sq, listid);
2552 EXEC SQL CLOSE csr108;
2553 /* now process each one */
2554 while (sq_get_data(sq, &id)) {
2555 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2558 if (get_ace_internal("USER", aid, action, actarg) == MR_SUCCESS)
2562 if (!strcmp(atype, "RKERBERO")) {
2563 EXEC SQL DECLARE csr109 CURSOR FOR
2564 SELECT list_id FROM imembers
2565 WHERE member_type='KERBEROS' AND member_id = :aid;
2566 EXEC SQL OPEN csr109;
2568 EXEC SQL FETCH csr109 INTO :listid;
2569 if(sqlca.sqlcode != 0) break;
2570 sq_save_data(sq, listid);
2572 EXEC SQL CLOSE csr109;
2573 /* now process each one */
2574 while (sq_get_data(sq, &id)) {
2575 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2578 if (get_ace_internal("KERBEROS", aid, action, actarg) == MR_SUCCESS)
2583 if (ingres_errno) return(mr_errcode);
2584 if (!found) return(MR_NO_MATCH);
2589 /* This looks up a single list or user for ace use. atype must be "USER"
2590 * or "LIST", and aid is the ID of the corresponding object. This is used
2591 * by get_ace_use above.
2594 get_ace_internal(atype, aid, action, actarg)
2595 EXEC SQL BEGIN DECLARE SECTION;
2598 EXEC SQL END DECLARE SECTION;
2604 EXEC SQL BEGIN DECLARE SECTION;
2606 EXEC SQL END DECLARE SECTION;
2609 if (!strcmp(atype, "LIST")) {
2610 rargv[0] = "FILESYS";
2611 EXEC SQL DECLARE csr110 CURSOR FOR
2612 SELECT label FROM filesys
2613 WHERE owners = :aid;
2614 EXEC SQL OPEN csr110;
2616 EXEC SQL FETCH csr110 INTO :name;
2617 if(sqlca.sqlcode != 0) break;
2618 (*action)(2, rargv, actarg);
2621 EXEC SQL CLOSE csr110;
2624 EXEC SQL DECLARE csr111 CURSOR FOR
2625 SELECT capability FROM capacls
2626 WHERE list_id = :aid ;
2627 EXEC SQL OPEN csr111;
2629 EXEC SQL FETCH csr111 INTO :name ;
2630 if(sqlca.sqlcode != 0) break;
2631 (*action)(2, rargv, actarg);
2634 EXEC SQL CLOSE csr111;
2635 } else if (!strcmp(atype, "USER")) {
2636 rargv[0] = "FILESYS";
2637 EXEC SQL DECLARE csr112 CURSOR FOR
2638 SELECT label FROM filesys
2640 EXEC SQL OPEN csr112;
2642 EXEC SQL FETCH csr112 INTO :name ;
2643 if(sqlca.sqlcode != 0) break;
2644 (*action)(2, rargv, actarg);
2647 EXEC SQL CLOSE csr112;
2651 EXEC SQL DECLARE csr113 CURSOR FOR
2652 SELECT name FROM list
2653 WHERE acl_type = :atype AND acl_id = :aid;
2654 EXEC SQL OPEN csr113;
2656 EXEC SQL FETCH csr113 INTO :name;
2657 if(sqlca.sqlcode != 0) break;
2658 (*action)(2, rargv, actarg);
2661 EXEC SQL CLOSE csr113;
2663 rargv[0] = "SERVICE";
2664 EXEC SQL DECLARE csr114 CURSOR FOR
2665 SELECT name FROM servers
2666 WHERE acl_type = :atype AND acl_id = :aid;
2667 EXEC SQL OPEN csr114;
2669 EXEC SQL FETCH csr114 INTO :name;
2670 if(sqlca.sqlcode != 0) break;
2671 (*action)(2, rargv, actarg);
2674 EXEC SQL CLOSE csr114;
2676 rargv[0] = "HOSTACCESS";
2677 EXEC SQL DECLARE csr115 CURSOR FOR
2678 SELECT name FROM machine, hostaccess
2679 WHERE mach_id = hostaccess.mach_id AND hostaccess.acl_type = :atype
2680 AND hostaccess.acl_id = :aid;
2681 EXEC SQL OPEN csr115;
2683 EXEC SQL FETCH csr115 INTO :name;
2684 if(sqlca.sqlcode != 0) break;
2685 (*action)(2, rargv, actarg);
2688 EXEC SQL CLOSE csr115;
2690 rargv[0] = "ZEPHYR";
2691 EXEC SQL DECLARE csr116 CURSOR FOR
2692 SELECT class FROM zephyr
2693 WHERE zephyr.xmt_type = :atype AND zephyr.xmt_id = :aid
2694 OR zephyr.sub_type = :atype AND zephyr.sub_id = :aid
2695 OR zephyr.iws_type = :atype AND zephyr.iws_id = :aid
2696 OR zephyr.iui_type = :atype AND zephyr.iui_id = :aid;
2697 EXEC SQL OPEN csr116;
2699 EXEC SQL FETCH csr116 INTO :name;
2700 if(sqlca.sqlcode != 0) break;
2701 (*action)(2, rargv, actarg);
2704 EXEC SQL CLOSE csr116;
2706 if (!found) return(MR_NO_MATCH);
2711 /* get_lists_of_member - given a type and a name, return the name and flags
2712 * of all of the lists of the given member. The member_type is one of
2713 * "LIST", "USER", "STRING", "RLIST", "RUSER", or "RSTRING" in argv[0],
2714 * and argv[1] will contain the ID of the entity in question. The R*
2715 * types mean to recursively look at every containing list, not just
2716 * when the object in question is a direct member.
2719 int get_lists_of_member(q, argv, cl, action, actarg)
2726 int found = 0, direct = 1;
2728 EXEC SQL BEGIN DECLARE SECTION;
2730 int aid, listid, id;
2731 char name[33], active[5], public[5], hidden[5], maillist[5], grouplist[5];
2732 EXEC SQL END DECLARE SECTION;
2735 aid = *(int *)argv[1];
2736 if (!strcmp(atype, "RLIST")) {
2740 if (!strcmp(atype, "RUSER")) {
2744 if (!strcmp(atype, "RSTRING")) {
2748 if (!strcmp(atype, "RKERBEROS")) {
2757 rargv[4] = maillist;
2758 rargv[5] = grouplist;
2760 EXEC SQL DECLARE csr117a CURSOR FOR
2761 SELECT name, CHAR(active), CHAR(publicflg), CHAR(hidden),
2762 CHAR(maillist), CHAR(grouplist)
2763 FROM list l, imembers m
2764 WHERE l.list_id = m.list_id AND m.direct = 1
2765 AND m.member_type = :atype AND m.member_id = :aid;
2766 EXEC SQL OPEN csr117a;
2768 EXEC SQL FETCH csr117a
2769 INTO :name, :active, :public, :hidden, :maillist, :grouplist;
2770 if(sqlca.sqlcode != 0) break;
2771 (*action)(6, rargv, actarg);
2774 EXEC SQL CLOSE csr117a;
2776 EXEC SQL DECLARE csr117b CURSOR FOR
2777 SELECT name, CHAR(active), CHAR(publicflg), CHAR(hidden),
2778 CHAR(maillist), CHAR(grouplist)
2779 FROM list l, imembers m
2780 WHERE l.list_id = m.list_id
2781 AND m.member_type = :atype AND m.member_id = :aid;
2782 EXEC SQL OPEN csr117b;
2784 EXEC SQL FETCH csr117b
2785 INTO :name, :active, :public, :hidden, :maillist, :grouplist;
2786 if(sqlca.sqlcode != 0) break;
2787 (*action)(6, rargv, actarg);
2790 EXEC SQL CLOSE csr117b;
2793 if (ingres_errno) return(mr_errcode);
2794 if (!found) return(MR_NO_MATCH);
2799 /* qualified_get_lists: passed "TRUE", "FALSE", or "DONTCARE" for each of
2800 * the five flags associated with each list. It will return the name of
2801 * each list that meets the quailifications. It does this by building a
2802 * where clause based on the arguments, then doing a retrieve.
2805 static char *lflags[5] = { "active", "publicflg", "hidden", "maillist", "group" };
2807 int qualified_get_lists(q, argv, cl, action, actarg)
2814 return(qualified_get(q, argv, action, actarg, "l.list_id != 0",
2815 "l", "name", lflags));
2819 /* get_members_of_list - this gets only direct members */
2821 get_members_of_list(q, argv, cl, action, actarg)
2828 return(gmol_internal(q, argv, cl, action, actarg, 1));
2831 /* get_end_members_of_list - this gets direct or indirect members */
2833 get_end_members_of_list(q, argv, cl, action, actarg)
2840 return(gmol_internal(q, argv, cl, action, actarg, 0));
2843 /** gmol_internal - optimized query for retrieval of list members
2844 ** used by both get_members_of_list and get_end_members_of_list
2847 ** argv[0] - list_id
2850 ** - retrieve USER members, then LIST members, then STRING members
2853 gmol_internal(q, argv, cl, action, actarg, flag)
2861 EXEC SQL BEGIN DECLARE SECTION;
2862 int list_id, member_id, direct;
2863 char member_name[129], member_type[9];
2864 EXEC SQL END DECLARE SECTION;
2867 struct save_queue *sq;
2869 /* true/false flag indicates whether to display only direct members. */
2875 list_id = *(int *)argv[0];
2879 EXEC SQL DECLARE csr118 CURSOR FOR
2880 SELECT member_type, member_id FROM imembers
2881 WHERE list_id = :list_id AND direct > :direct;
2882 EXEC SQL OPEN csr118;
2884 EXEC SQL FETCH csr118 INTO :member_type, :member_id;
2885 if (sqlca.sqlcode != 0) break;
2888 sq_save_data(sq, ((int)member_type[0] << 24) | (member_id & 0xffffff));
2890 EXEC SQL CLOSE csr118;
2892 if (members <= 49) {
2893 targv[1] = malloc(0);
2894 while (sq_remove_data(sq, &member_id)) {
2895 switch (member_id >> 24) {
2898 id_to_name(member_id & 0xffffff, "USER", &targv[1]);
2899 (*action)(2, targv, actarg);
2903 id_to_name(member_id & 0xffffff, "LIST", &targv[1]);
2904 (*action)(2, targv, actarg);
2907 targv[0] = "STRING";
2908 id_to_name(member_id & 0xffffff, "STRING", &targv[1]);
2909 (*action)(2, targv, actarg);
2912 targv[0] = "KERBEROS";
2913 id_to_name(member_id & 0xffffff, "STRING", &targv[1]);
2914 (*action)(2, targv, actarg);
2918 return(MR_INTERNAL);
2927 targv[1] = member_name;
2929 EXEC SQL DECLARE csr119 CURSOR FOR
2930 SELECT users.login FROM users, imembers
2931 WHERE imembers.list_id = :list_id AND imembers.member_type = 'USER'
2932 AND imembers.member_id = users.users_id AND imembers.direct > :direct
2934 EXEC SQL OPEN csr119;
2936 EXEC SQL FETCH csr119 INTO :member_name;
2937 if(sqlca.sqlcode != 0) break;
2938 (*action)(2, targv, actarg);
2940 EXEC SQL CLOSE csr119;
2941 if (ingres_errno) return(mr_errcode);
2944 EXEC SQL DECLARE csr120 CURSOR FOR
2945 SELECT list.name FROM list, imembers
2946 WHERE imembers.list_id = :list_id AND imembers.member_type='LIST'
2947 AND imembers.member_id = list.list_id AND imembers.direct > :direct
2949 EXEC SQL OPEN csr120;
2951 EXEC SQL FETCH csr120 INTO :member_name;
2952 if(sqlca.sqlcode != 0) break;
2953 (*action)(2, targv, actarg);
2955 EXEC SQL CLOSE csr120;
2956 if (ingres_errno) return(mr_errcode);
2958 targv[0] = "STRING";
2959 EXEC SQL DECLARE csr121 CURSOR FOR
2960 SELECT strings.string FROM strings, imembers
2961 WHERE imembers.list_id = :list_id AND imembers.member_type='STRING'
2962 AND imembers.member_id = strings.string_id
2963 AND imembers.direct > :direct
2965 EXEC SQL OPEN csr121;
2967 EXEC SQL FETCH csr121 INTO :member_name;
2968 if(sqlca.sqlcode != 0) break;
2969 (*action)(2, targv, actarg);
2971 EXEC SQL CLOSE csr121;
2972 if (ingres_errno) return(mr_errcode);
2974 targv[0] = "KERBEROS";
2975 EXEC SQL DECLARE csr122 CURSOR FOR
2976 SELECT strings.string FROM strings, imembers
2977 WHERE imembers.list_id = :list_id AND imembers.member_type='KERBEROS'
2978 AND imembers.member_id = strings.string_id
2979 AND imembers.direct > :direct;
2981 EXEC SQL OPEN csr122;
2983 EXEC SQL FETCH csr122 INTO :member_name;
2984 if(sqlca.sqlcode != 0) break;
2985 (*action)(2, targv, actarg);
2987 EXEC SQL CLOSE csr122;
2988 if (ingres_errno) return(mr_errcode);
2994 /* count_members_of_list: this is a simple query, but it cannot be done
2995 * through the dispatch table.
2998 int count_members_of_list(q, argv, cl, action, actarg)
3005 EXEC SQL BEGIN DECLARE SECTION;
3007 EXEC SQL END DECLARE SECTION;
3008 char *rargv[1], countbuf[5];
3010 list = *(int *)argv[0];
3011 rargv[0] = countbuf;
3012 EXEC SQL REPEATED SELECT count (*) INTO :ct FROM imembers
3013 WHERE list_id = :list AND direct=1;
3014 if (ingres_errno) return(mr_errcode);
3015 sprintf(countbuf, "%d", ct);
3016 (*action)(1, rargv, actarg);
3021 /* qualified_get_server: passed "TRUE", "FALSE", or "DONTCARE" for each of
3022 * the three flags associated with each service. It will return the name of
3023 * each service that meets the quailifications. It does this by building a
3024 * where clause based on the arguments, then doing a retrieve.
3027 static char *sflags[3] = { "enable", "inprogress", "harderror" };
3029 int qualified_get_server(q, argv, cl, action, actarg)
3036 return(qualified_get(q, argv, action, actarg, "s.name != ''",
3037 "s", "name", sflags));
3041 /* generic qualified get routine, used by qualified_get_lists,
3042 * qualified_get_server, and qualified_get_serverhost.
3044 * start - a simple where clause, must not be empty
3045 * range - the name of the range variable
3046 * field - the field to return
3047 * flags - an array of strings, names of the flag variables
3050 int qualified_get(q, argv, action, actarg, start, range, field, flags)
3060 char name[33], qual[256];
3062 char *rargv[1], buf[32];
3064 strcpy(qual, start);
3065 for (i = 0; i < q->argc; i++) {
3066 if (!strcmp(argv[i], "TRUE")) {
3067 sprintf(buf, " and %s.%s != 0", range, flags[i]);
3068 (void) strcat(qual, buf);
3069 } else if (!strcmp(argv[i], "FALSE")) {
3070 sprintf(buf, " and %s.%s = 0", range, flags[i]);
3071 (void) strcat(qual, buf);
3075 rargv[0] = SQLDA->sqlvar[0].sqldata;
3076 sprintf(stmt_buf,"SELECT %s.%s FROM %s %s WHERE %s",q->rtable,field,q->rtable,q->rvar,qual);
3077 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3079 return(MR_INTERNAL);
3080 EXEC SQL DECLARE csr123 CURSOR FOR stmt;
3081 EXEC SQL OPEN csr123;
3083 EXEC SQL FETCH csr123 USING DESCRIPTOR :SQLDA;
3084 if(sqlca.sqlcode != 0) break;
3086 (*action)(1, rargv, actarg);
3088 EXEC SQL CLOSE csr123;
3089 if (ingres_errno) return(mr_errcode);
3091 return(MR_NO_MATCH);
3096 /* qualified_get_serverhost: passed "TRUE", "FALSE", or "DONTCARE" for each of
3097 * the five flags associated with each serverhost. It will return the name of
3098 * each service and host that meets the quailifications. It does this by
3099 * building a where clause based on the arguments, then doing a retrieve.
3102 static char *shflags[6] = { "service", "enable", "override", "success",
3103 "inprogress", "hosterror" };
3105 int qualified_get_serverhost(q, argv, cl, action, actarg)
3112 EXEC SQL BEGIN DECLARE SECTION;
3113 char sname[33], mname[33], qual[256];
3114 EXEC SQL END DECLARE SECTION;
3115 char *rargv[2], buf[32];
3118 /** the uppercase() function is INGRES-specific */
3119 sprintf(qual, "machine.mach_id = serverhosts.mach_id AND \
3120 serverhosts.service = uppercase('%s')",
3122 for (i = 1; i < q->argc; i++) {
3123 if (!strcmp(argv[i], "TRUE")) {
3124 sprintf(buf, " AND serverhosts.%s != 0", shflags[i]);
3126 } else if (!strcmp(argv[i], "FALSE")) {
3127 sprintf(buf, " AND serverhosts.%s = 0", shflags[i]);
3134 EXEC SQL DECLARE csr124 CURSOR FOR
3135 SELECT serverhosts.service, machine.name FROM serverhosts, machine
3137 EXEC SQL OPEN csr124;
3139 EXEC SQL FETCH csr124 INTO :sname, :mname;
3140 if(sqlca.sqlcode != 0) break;
3142 (*action)(2, rargv, actarg);
3144 EXEC SQL CLOSE csr124;
3146 if (ingres_errno) return(mr_errcode);
3148 return(MR_NO_MATCH);
3153 /* register_user - change user's login name and allocate a pobox, group,
3154 * filesystem, and quota for them. The user's status must start out as 0,
3155 * and is left as 2. Arguments are: user's UID, new login name, and user's
3156 * type for filesystem allocation (MR_FS_STUDENT, MR_FS_FACULTY,
3157 * MR_FS_STAFF, MR_FS_MISC).
3160 register_user(q, argv, cl)
3165 EXEC SQL BEGIN DECLARE SECTION;
3166 char *login, dir[65], *entity, directory[129], machname[33];
3167 int who, rowcount, mid, uid, users_id, flag, utype, nid, list_id, quota;
3168 int size, alloc, pid, ostatus, nstatus, gidval, fsidval, npidval;
3169 static int m_id = 0, def_quota = 0;
3170 EXEC SQL END DECLARE SECTION;
3171 char buffer[256], *aargv[3];
3173 entity = cl->entity;
3174 who = cl->client_id;
3176 uid = atoi(argv[0]);
3178 utype = atoi(argv[2]);
3181 EXEC SQL REPEATED SELECT users_id, status INTO :users_id, :ostatus
3183 WHERE uid = :uid AND (status=0 OR status=5 OR status=6);
3185 if (sqlca.sqlerrd[2] == 0)
3186 return(MR_NO_MATCH);
3187 if (sqlca.sqlerrd[2] > 1)
3188 return(MR_NOT_UNIQUE);
3190 /* check new login name */
3191 EXEC SQL REPEATED SELECT login INTO :cdummy FROM users
3192 WHERE login = LEFT(:login,SIZE(login)) AND users_id != :users_id;
3193 if (ingres_errno) return(mr_errcode);
3194 if (sqlca.sqlerrd[2] > 0) return(MR_IN_USE);
3195 EXEC SQL REPEATED SELECT name INTO :cdummy FROM list
3196 WHERE name = LEFT(:login,SIZE(name));
3197 if (ingres_errno) return(mr_errcode);
3198 if (sqlca.sqlerrd[2] > 0) return(MR_IN_USE);
3199 EXEC SQL REPEATED SELECT label INTO :cdummy FROM filesys
3200 WHERE label = LEFT(:login,SIZE(label));
3201 if (ingres_errno) return(mr_errcode);
3202 if (sqlca.sqlerrd[2] > 0) return(MR_IN_USE);
3203 com_err(whoami, 0, "login name OK");
3205 /* choose place for pobox, put in mid */
3206 EXEC SQL DECLARE csr130 CURSOR FOR
3207 SELECT sh.mach_id, m.name FROM serverhosts sh, machine m
3208 WHERE sh.service='POP' AND sh.mach_id=m.mach_id
3209 AND sh.value2 - sh.value1 =
3210 (SELECT MAX(value2 - value1) FROM serverhosts
3211 WHERE service = 'POP');
3212 EXEC SQL OPEN csr130;
3213 EXEC SQL FETCH csr130 INTO :mid, :machname;
3214 if (sqlca.sqlerrd[2] == 0) {
3215 EXEC SQL CLOSE csr130;
3216 if (ingres_errno) return(mr_errcode);
3217 return(MR_NO_POBOX);
3219 EXEC SQL CLOSE csr130;
3220 if (ingres_errno) return(mr_errcode);
3223 /* change login name, set pobox */
3224 sprintf(buffer, "users.users_id = %d", users_id);
3225 incremental_before("users", buffer, 0);
3227 if (ostatus == 5 || ostatus == 6)
3229 EXEC SQL REPEATED UPDATE users SET login = :login, status = :nstatus,
3230 modtime='now', modby = :who, modwith = :entity, potype='POP',
3231 pop_id = :mid, pmodtime='now', pmodby = :who, pmodwith = :entity
3232 WHERE users_id = :users_id;
3234 if (ingres_errno) return(mr_errcode);
3235 if (sqlca.sqlerrd[2] != 1)
3236 return(MR_INTERNAL);
3237 set_pop_usage(mid, 1);
3238 com_err(whoami, 0, "set login name to %s and pobox to %s", login,
3240 incremental_after("users", buffer, 0);
3242 /* create group list */
3243 if (set_next_object_id("gid", "list", 1))
3245 if (set_next_object_id("list_id", "list", 0))
3247 EXEC SQL REPEATED SELECT value INTO :list_id FROM numvalues
3248 WHERE name='list_id';
3249 if (ingres_errno) return(mr_errcode);
3250 if (sqlca.sqlerrd[2] != 1)
3251 return(MR_INTERNAL);
3252 incremental_clear_before();
3253 EXEC SQL SELECT value INTO :gidval FROM numvalues WHERE name = 'gid';
3254 EXEC SQL REPEATED INSERT INTO list
3255 (name, list_id, active, publicflg, hidden, maillist, grouplist,
3256 gid, description, acl_type, acl_id,
3257 modtime, modby, modwith)
3258 VALUES (:login, :list_id, 1, 0, 0, 0, 1,
3259 :gidval, 'User Group', 'USER', :users_id,
3260 'now', :who, :entity);
3261 if (ingres_errno) return(mr_errcode);
3262 if (sqlca.sqlerrd[2] != 1)
3263 return(MR_INTERNAL);
3264 sprintf(buffer, "list_id = %d", list_id);
3265 incremental_after("list", buffer, 0);
3266 aargv[0] = (char *) list_id;
3268 aargv[2] = (char *) users_id;
3269 incremental_clear_before();
3270 EXEC SQL REPEATED INSERT INTO imembers
3271 (list_id, member_type, member_id, ref_count, direct)
3272 VALUES (:list_id, 'USER', :users_id, 1, 1);
3273 if (ingres_errno) return(mr_errcode);
3274 if (sqlca.sqlerrd[2] != 1)
3275 return(MR_INTERNAL);
3276 incremental_after("members", 0, aargv);
3279 /* Cell Name (I know, it shouldn't be hard coded...) */
3280 strcpy(machname, "ATHENA.MIT.EDU");
3281 EXEC SQL SELECT mach_id INTO :m_id FROM machine
3282 WHERE name = :machname;
3285 /* create filesystem */
3286 if (set_next_object_id("filsys_id", "filesys", 0))
3288 incremental_clear_before();
3289 if (islower(login[0]) && islower(login[1])) {
3290 sprintf(directory, "/afs/athena.mit.edu/user/%c/%c/%s",
3291 login[0], login[1], login);
3293 sprintf(directory, "/afs/athena.mit.edu/user/other/%s", login);
3296 EXEC SQL SELECT value INTO :fsidval FROM numvalues
3297 WHERE numvalues.name='filsys_id';
3298 EXEC SQL REPEATED INSERT INTO filesys
3299 (filsys_id, phys_id, label, type, mach_id, name,
3300 mount, access, comments, owner, owners, createflg,
3301 lockertype, modtime, modby, modwith)
3303 (:fsidval, 0, :login, 'AFS', :m_id, :directory,
3304 '/mit/'+:login, 'w', 'User Locker', :users_id, :list_id, 1,
3305 'HOMEDIR', 'now', :who, :entity);
3307 if (ingres_errno) return(mr_errcode);
3308 if (sqlca.sqlerrd[2] != 1)
3309 return(MR_INTERNAL);
3310 sprintf(buffer,"fs.filsys_id = %d",fsidval);
3311 incremental_after("filesys", buffer, 0);
3314 if (def_quota == 0) {
3315 EXEC SQL REPEATED SELECT value INTO :quota FROM numvalues
3316 WHERE name='def_quota';
3317 if (ingres_errno) return(mr_errcode);
3318 if (sqlca.sqlerrd[2] != 1)
3319 return(MR_NO_QUOTA);
3321 incremental_clear_before();
3322 EXEC SQL REPEATED INSERT INTO quota
3323 (entity_id, filsys_id, type, quota, phys_id, modtime, modby, modwith)
3325 (0, :fsidval, 'ANY', :def_quota, 0, 'now', :who, :entity);
3326 if (ingres_errno) return(mr_errcode);
3327 if (sqlca.sqlerrd[2] != 1)
3328 return(MR_INTERNAL);
3332 sprintf(buffer, "q.entity_id = 0 and q.filsys_id = %d and q.type = 'ANY'", fsidval);
3333 incremental_after("quota", buffer, aargv);
3334 com_err(whoami, 0, "quota of %d assigned", def_quota);
3335 if (ingres_errno) return(mr_errcode);
3337 cache_entry(login, "USER", users_id);
3339 EXEC SQL REPEATED UPDATE tblstats SET updates=updates+1, modtime='now'
3340 WHERE table_name='users';
3341 EXEC SQL REPEATED UPDATE tblstats SET appends=appends+1, modtime='now'
3342 WHERE table_name='list' OR table_name='filesys' OR table_name='quota';
3343 if (ingres_errno) return(mr_errcode);
3349 /** set_pop_usage - incr/decr usage count for pop server in serverhosts talbe
3353 ** delta (will be +/- 1)
3356 ** - incr/decr value field in serverhosts table for pop/mach_id
3360 static int set_pop_usage(id, cnt)
3361 EXEC SQL BEGIN DECLARE SECTION;
3364 EXEC SQL END DECLARE SECTION;
3366 EXEC SQL REPEATED UPDATE serverhosts SET value1 = value1 + :cnt
3367 WHERE serverhosts.service = 'POP' AND serverhosts.mach_id = :id;
3369 if (ingres_errno) return(mr_errcode);
3375 /* Validation Routines */
3377 validate_row(q, argv, v)
3378 register struct query *q;
3380 register struct validate *v;
3382 EXEC SQL BEGIN DECLARE SECTION;
3386 EXEC SQL END DECLARE SECTION;
3388 /* build where clause */
3389 build_qual(v->qual, v->argc, argv, qual);
3391 if (log_flags & LOG_VALID)
3392 /* tell the logfile what we're doing */
3393 com_err(whoami, 0, "validating row: %s", qual);
3395 /* look for the record */
3396 sprintf(stmt_buf,"SELECT COUNT (*) FROM %s WHERE %s",q->rtable,qual);
3397 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3399 return(MR_INTERNAL);
3400 EXEC SQL DECLARE csr126 CURSOR FOR stmt;
3401 EXEC SQL OPEN csr126;
3402 EXEC SQL FETCH csr126 USING DESCRIPTOR :SQLDA;
3403 EXEC SQL CLOSE csr126;
3404 rowcount = *(int *)SQLDA->sqlvar[0].sqldata;
3406 if (ingres_errno) return(mr_errcode);
3407 if (rowcount == 0) return(MR_NO_MATCH);
3408 if (rowcount > 1) return(MR_NOT_UNIQUE);
3412 validate_fields(q, argv, vo, n)
3414 register char *argv[];
3415 register struct valobj *vo;
3418 register int status;
3423 if (log_flags & LOG_VALID)
3424 com_err(whoami, 0, "validating %s in %s: %s",
3425 vo->namefield, vo->table, argv[vo->index]);
3426 status = validate_name(argv, vo);
3430 if (log_flags & LOG_VALID)
3431 com_err(whoami, 0, "validating %s in %s: %s",
3432 vo->idfield, vo->table, argv[vo->index]);
3433 status = validate_id(q, argv, vo);
3437 if (log_flags & LOG_VALID)
3438 com_err(whoami, 0, "validating date: %s", argv[vo->index]);
3439 status = validate_date(argv, vo);
3443 if (log_flags & LOG_VALID)
3444 com_err(whoami, 0, "validating %s type: %s",
3445 vo->table, argv[vo->index]);
3446 status = validate_type(argv, vo);
3450 if (log_flags & LOG_VALID)
3451 com_err(whoami, 0, "validating typed data (%s): %s",
3452 argv[vo->index - 1], argv[vo->index]);
3453 status = validate_typedata(q, argv, vo);
3457 if (log_flags & LOG_VALID)
3458 com_err(whoami, 0, "validating rename %s in %s",
3459 argv[vo->index], vo->table);
3460 status = validate_rename(argv, vo);
3464 if (log_flags & LOG_VALID)
3465 com_err(whoami, 0, "validating chars: %s", argv[vo->index]);
3466 status = validate_chars(argv[vo->index]);
3474 status = lock_table(vo);
3478 status = convert_wildcards(argv[vo->index]);
3482 status = convert_wildcards_uppercase(argv[vo->index]);
3487 if (status != MR_EXISTS) return(status);
3491 if (ingres_errno) return(mr_errcode);
3496 /* validate_chars: verify that there are no illegal characters in
3497 * the string. Legal characters are printing chars other than
3498 * ", *, ?, \, [ and ].
3500 static int illegalchars[] = {
3501 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
3502 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
3503 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
3504 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
3505 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* : - O */
3506 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* P - _ */
3507 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
3508 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
3509 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3510 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3511 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3512 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3513 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3514 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3515 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3516 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3523 if (illegalchars[*s++])
3524 return(MR_BAD_CHAR);
3529 validate_id(q, argv, vo)
3532 register struct valobj *vo;
3534 EXEC SQL BEGIN DECLARE SECTION;
3535 char *name, *tbl, *namefield, *idfield;
3537 EXEC SQL END DECLARE SECTION;
3541 name = argv[vo->index];
3543 namefield = vo->namefield;
3544 idfield = vo->idfield;
3546 if ((!strcmp(tbl, "users") && !strcmp(namefield, "login")) ||
3547 !strcmp(tbl, "machine") ||
3548 !strcmp(tbl, "filesys") ||
3549 !strcmp(tbl, "list") ||
3550 !strcmp(tbl, "cluster") ||
3551 !strcmp(tbl, "strings")) {
3552 if (!strcmp(tbl, "machine"))
3553 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3554 status = name_to_id(name, tbl, &id);
3556 *(int *)argv[vo->index] = id;
3558 } else if (status == MR_NO_MATCH && !strcmp(tbl, "strings") &&
3559 (q->type == APPEND || q->type == UPDATE)) {
3560 EXEC SQL SELECT value INTO :id FROM numvalues
3561 WHERE name = 'strings_id';
3563 EXEC SQL UPDATE numvalues SET value = :id WHERE name = 'string_id';
3564 EXEC SQL INSERT INTO strings (string_id, string) VALUES (:id, :name);
3565 cache_entry(name, "STRING", id);
3566 *(int *)argv[vo->index] = id;
3568 } else if (status == MR_NO_MATCH || status == MR_NOT_UNIQUE)
3574 if (!strcmp(namefield, "uid")) {
3575 sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s = %s",idfield,tbl,namefield,name);
3577 sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s = '%s'",idfield,tbl,namefield,name);
3579 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3581 return(MR_INTERNAL);
3582 EXEC SQL DECLARE csr127 CURSOR FOR stmt;
3583 EXEC SQL OPEN csr127;
3585 EXEC SQL FETCH csr127 USING DESCRIPTOR :SQLDA;
3586 if(sqlca.sqlcode == 0) {
3588 EXEC SQL FETCH csr127 USING DESCRIPTOR :SQLDA;
3589 if(sqlca.sqlcode == 0) rowcount++;
3591 EXEC SQL CLOSE csr127;
3595 if (rowcount != 1) return(vo->error);
3596 bcopy(SQLDA->sqlvar[0].sqldata,argv[vo->index],sizeof(int));
3600 validate_name(argv, vo)
3602 register struct valobj *vo;
3604 EXEC SQL BEGIN DECLARE SECTION;
3605 char *name, *tbl, *namefield;
3607 EXEC SQL END DECLARE SECTION;
3610 name = argv[vo->index];
3612 namefield = vo->namefield;
3613 if (!strcmp(tbl, "servers") && !strcmp(namefield, "name")) {
3614 for (c = name; *c; c++)
3618 sprintf(stmt_buf,"SELECT DISTINCT COUNT(*) FROM %s WHERE %s.%s = '%s'",
3619 tbl,tbl,namefield,name);
3620 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3622 return(MR_INTERNAL);
3623 EXEC SQL DECLARE csr128 CURSOR FOR stmt;
3624 EXEC SQL OPEN csr128;
3625 EXEC SQL FETCH csr128 USING DESCRIPTOR :SQLDA;
3626 rowcount = *(int *)SQLDA->sqlvar[0].sqldata;
3627 EXEC SQL CLOSE csr128;
3629 if (ingres_errno) return(mr_errcode);
3630 return ((rowcount == 1) ? MR_EXISTS : vo->error);
3633 validate_date(argv, vo)
3637 EXEC SQL BEGIN DECLARE SECTION;
3641 EXEC SQL END DECLARE SECTION;
3643 idate = argv[vo->index];
3644 EXEC SQL SELECT interval('years',date(:idate)-date('today')) INTO :dd;
3646 if (sqlca.sqlcode != 0 || dd > 5.0) return(MR_DATE);
3651 validate_rename(argv, vo)
3655 EXEC SQL BEGIN DECLARE SECTION;
3656 char *name, *tbl, *namefield, *idfield;
3658 EXEC SQL END DECLARE SECTION;
3662 c = name = argv[vo->index];
3664 if (illegalchars[*c++])
3665 return(MR_BAD_CHAR);
3667 /* minor kludge to upcasify machine names */
3668 if (!strcmp(tbl, "machine"))
3669 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3670 namefield = vo->namefield;
3671 idfield = vo->idfield;
3674 if (!strcmp(argv[vo->index], argv[vo->index - 1]))
3676 sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s = LEFT('%s',SIZE(%s))",
3677 namefield,tbl,namefield,name,namefield);
3678 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3680 return(MR_INTERNAL);
3681 EXEC SQL DECLARE csr129 CURSOR FOR stmt;
3682 EXEC SQL OPEN csr129;
3683 EXEC SQL FETCH csr129 USING DESCRIPTOR :SQLDA;
3684 if(sqlca.sqlcode == 0) id=1; else id=0;
3685 EXEC SQL CLOSE csr129;
3687 if (ingres_errno) return(mr_errcode);
3693 status = name_to_id(name, tbl, &id);
3694 if (status == MR_NO_MATCH || id == *(int *)argv[vo->index - 1])
3701 validate_type(argv, vo)
3703 register struct valobj *vo;
3705 EXEC SQL BEGIN DECLARE SECTION;
3708 EXEC SQL END DECLARE SECTION;
3711 typename = vo->table;
3712 c = val = argv[vo->index];
3714 if (illegalchars[*c++])
3715 return(MR_BAD_CHAR);
3718 /* uppercase type fields */
3719 for (c = val; *c; c++) if (islower(*c)) *c = toupper(*c);
3721 EXEC SQL SELECT trans INTO :cdummy FROM alias
3722 WHERE name = :typename AND type='TYPE' AND trans = :val;
3723 if (ingres_errno) return(mr_errcode);
3724 return (sqlca.sqlerrd[2] ? MR_EXISTS : vo->error);
3727 /* validate member or type-specific data field */
3729 validate_typedata(q, argv, vo)
3730 register struct query *q;
3731 register char *argv[];
3732 register struct valobj *vo;
3734 EXEC SQL BEGIN DECLARE SECTION;
3737 char data_type[129];
3739 EXEC SQL END DECLARE SECTION;
3744 /* get named object */
3745 name = argv[vo->index];
3747 /* get field type string (known to be at index-1) */
3748 field_type = argv[vo->index-1];
3750 /* get corresponding data type associated with field type name */
3751 EXEC SQL SELECT trans INTO :data_type FROM alias
3752 WHERE name = :field_type AND type='TYPEDATA';
3753 if (ingres_errno) return(mr_errcode);
3754 if (sqlca.sqlerrd[2] != 1) return(MR_TYPE);
3756 /* now retrieve the record id corresponding to the named object */
3757 if (index(data_type, ' '))
3758 *index(data_type, ' ') = 0;
3759 if (!strcmp(data_type, "user")) {
3761 status = name_to_id(name, data_type, &id);
3762 if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
3764 if (status) return(status);
3765 } else if (!strcmp(data_type, "list")) {
3767 status = name_to_id(name, data_type, &id);
3768 if (status && status == MR_NOT_UNIQUE)
3770 if (status == MR_NO_MATCH) {
3771 /* if idfield is non-zero, then if argv[0] matches the string
3772 * that we're trying to resolve, we should get the value of
3773 * numvalues.[idfield] for the id.
3775 if (vo->idfield && !strcmp(argv[0], argv[vo->index])) {
3776 set_next_object_id(q->validate->object_id, q->rtable, 0);
3778 EXEC SQL REPEATED SELECT value INTO :id FROM numvalues
3780 if (sqlca.sqlerrd[2] != 1) return(MR_LIST);
3783 } else if (status) return(status);
3784 } else if (!strcmp(data_type, "machine")) {
3786 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3787 status = name_to_id(name, data_type, &id);
3788 if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
3790 if (status) return(status);
3791 } else if (!strcmp(data_type, "string")) {
3793 status = name_to_id(name, data_type, &id);
3794 if (status && status == MR_NOT_UNIQUE)
3796 if (status == MR_NO_MATCH) {
3797 if (q->type != APPEND && q->type != UPDATE) return(MR_STRING);
3798 EXEC SQL SELECT value INTO :id FROM numvalues WHERE name = 'strings_id';
3800 EXEC SQL UPDATE numvalues SET value = :id WHERE name = 'strings_id';
3801 EXEC SQL INSERT INTO strings (string_id, string) VALUES (:id, :name);
3802 cache_entry(name, "STRING", id);
3803 } else if (status) return(status);
3804 } else if (!strcmp(data_type, "none")) {
3810 /* now set value in argv */
3811 *(int *)argv[vo->index] = id;
3817 /* Lock the table named by the validation object */
3822 sprintf(stmt_buf,"UPDATE %s SET modtime='now' WHERE %s.%s = 0",
3823 vo->table,vo->table,vo->idfield);
3824 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
3825 if (ingres_errno) return(mr_errcode);
3826 if (sqlca.sqlerrd[2] != 1)
3833 /* Check the database at startup time. For now this just resets the
3834 * inprogress flags that the DCM uses.
3837 sanity_check_database()
3842 /* Dynamic SQL support routines */
3843 MR_SQLDA_T *mr_alloc_SQLDA()
3846 short *null_indicators;
3849 if((it=(MR_SQLDA_T *)malloc(sizeof(MR_SQLDA_T)))==NULL) {
3850 com_err(whoami, MR_NO_MEM, "setting up SQLDA");
3854 if((null_indicators=(short *)calloc(QMAXARGS,sizeof(short)))==NULL) {
3855 com_err(whoami, MR_NO_MEM, "setting up SQLDA null indicators");
3859 for(j=0; j<QMAXARGS; j++) {
3860 if((it->sqlvar[j].sqldata=malloc(sizeof(short)+QMAXARGSIZE))==NULL) {
3861 com_err(whoami, MR_NO_MEM, "setting up SQLDA variables");
3864 it->sqlvar[j].sqllen=QMAXARGSIZE;
3865 it->sqlvar[j].sqlind=null_indicators+j;
3866 null_indicators[j]=0;
3873 /* Use this after FETCH USING DESCRIPTOR one or more
3874 * result columns may contain NULLs. This routine is
3875 * not currently needed, since db/schema creates all
3876 * columns with a NOT NULL WITH DEFAULT clause.
3878 * This is currently dead flesh, since no Moira columns
3879 * allow null values; all use default values.
3881 mr_fix_nulls_in_SQLDA(da)
3884 register IISQLVAR *var;
3888 for(j=0, var=da->sqlvar; j<da->sqld; j++, var++) {
3889 switch(var->sqltype) {
3890 case -IISQ_CHA_TYPE:
3894 case -IISQ_INT_TYPE:
3896 intp=(int *)var->sqldata;
3904 /* prefetch_value():
3905 * This routine fetches an appropriate value from the numvalues table.
3906 * It is a little hack to get around the fact that SQL doesn't let you
3907 * do something like INSERT INTO table (foo) VALUES (other_table.bar).
3909 * It is called from the query table as (*v->pre_rtn)(q,Argv,cl) or
3910 * from within a setup_...() routine with the appropriate arguments.
3912 * Correct functioning of this routine may depend on the assumption
3913 * that this query is an APPEND.
3916 prefetch_value(q,argv,cl)
3921 EXEC SQL BEGIN DECLARE SECTION;
3922 char *name = q->validate->object_id;
3924 EXEC SQL END DECLARE SECTION;
3925 int status, limit, argc;
3927 /* set next object id, limiting it if necessary */
3928 if(!strcmp(name, "uid") || !strcmp(name, "gid"))
3929 limit = 1; /* So far as I know, this isn't needed. Just CMA. */
3932 if((status = set_next_object_id(name, q->rtable, limit)) != MR_SUCCESS)
3935 /* fetch object id */
3936 EXEC SQL SELECT value INTO :value FROM numvalues WHERE name=:name;
3937 if(ingres_errno) return(mr_errcode);
3938 if(sqlca.sqlerrd[2] != 1) return(MR_INTERNAL);
3940 argc = q->argc + q->vcnt; /* end of Argv for APPENDs */
3941 sprintf(argv[argc],"%d",value);
3946 /* prefetch_filesys():
3947 * Fetches the phys_id from filesys based on the filsys_id in argv[0].
3948 * Appends the filsys_id and the phys_id to the argv so they can be
3949 * referenced in an INSERT into a table other than filesys. Also
3950 * see comments at prefetch_value().
3952 * Assumes the existence of a row where filsys_id = argv[0], since a
3953 * filesys label has already been resolved to a filsys_id.
3955 prefetch_filesys(q,argv,cl)
3960 EXEC SQL BEGIN DECLARE SECTION;
3962 EXEC SQL END DECLARE SECTION;
3965 fid = *(int *)argv[0];
3966 EXEC SQL SELECT phys_id INTO :phid FROM filesys WHERE filsys_id = :fid;
3967 if(ingres_errno) return(mr_errcode);
3969 argc=q->argc+q->vcnt;
3970 sprintf(argv[argc++],"%d",fid);
3971 sprintf(argv[argc],"%d",phid);
3976 /* Convert normal Unix-style wildcards to SQL voodoo */
3977 convert_wildcards(arg)
3980 static char buffer[QMAXARGSIZE];
3981 register char *s, *d;
3983 for(d=buffer,s=arg;*s;s++) {
3985 case '*': *d++='%'; *d++='%'; break;
3986 case '?': *d++='_'; break;
3989 case ']': *d++='*'; *d++ = *s; break;
3990 case '%': *d++='*'; *d++='%'; *d++='%'; break;
3991 default: *d++ = *s; break;
3996 /* Copy back into argv */
4002 /* This version includes uppercase conversion, for things like gmac.
4003 * This is necessary because "LIKE" doesn't work with "uppercase()".
4004 * Including it in a wildcard routine saves making two passes over
4005 * the argument string.
4007 convert_wildcards_uppercase(arg)
4010 static char buffer[QMAXARGSIZE];
4011 register char *s, *d;
4013 for(d=buffer,s=arg;*s;s++) {
4015 case '*': *d++='%'; *d++='%'; break;
4016 case '?': *d++='_'; break;
4019 case ']': *d++='*'; *d++ = *s; break;
4020 case '%': *d++='*'; *d++='%'; *d++='%'; break;
4021 default: *d++=toupper(*s); break; /* This is the only diff. */
4026 /* Copy back into argv */
4032 /* eof:qsupport.dc */