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;
31 extern char stmt_buf[];
32 EXEC SQL END DECLARE SECTION;
34 /* Specialized Access Routines */
36 /* access_user - verify that client name equals specified login name
38 * - since field validation routines are called first, a users_id is
39 * now in argv[0] instead of the login name.
42 EXEC SQL WHENEVER SQLERROR CALL ingerr;
44 access_user(q, argv, cl)
49 if (cl->users_id != *(int *)argv[0])
57 /* access_login - verify that client name equals specified login name
59 * argv[0...n] contain search info. q->
62 access_login(q, argv, cl)
67 EXEC SQL BEGIN DECLARE SECTION;
70 EXEC SQL END DECLARE SECTION;
72 build_qual(q->qual, q->argc, argv, qual);
73 if (!strncmp(q->name,"get_user_account",strlen("get_user_account"))) {
74 EXEC SQL SELECT users_id INTO :id FROM users u, strings str WHERE :qual;
76 EXEC SQL SELECT users_id INTO :id FROM users u WHERE :qual;
79 if (sqlca.sqlerrd[2] != 1 || id != cl->users_id)
87 /* access_list - check access for most list operations
89 * Inputs: argv[0] - list_id
91 * argv[2] - member ID (only for queries "amtl" and "dmfl")
92 * argv[7] - group IID (only for query "ulis")
95 * - check that client is a member of the access control list
96 * - OR, if the query is add_member_to_list or delete_member_from_list
97 * and the list is public, allow access if client = member
100 access_list(q, argv, cl)
105 EXEC SQL BEGIN DECLARE SECTION;
106 int list_id, acl_id, flags, gid;
108 EXEC SQL END DECLARE SECTION;
110 int client_id, status;
112 list_id = *(int *)argv[0];
113 EXEC SQL SELECT acl_id, acl_type, gid, publicflg
114 INTO :acl_id, :acl_type, :gid, :flags
116 WHERE list_id = :list_id;
118 if (sqlca.sqlerrd[2] != 1)
121 /* parse client structure */
122 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
125 /* if amtl or dmfl and list is public allow client to add or delete self */
126 if (((!strcmp("amtl", q->shortname) && flags) ||
127 (!strcmp("dmfl", q->shortname))) &&
128 (!strcmp("USER", argv[1]))) {
129 if (*(int *)argv[2] == client_id) return(MR_SUCCESS);
130 /* if update_list, don't allow them to change the GID */
131 } else if (!strcmp("ulis", q->shortname)) {
132 if ((!strcmp(argv[7], UNIQUE_GID) && (gid != -1)) ||
133 (strcmp(argv[7], UNIQUE_GID) && (gid != atoi(argv[7]))))
137 /* check for client in access control list */
138 status = find_member(acl_type, acl_id, client_type, client_id, 0);
139 if (!status) return(MR_PERM);
145 /* access_visible_list - allow access to list only if it is not hidden,
146 * or if the client is on the ACL
148 * Inputs: argv[0] - list_id
149 * cl - client identifier
152 access_visible_list(q, argv, cl)
157 EXEC SQL BEGIN DECLARE SECTION;
158 int list_id, acl_id, flags ;
160 EXEC SQL END DECLARE SECTION;
162 int client_id, status;
164 list_id = *(int *)argv[0];
165 EXEC SQL SELECT hidden, acl_id, acl_type
166 INTO :flags, :acl_id, :acl_type
168 WHERE list_id = :list_id;
169 if (sqlca.sqlerrd[2] != 1)
174 /* parse client structure */
175 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
178 /* check for client in access control list */
179 status = find_member(acl_type, acl_id, client_type, client_id, 0);
187 /* access_vis_list_by_name - allow access to list only if it is not hidden,
188 * or if the client is on the ACL
190 * Inputs: argv[0] - list name
191 * cl - client identifier
194 access_vis_list_by_name(q, argv, cl)
199 EXEC SQL BEGIN DECLARE SECTION;
200 int acl_id, flags, rowcount;
201 char acl_type[9], *listname;
202 EXEC SQL END DECLARE SECTION;
204 int client_id, status;
207 EXEC SQL SELECT hidden, acl_id, acl_type INTO :flags, :acl_id, :acl_type
208 FROM list WHERE name = :listname;
210 rowcount=sqlca.sqlerrd[2];
218 /* parse client structure */
219 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
222 /* check for client in access control list */
223 status = find_member(acl_type, acl_id, client_type, client_id, 0);
231 /* access_member - allow user to access member of type "USER" and name matches
232 * username, or to access member of type "LIST" and list is one that user is
233 * on the acl of, or the list is visible.
236 access_member(q, argv, cl)
241 if (!strcmp(argv[0], "LIST") || !strcmp(argv[0], "RLIST"))
242 return(access_visible_list(q, &argv[1], cl));
244 if (!strcmp(argv[0], "USER") || !strcmp(argv[0], "RUSER")) {
245 if (cl->users_id == *(int *)argv[1])
249 if (!strcmp(argv[0], "KERBEROS") || !strcmp(argv[0], "RKERBERO")) {
250 if (cl->client_id == *(int *)argv[1])
258 /* access_qgli - special access routine for Qualified_get_lists. Allows
259 * access iff argv[0] == "TRUE" and argv[2] == "FALSE".
262 access_qgli(q, argv, cl)
267 if (!strcmp(argv[0], "TRUE") && !strcmp(argv[2], "FALSE"))
273 /* access_service - allow access if user is on ACL of service. Don't
274 * allow access if a wildcard is used.
277 access_service(q, argv, cl)
282 EXEC SQL BEGIN DECLARE SECTION;
284 char *name, acl_type[9];
285 EXEC SQL END DECLARE SECTION;
286 int client_id, status;
287 char *client_type, *c;
290 for(c=name;*c;c++) if(islower(*c)) *c = toupper(*c); /* uppercasify */
291 EXEC SQL SELECT acl_id, acl_type INTO :acl_id, :acl_type FROM servers
293 if (sqlca.sqlerrd[2] > 1)
296 /* parse client structure */
297 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
300 /* check for client in access control list */
301 status = find_member(acl_type, acl_id, client_type, client_id, 0);
302 if (!status) return(MR_PERM);
308 /* access_filesys - verify that client is owner or on owners list of filesystem
312 access_filesys(q, argv, cl)
317 EXEC SQL BEGIN DECLARE SECTION;
318 int users_id, list_id;
320 EXEC SQL END DECLARE SECTION;
321 int status, client_id;
325 EXEC SQL SELECT owner, owners INTO :users_id, :list_id FROM filesys
328 if (sqlca.sqlerrd[2] != 1)
330 if (users_id == cl->users_id)
332 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
334 status = find_member("LIST", list_id, client_type, client_id, 0);
345 /* Setup routine for add_user
347 * Inputs: argv[0] - login
352 * - if argv[1] == UNIQUE_UID then set argv[1] = next(uid)
353 * - if argv[0] == UNIQUE_LOGIN then set argv[0] = "#<uid>"
356 setup_ausr(q, argv, cl)
358 register char *argv[];
362 EXEC SQL BEGIN DECLARE SECTION;
364 EXEC SQL END DECLARE SECTION;
366 if (!strcmp(q->shortname, "uusr") || !strcmp(q->shortname, "uuac"))
370 if (!strcmp(argv[row], UNIQUE_UID) || atoi(argv[row]) == -1) {
371 if (set_next_object_id("uid", "users", 1))
372 return(MR_INGRES_ERR);
373 EXEC SQL SELECT value INTO :nuid FROM numvalues WHERE name = 'uid';
374 if (sqlca.sqlerrd[2] != 1)
376 sprintf(argv[row], "%d", nuid);
379 if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[row]) == -1) {
380 sprintf(argv[0], "#%s", argv[row]);
383 if((mr_errcode=prefetch_value(q,argv,cl))!=MR_SUCCESS)
390 /* setup_dusr - verify that the user is no longer being referenced
391 * and may safely be deleted.
394 int setup_dusr(q, argv)
398 EXEC SQL BEGIN DECLARE SECTION;
400 EXEC SQL END DECLARE SECTION;
402 id = *(int *)argv[0];
404 /* For now, only allow users to be deleted if their status is 0 */
405 EXEC SQL REPEATED SELECT status INTO :flag FROM users
406 WHERE users_id = :id;
407 if (flag != 0 && flag != 4)
410 EXEC SQL REPEATED DELETE FROM quota WHERE entity_id = :id AND type='USER';
411 EXEC SQL REPEATED DELETE FROM krbmap WHERE users_id = :id;
412 EXEC SQL REPEATED SELECT COUNT(member_id) INTO :cnt FROM imembers
413 WHERE member_id = :id AND member_type = 'USER';
416 EXEC SQL REPEATED SELECT COUNT(label) INTO :cnt FROM filesys
420 EXEC SQL REPEATED SELECT COUNT(name) INTO :cnt FROM list
421 WHERE acl_id = :id AND acl_type = 'USER';
424 EXEC SQL REPEATED SELECT COUNT(name) INTO :cnt FROM servers
425 WHERE acl_id = :id AND acl_type = 'USER';
428 EXEC SQL REPEATED SELECT COUNT(acl_id) INTO :cnt FROM hostaccess
429 WHERE acl_id = :id AND acl_type = 'USER';
438 /* setup_spop: verify that there is already a valid POP machine_id in the
439 * pop_id field. Also take care of keeping track of the post office usage.
441 int setup_spop(q, argv)
445 EXEC SQL BEGIN DECLARE SECTION;
448 EXEC SQL END DECLARE SECTION;
450 id = *(int *)argv[0];
451 EXEC SQL REPEATED SELECT potype, pop_id INTO :type, :mid FROM users
452 WHERE users_id = :id;
453 if(sqlca.sqlerrd[2] = 0)
455 EXEC SQL REPEATED SELECT mach_id INTO :mid FROM machine
456 WHERE mach_id = :mid;
457 if (sqlca.sqlerrd[2] = 0)
459 if (strcmp(strtrim(type), "POP"))
460 set_pop_usage(mid, 1);
465 /* setup_dpob: Take care of keeping track of the post office usage.
467 int setup_dpob(q, argv)
471 EXEC SQL BEGIN DECLARE SECTION;
474 EXEC SQL END DECLARE SECTION;
476 user = *(int *)argv[0];
477 EXEC SQL REPEATED SELECT potype, pop_id INTO :type, :id FROM users
478 WHERE users_id = :user;
479 if (ingres_errno) return(mr_errcode);
481 if (!strcmp(strtrim(type), "POP"))
482 set_pop_usage(id, -1);
487 /* setup_dmac - verify that the machine is no longer being referenced
488 * and may safely be deleted.
491 int setup_dmac(q, argv)
495 EXEC SQL BEGIN DECLARE SECTION;
497 EXEC SQL END DECLARE SECTION;
499 id = *(int *)argv[0];
500 EXEC SQL REPEATED SELECT COUNT(login) INTO :cnt FROM users
501 WHERE potype='POP' AND pop_id = :id;
504 EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM serverhosts
508 EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM nfsphys
512 EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM hostaccess
516 EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM printcap
520 EXEC SQL REPEATED SELECT COUNT(quotaserver) INTO :cnt FROM printcap
521 WHERE quotaserver = :id;
524 EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM palladium
529 EXEC SQL REPEATED DELETE FROM mcmap WHERE mach_id = :id;
530 if (ingres_errno) return(mr_errcode);
535 /* setup_dclu - verify that the cluster is no longer being referenced
536 * and may safely be deleted.
539 int setup_dclu(q, argv)
543 EXEC SQL BEGIN DECLARE SECTION;
545 EXEC SQL END DECLARE SECTION;
547 id = *(int *)argv[0];
548 EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM mcmap
552 EXEC SQL REPEATED SELECT COUNT(clu_id) INTO :cnt FROM svc
562 /* setup_alis - if argv[5] is non-zero and argv[6] is UNIQUE_ID, then allocate
563 * a new gid and put it in argv[6]. Otherwise if argv[6] is UNIQUE_ID but
564 * argv[5] is not, then remember that UNIQUE_ID is being stored by putting
565 * a -1 there. Remember that this is also used for ulis, with the indexes
566 * at 6 & 7. Also check that the list name does not contain uppercase
567 * characters, control characters, @, or :.
570 static int badlistchars[] = {
571 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
572 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
573 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
574 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, /* 0 - ? */
575 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
576 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, /* P - _ */
577 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
578 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
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,
584 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
585 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
586 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
589 int setup_alis(q, argv, cl)
594 EXEC SQL BEGIN DECLARE SECTION;
596 EXEC SQL END DECLARE SECTION;
601 if (!strcmp(q->shortname, "alis"))
603 else if (!strcmp(q->shortname, "ulis"))
606 for (p = (unsigned char *) argv[idx]; *p; p++)
607 if (badlistchars[*p])
610 if (!strcmp(argv[6 + idx], UNIQUE_GID) || atoi(argv[6 + idx]) == -1) {
611 if (atoi(argv[5 + idx])) {
612 if (set_next_object_id("gid", "list", 1))
613 return(MR_INGRES_ERR);
614 EXEC SQL REPEATED SELECT value INTO :ngid FROM numvalues
616 if (ingres_errno) return(mr_errcode);
617 sprintf(argv[6 + idx], "%d", ngid);
619 strcpy(argv[6 + idx], "-1");
623 if((mr_errcode=prefetch_value(q,argv,cl))!=MR_SUCCESS)
630 /* setup_dlis - verify that the list is no longer being referenced
631 * and may safely be deleted.
634 int setup_dlis(q, argv)
640 id = *(int *)argv[0];
641 sprintf(stmt_buf,"SELECT member_id FROM imembers WHERE member_id = %d AND member_type='LIST'",id);
642 if(ec=mr_select_any(stmt_buf)) {
643 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
646 sprintf(stmt_buf,"SELECT member_id FROM imembers WHERE list_id = %d",id);
647 if(ec=mr_select_any(stmt_buf)) {
648 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
651 sprintf(stmt_buf,"SELECT label FROM filesys WHERE owners = %d",id);
652 if(ec=mr_select_any(stmt_buf)) {
653 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
656 sprintf(stmt_buf,"SELECT tag FROM capacls WHERE list_id = %d",id);
657 if(ec=mr_select_any(stmt_buf)) {
658 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
661 sprintf(stmt_buf,"SELECT name FROM list WHERE acl_id = %d AND acl_type='LIST' AND list_id != %d",id,id);
662 if(ec=mr_select_any(stmt_buf)) {
663 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
666 sprintf(stmt_buf,"SELECT name FROM servers WHERE acl_id = %d AND acl_type='LIST'",id);
667 if(ec=mr_select_any(stmt_buf)) {
668 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
671 sprintf(stmt_buf,"SELECT entity_id FROM quota WHERE entity_id = %d AND type='GROUP'",id);
672 if(ec=mr_select_any(stmt_buf)) {
673 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
676 sprintf(stmt_buf,"SELECT acl_id FROM hostaccess WHERE acl_id = %d AND acl_type='LIST'",id);
677 if(ec=mr_select_any(stmt_buf)) {
678 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
681 sprintf(stmt_buf,"SELECT class FROM zephyr z \
682 WHERE z.xmt_type = 'LIST' AND z.xmt_id = %d \
683 OR z.sub_type = 'LIST' AND z.sub_id = %d \
684 OR z.iws_type = 'LIST' AND z.iws_id = %d \
685 OR z.iui_type = 'LIST' AND z.iui_id = %d",id,id,id,id);
686 if(ec=mr_select_any(stmt_buf)) {
687 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
694 /* setup_dsin - verify that the service is no longer being referenced
695 * and may safely be deleted.
698 int setup_dsin(q, argv)
702 EXEC SQL BEGIN DECLARE SECTION;
705 EXEC SQL END DECLARE SECTION;
707 sprintf(stmt_buf,"SELECT service FROM serverhosts WHERE service = UPPERCASE('%s')",argv[0]);
708 if(ec=mr_select_any(stmt_buf)) {
716 EXEC SQL SELECT inprogress INTO :ec FROM servers
717 WHERE name=UPPERCASE(:svrname);
727 /* setup_dshi - verify that the service-host is no longer being referenced
728 * and may safely be deleted.
731 int setup_dshi(q, argv)
735 EXEC SQL BEGIN DECLARE SECTION;
738 EXEC SQL END DECLARE SECTION;
741 id = *(int *)argv[1];
743 EXEC SQL SELECT inprogress INTO :ec FROM serverhosts
744 WHERE service=UPPERCASE(:svrname) AND mach_id = :id;
756 ** setup_add_filesys - verify existance of referenced file systems
768 ** * extract directory prefix from name
769 ** * verify mach_id/dir in nfsphys
770 ** * verify access in {r, w, R, W}
772 ** Side effect: sets variable var_phys_id to the ID of the physical
773 ** filesystem (nfsphys_id for NFS, 0 for RVD)
776 ** MR_NFS - specified directory not exported
777 ** MR_FILESYS_ACCESS - invalid filesys access
781 EXEC SQL BEGIN DECLARE SECTION;
782 static int var_phys_id;
783 EXEC SQL END DECLARE SECTION;
785 setup_afil(q, argv, cl)
792 EXEC SQL BEGIN DECLARE SECTION;
794 char ftype[32], *access;
795 EXEC SQL END DECLARE SECTION;
798 mach_id = *(int *)argv[2];
803 sprintf(ftype, "fs_access_%s", type);
804 EXEC SQL SELECT COUNT(trans) INTO :ok FROM alias
805 WHERE name = :ftype AND type = 'TYPE' and trans = :access;
806 if (ingres_errno) return(mr_errcode);
807 if (ok == 0) return(MR_FILESYS_ACCESS);
809 if((mr_errcode=prefetch_value(q,argv,cl))!=MR_SUCCESS)
812 if (!strcmp(type, "NFS"))
813 return (check_nfs(mach_id, name, access));
819 /* Verify the arguments, depending on the FStype. Also, if this is an
820 * NFS filesystem, then update any quotas for that filesystem to reflect
824 setup_ufil(q, argv, cl)
831 EXEC SQL BEGIN DECLARE SECTION;
832 int fid, total, who, ok;
833 char *entity, ftype[32], *access;
835 short int total_null;
836 EXEC SQL END DECLARE SECTION;
839 mach_id = *(int *)argv[3];
842 fid = *(int *)argv[0];
846 sprintf(ftype, "fs_access_%s", type);
847 EXEC SQL SELECT COUNT(trans) INTO :ok FROM alias
848 WHERE name = :ftype AND type='TYPE' AND trans = :access;
849 if (ingres_errno) return(mr_errcode);
850 if (ok == 0) return(MR_FILESYS_ACCESS);
852 EXEC SQL SELECT type INTO :ftype FROM filesys
853 WHERE filsys_id = :fid;
855 if (ingres_errno) return(mr_errcode);
857 if (!strcmp(type, "NFS")) {
858 status = check_nfs(mach_id, name, access);
859 EXEC SQL UPDATE quota SET phys_id = :var_phys_id
860 WHERE filsys_id = :fid;
861 if (ingres_errno) return(mr_errcode);
863 } else if (!strcmp(type, "AFS") && strcmp(ftype, "AFS")) {
865 EXEC SQL REPEATED DELETE FROM quota
866 WHERE type = 'ANY' AND filsys_id = :fid;
867 EXEC SQL SELECT SUM (quota) INTO :total:total_null FROM quota
868 WHERE filsys_id = :fid AND phys_id != 0;
869 if (ingres_errno) return(mr_errcode);
870 if (!total_null && (total != 0)) {
872 * append quota (quota = total, filsys_id = fid,
873 * phys_id = 0, entity_id = 0, type = "ANY",
874 * modtime = "now", modby = who, modwith = entity)
876 EXEC SQL INSERT INTO quota (quota, filsys_id, phys_id, entity_id,
877 type, modtime, modby, modwith)
878 VALUES (:total, :fid, 0, 0,
879 'ANY', 'now', :who, :entity) ;
880 if (ingres_errno) return(mr_errcode);
883 EXEC SQL UPDATE quota SET phys_id = 0 WHERE filsys_id = :fid;
884 if (ingres_errno) return(mr_errcode);
890 /* Find the NFS physical partition that the named directory is on.
891 * This is done by comparing the dir against the mount point of the
892 * partition. To make sure we get the correct match when there is
893 * more than one, we sort the query in reverse order by dir name.
896 check_nfs(mach_id, name, access)
897 EXEC SQL BEGIN DECLARE SECTION;
899 EXEC SQL END DECLARE SECTION;
903 EXEC SQL BEGIN DECLARE SECTION;
905 EXEC SQL END DECLARE SECTION;
912 EXEC SQL DECLARE csr101 CURSOR FOR
913 SELECT nfsphys_id, TRIM (dir) FROM nfsphys
914 WHERE mach_id = :mach_id
918 EXEC SQL OPEN csr101;
922 EXEC SQL FETCH csr101 INTO :var_phys_id, :dir;
923 if(sqlca.sqlcode != 0) break;
927 if (*cp1++ != *cp2) break;
935 EXEC SQL CLOSE csr101;
942 /* setup_dfil: free any quota records and fsgroup info associated with
943 * a filesystem when it is deleted. Also adjust the allocation numbers.
946 setup_dfil(q, argv, cl)
951 EXEC SQL BEGIN DECLARE SECTION;
952 int id, total, phys_id;
954 EXEC SQL END DECLARE SECTION;
956 id = *(int *)argv[0];
957 EXEC SQL REPEATED SELECT SUM (quota) INTO :total:none FROM quota
958 WHERE filsys_id = :id;
962 /** What if there are multiple phys_id's per f/s? (bad data) **/
963 EXEC SQL REPEATED SELECT phys_id INTO :phys_id FROM filesys
964 WHERE filsys_id = :id;
965 EXEC SQL REPEATED UPDATE nfsphys SET allocated = allocated - :total
966 WHERE nfsphys_id = :phys_id;
969 EXEC SQL REPEATED DELETE FROM quota WHERE filsys_id = :id;
971 EXEC SQL REPEATED DELETE FROM fsgroup WHERE filsys_id = :id;
972 EXEC SQL REPEATED DELETE FROM fsgroup WHERE group_id = :id;
973 if (ingres_errno) return(mr_errcode);
978 /* setup_dnfp: check to see that the nfs physical partition does not have
979 * any filesystems assigned to it before allowing it to be deleted.
982 setup_dnfp(q, argv, cl)
987 EXEC SQL BEGIN DECLARE SECTION;
990 EXEC SQL END DECLARE SECTION;
992 id = *(int *)argv[0];
994 EXEC SQL REPEATED SELECT fs.tid INTO :cnt FROM filesys fs, nfsphys np
995 WHERE fs.mach_id = :id AND fs.phys_id = np.nfsphys_id
996 AND np.mach_id = :id AND np.dir = :dir;
1005 /* setup_dqot: Remove allocation from nfsphys before deleting quota.
1006 * argv[0] = filsys_id
1007 * argv[1] = type if "update_quota" or "delete_quota"
1008 * argv[2 or 1] = users_id or list_id
1011 setup_dqot(q, argv, cl)
1016 EXEC SQL BEGIN DECLARE SECTION;
1017 int quota, fs, id, physid;
1019 EXEC SQL END DECLARE SECTION;
1021 fs = *(int *)argv[0];
1022 if (!strcmp(q->name, "update_quota") || !strcmp(q->name, "delete_quota")) {
1024 id = *(int *)argv[2];
1027 id = *(int *)argv[1];
1030 EXEC SQL REPEATED SELECT quota INTO :quota FROM quota
1031 WHERE type = :qtype AND entity_id = :id AND filsys_id = :fs;
1032 EXEC SQL REPEATED SELECT phys_id INTO :physid FROM filesys
1033 WHERE filsys_id = :fs;
1034 EXEC SQL REPEATED UPDATE nfsphys SET allocated = allocated - :quota
1035 WHERE nfsphys_id = :physid;
1037 if (ingres_errno) return(mr_errcode);
1042 /* setup_sshi: don't exclusive lock the machine table during
1043 * set_server_host_internal.
1045 /** Not allowed under (INGRES) SQL **/
1046 setup_sshi(q, argv, cl)
1053 EXEC SQL set lockmode session where readlock = system;
1060 /* setup add_kerberos_user_mapping: add the string to the string
1061 * table if necessary.
1064 setup_akum(q, argv, cl)
1069 EXEC SQL BEGIN DECLARE SECTION;
1072 EXEC SQL END DECLARE SECTION;
1075 if (name_to_id(name, "STRING", &id) != MR_SUCCESS) {
1076 if (q->type != APPEND) return(MR_STRING);
1077 id=add_string(name);
1078 cache_entry(name, "STRING", id);
1080 if (ingres_errno) return(mr_errcode);
1081 *(int *)argv[1] = id;
1087 /* FOLLOWUP ROUTINES */
1089 /* generic set_modtime routine. This takes the table name from the query,
1090 * and will update the modtime, modby, and modwho fields in the entry in
1091 * the table whose name field matches argv[0].
1094 set_modtime(q, argv, cl)
1099 char *name, *entity, *table;
1102 entity = cl->entity;
1103 who = cl->client_id;
1107 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);
1108 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
1113 /* generic set_modtime_by_id routine. This takes the table name from
1114 * the query, and the id name from the validate record,
1115 * and will update the modtime, modby, and modwho fields in the entry in
1116 * the table whose id matches argv[0].
1119 set_modtime_by_id(q, argv, cl)
1124 char *entity, *table, *id_name;
1127 entity = cl->entity;
1128 who = cl->client_id;
1130 id_name = q->validate->object_id;
1132 id = *(int *)argv[0];
1133 sprintf(stmt_buf,"UPDATE %s SET modtime = 'now', modby = %d, \
1134 modwith = '%s' WHERE %s.%s = %d",table,who,entity,table,id_name,id);
1135 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
1140 /* Sets the finger modtime on a user record. The users_id will be in argv[0].
1143 set_finger_modtime(q, argv, cl)
1148 EXEC SQL BEGIN DECLARE SECTION;
1151 EXEC SQL END DECLARE SECTION;
1153 entity = cl->entity;
1154 who = cl->client_id;
1155 users_id = *(int *)argv[0];
1157 EXEC SQL UPDATE users SET fmodtime='now', fmodby = :who, fmodwith = :entity
1158 WHERE users.users_id = :users_id;
1164 /* Sets the pobox modtime on a user record. The users_id will be in argv[0].
1167 set_pobox_modtime(q, argv, cl)
1172 EXEC SQL BEGIN DECLARE SECTION;
1175 EXEC SQL END DECLARE SECTION;
1177 entity = cl->entity;
1178 who = cl->client_id;
1179 users_id = *(int *)argv[0];
1181 EXEC SQL UPDATE users SET pmodtime='now', pmodby = :who, pmodwith = :entity
1182 WHERE users.users_id = :users_id;
1188 /* Like set_modtime, but uppercases the name first.
1191 set_uppercase_modtime(q, argv, cl)
1196 char *name, *entity, *table;
1199 entity = cl->entity;
1200 who = cl->client_id;
1204 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);
1205 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
1211 /* Sets the modtime on the machine whose mach_id is in argv[0]. This routine
1212 * is necessary for add_machine_to_cluster becuase the table that query
1213 * operates on is "mcm", not "machine".
1216 set_mach_modtime_by_id(q, argv, cl)
1221 EXEC SQL BEGIN DECLARE SECTION;
1224 EXEC SQL END DECLARE SECTION;
1226 entity = cl->entity;
1227 who = cl->client_id;
1228 id = *(int *)argv[0];
1229 EXEC SQL UPDATE machine SET modtime='now', modby = :who, modwith = :entity
1230 WHERE machine.mach_id = :id;
1236 /* Sets the modtime on the cluster whose mach_id is in argv[0]. This routine
1237 * is necessary for add_cluster_data and delete_cluster_data becuase the
1238 * table that query operates on is "svc", not "cluster".
1241 set_cluster_modtime_by_id(q, argv, cl)
1246 EXEC SQL BEGIN DECLARE SECTION;
1249 EXEC SQL END DECLARE SECTION;
1251 entity = cl->entity;
1252 who = cl->client_id;
1254 id = *(int *)argv[0];
1255 EXEC SQL UPDATE cluster SET modtime='now', modby = :who, modwith = :entity
1256 WHERE cluster.clu_id = :id;
1261 /* sets the modtime on the serverhost where the service name is in argv[0]
1262 * and the mach_id is in argv[1].
1265 set_serverhost_modtime(q, argv, cl)
1270 EXEC SQL BEGIN DECLARE SECTION;
1271 char *entity, *serv;
1273 EXEC SQL END DECLARE SECTION;
1275 entity = cl->entity;
1276 who = cl->client_id;
1279 id = *(int *)argv[1];
1280 EXEC SQL UPDATE serverhosts
1281 SET modtime = 'now', modby = :who, modwith = :entity
1282 WHERE service = :serv AND mach_id = :id;
1287 /* sets the modtime on the nfsphys where the mach_id is in argv[0] and the
1288 * directory name is in argv[1].
1291 set_nfsphys_modtime(q, argv, cl)
1296 EXEC SQL BEGIN DECLARE SECTION;
1299 EXEC SQL END DECLARE SECTION;
1301 entity = cl->entity;
1302 who = cl->client_id;
1304 id = *(int *)argv[0];
1306 EXEC SQL UPDATE nfsphys SET modtime = 'now', modby = :who, modwith = :entity
1307 WHERE dir = :dir AND mach_id = :id;
1312 /* sets the modtime on a filesystem, where argv[0] contains the filesys
1316 set_filesys_modtime(q, argv, cl)
1321 EXEC SQL BEGIN DECLARE SECTION;
1322 char *label, *entity;
1324 EXEC SQL END DECLARE SECTION;
1326 entity = cl->entity;
1327 who = cl->client_id;
1330 if (!strcmp(q->shortname, "ufil"))
1333 EXEC SQL UPDATE filesys SET modtime = 'now', modby = :who,
1334 modwith = :entity, phys_id = :var_phys_id
1335 WHERE label = LEFT(:label,SIZE(label));
1340 /* sets the modtime on a zephyr class, where argv[0] contains the class
1344 set_zephyr_modtime(q, argv, cl)
1349 EXEC SQL BEGIN DECLARE SECTION;
1350 char *class, *entity;
1352 EXEC SQL END DECLARE SECTION;
1354 entity = cl->entity;
1355 who = cl->client_id;
1359 EXEC SQL UPDATE zephyr SET modtime = 'now', modby = :who, modwith = :entity
1360 WHERE class = LEFT(:class,SIZE(class));
1366 /* fixes the modby field. This will be the second to last thing in the
1367 * argv, the argv length is determined from the query structure. It is
1368 * passed as a pointer to an integer. This will either turn it into a
1369 * username, or # + the users_id.
1371 followup_fix_modby(q, sq, v, action, actarg, cl)
1373 register struct save_queue *sq;
1375 register int (*action)();
1376 register int actarg;
1380 char **argv, *malloc();
1384 while (sq_get_data(sq, &argv)) {
1387 status = id_to_name(id, "USER", &argv[i]);
1389 status = id_to_name(-id, "STRING", &argv[i]);
1390 if (status && status != MR_NO_MATCH)
1392 (*action)(q->vcnt, argv, actarg);
1393 for (j = 0; j < q->vcnt; j++)
1402 /* After retrieving a user account, fix the modby field and signature.
1403 * The modby field is the second to last thing in the
1404 * argv, the argv length is determined from the query structure. It is
1405 * passed as a pointer to an integer. This will either turn it into a
1406 * username, or # + the users_id. Only "gua*" queries have a signature,
1407 * these are ones with U_END return values. "gub*" queries also use this
1408 * routine but don't have a signature.
1410 followup_guax(q, sq, v, action, actarg, cl)
1412 register struct save_queue *sq;
1414 register int (*action)();
1415 register int actarg;
1419 char **argv, *malloc();
1421 unsigned char sigbuf[256];
1424 EXEC SQL BEGIN DECLARE SECTION;
1427 varchar struct { short data_size; char data_buf[257];} rsig;
1428 EXEC SQL END DECLARE SECTION;
1433 while (sq_get_data(sq, &argv)) {
1435 com_err(whoami, 0, "argv[SIGNATURE] = \"%s\"", argv[U_SIGNATURE]);
1439 status = id_to_name(id, "USER", &argv[i]);
1441 status = id_to_name(-id, "STRING", &argv[i]);
1442 if (status && status != MR_NO_MATCH)
1445 if (q->vcnt == U_END && strlen(argv[U_SIGNATURE])) {
1446 login = argv[U_NAME];
1447 EXEC SQL REPEATED SELECT signature, sigdate, sigwho
1448 INTO :rsig, :timestamp, :who FROM users
1449 WHERE login = :login;
1450 /** What about (INGRES) error handling? **/
1452 status = id_to_name(who, "STRING", &kname);
1453 si.timestamp = timestamp;
1454 si.SigInfoVersion = 0; /* XXXXX this isn't used */
1455 kname_parse(si.pname, si.pinst, si.prealm, kname);
1457 rsig.data_buf[rsig.data_size] = 0;
1458 si.rawsig = (unsigned char *)strsave(rsig.data_buf);
1459 if (log_flags & LOG_GDSS)
1460 com_err(whoami, 0, "rawsig length = %d, sig=\"%s\"", strlen(si.rawsig), si.rawsig);
1461 GDSS_Recompose(&si, sigbuf);
1463 free(argv[U_SIGNATURE]);
1464 argv[U_SIGNATURE] = strsave(sigbuf);
1465 if (log_flags & LOG_GDSS)
1466 com_err(whoami, 0, "generated signature length %d", strlen(sigbuf));
1469 (*action)(q->vcnt, argv, actarg);
1470 for (j = 0; j < q->vcnt; j++)
1480 ** followup_ausr - add finger and pobox entries, set_user_modtime
1483 ** argv[0] - login (add_user)
1484 ** argv[3] - last name
1485 ** argv[4] - first name
1486 ** argv[5] - middle name
1490 followup_ausr(q, argv, cl)
1495 EXEC SQL BEGIN DECLARE SECTION;
1496 int who, status, id;
1497 char *login, *entity, *src, *dst, *name;
1499 EXEC SQL END DECLARE SECTION;
1501 char databuf[32], *kname_unparse();
1502 EXEC SQL BEGIN DECLARE SECTION;
1504 int sigwho, timestamp;
1505 EXEC SQL END DECLARE SECTION;
1509 /* build fullname */
1510 if (strlen(argv[4]) && strlen(argv[5]))
1511 sprintf(fullname, "%s %s %s", argv[4], argv[5], argv[3]);
1512 else if (strlen(argv[4]))
1513 sprintf(fullname, "%s %s", argv[4], argv[3]);
1515 sprintf(fullname, "%s", argv[3]);
1518 if (q->vcnt == U_END && *argv[U_SIGNATURE]) {
1519 /* unquote ' chars in signature */
1520 for (dst = src = argv[U_SIGNATURE]; *src; ) {
1526 sprintf(databuf, "%s:%s", argv[U_NAME], argv[U_MITID]);
1527 /* skip bytes for timestamp & kname */
1528 si.rawsig = (unsigned char *) rawsig;
1529 status = GDSS_Verify(databuf, strlen(databuf), argv[U_SIGNATURE], &si);
1530 if (strlen(rawsig) > mr_sig_length) {
1531 com_err(whoami, 0, "GDSS signature would be truncated."); /** untested **/
1532 return(MR_INTERNAL);
1535 name = kname_unparse(si.pname, si.pinst, si.prealm);
1536 status = name_to_id(name, "STRING", &sigwho);
1537 if (status == MR_NO_MATCH) {
1538 sigwho=add_string(name);
1541 timestamp = si.timestamp;
1543 if (log_flags & LOG_GDSS)
1544 hex_dump(argv[U_SIGNATURE]);
1545 return(gdss2et(status));
1555 who = cl->client_id;
1556 entity = cl->entity;
1558 /* create finger entry, pobox & set modtime on user */
1560 EXEC SQL REPEATED UPDATE users
1561 SET modtime='now', modby=:who, modwith = :entity,
1562 fullname = :fullname, affiliation = type,
1563 signature = :rawsig, sigdate = :timestamp, sigwho = :sigwho,
1564 fmodtime='now', fmodby = :who, fmodwith = :entity,
1565 potype='NONE', pmodtime='now', pmodby = :who, pmodwith = :entity
1566 WHERE login = :login;
1568 EXEC SQL REPEATED UPDATE users
1569 SET modtime='now', modby=:who, modwith = :entity,
1570 fullname = :fullname, affiliation = type,
1571 fmodtime='now', fmodby = :who, fmodwith = :entity,
1572 potype='NONE', pmodtime='now', pmodby = :who, pmodwith = :entity
1573 WHERE login = :login;
1581 ** followup_uusr - do signature, set_user_modtime
1584 ** argv[0] - login (add_user)
1585 ** argv[U_SIGNATURE] - sig
1589 followup_uuac(q, argv, cl)
1594 EXEC SQL BEGIN DECLARE SECTION;
1595 int who, status, id;
1596 char *entity, *name, *src, *dst;
1597 EXEC SQL END DECLARE SECTION;
1599 char databuf[32], *kname_unparse();
1600 EXEC SQL BEGIN DECLARE SECTION;
1603 int sigwho, timestamp;
1604 EXEC SQL END DECLARE SECTION;
1608 id = *(int *)argv[0];
1609 who = cl->client_id;
1610 entity = cl->entity;
1613 if (q->vcnt == U_MODTIME && *argv[U_SIGNATURE + 1]) {
1614 /* unquote ' chars in signature */
1615 for (dst = src = argv[U_SIGNATURE+1]; *src; ) {
1622 status = id_to_name(id, "USER", &login);
1623 sprintf(databuf, "%s:%s", login, argv[U_MITID+1]);
1625 /* skip bytes for timestamp & kname */
1626 si.rawsig = (unsigned char *) rawsig;
1628 com_err(whoami, 0, "verifying sig");
1630 status = GDSS_Verify(databuf, strlen(databuf), argv[U_SIGNATURE+1], &si);
1632 com_err(whoami, 0, "verified");
1634 if (strlen(rawsig) > mr_sig_length) {
1635 com_err(whoami, 0, "GDSS signature would be truncated."); /** untested **/
1636 return(MR_INTERNAL);
1639 name = kname_unparse(si.pname, si.pinst, si.prealm);
1640 status = name_to_id(name, "STRING", &sigwho);
1641 if (status == MR_NO_MATCH) {
1642 sigwho=add_string(name);
1645 timestamp = si.timestamp;
1647 if (log_flags & LOG_GDSS)
1648 hex_dump(argv[U_SIGNATURE+1]);
1649 return(gdss2et(status));
1658 /* create finger entry, pobox & set modtime on user */
1661 EXEC SQL REPEATED UPDATE users SET modtime='now', modby = :who, modwith = :entity,
1662 signature = :rawsig, sigdate = :timestamp, sigwho = :sigwho
1663 WHERE users_id = :id;
1665 EXEC SQL REPEATED UPDATE users SET modtime='now', modby = :who, modwith = :entity
1666 WHERE users_id = :id;
1672 /* followup_gpob: fixes argv[2] based on the IDs currently there and the
1673 * type in argv[1]. Then completes the upcall to the user.
1675 * argv[2] is of the form "123:234" where the first integer is the machine
1676 * ID if it is a pop box, and the second is the string ID if it is an SMTP
1677 * box. argv[1] should be "POP", "SMTP", or "NONE". Boxes of type NONE
1681 followup_gpob(q, sq, v, action, actarg, cl)
1682 register struct query *q;
1683 register struct save_queue *sq;
1684 register struct validate *v;
1685 register int (*action)();
1689 char **argv, *index();
1691 int mid, sid, status, i;
1694 while (sq_get_data(sq, &argv)) {
1695 mr_trim_args(2, argv);
1697 p = index(argv[2], ':');
1699 mid = atoi(argv[2]);
1702 if (!strcmp(ptype, "POP")) {
1703 status = id_to_name(mid, "MACHINE", &argv[2]);
1704 if (status == MR_NO_MATCH)
1706 } else if (!strcmp(ptype, "SMTP")) {
1707 status = id_to_name(sid, "STRING", &argv[2]);
1708 if (status == MR_NO_MATCH)
1710 } else /* ptype == "NONE" */ {
1713 if (status) return(status);
1715 if (!strcmp(q->shortname, "gpob")) {
1716 sid = atoi(argv[4]);
1718 status = id_to_name(sid, "USER", &argv[4]);
1720 status = id_to_name(-sid, "STRING", &argv[4]);
1722 if (status && status != MR_NO_MATCH) return(status);
1724 (*action)(q->vcnt, argv, actarg);
1726 /* free saved data */
1727 for (i = 0; i < q->vcnt; i++)
1733 return (MR_SUCCESS);
1737 /* followup_glin: fix the ace_name in argv[8]. argv[7] will contain the
1738 * ace_type: "LIST", "USER", or "NONE". Decode the id in argv[8] into the
1739 * proper name based on the type, and repace that string in the argv.
1740 * Also fixes the modby field by called followup_fix_modby.
1743 followup_glin(q, sq, v, action, actarg, cl)
1744 register struct query *q;
1745 register struct save_queue *sq;
1746 register struct validate *v;
1747 register int (*action)();
1751 char **argv, *malloc(), *realloc(), *type;
1752 int id, i, idx, status;
1755 if (!strcmp(q->shortname, "gsin"))
1758 while (sq_get_data(sq, &argv)) {
1759 mr_trim_args(q->vcnt, argv);
1761 id = atoi(argv[i = q->vcnt - 2]);
1763 status = id_to_name(id, "USER", &argv[i]);
1765 status = id_to_name(-id, "STRING", &argv[i]);
1766 if (status && status != MR_NO_MATCH)
1769 id = atoi(argv[idx]);
1770 type = argv[idx - 1];
1772 if (!strcmp(type, "LIST")) {
1773 status = id_to_name(id, "LIST", &argv[idx]);
1774 } else if (!strcmp(type, "USER")) {
1775 status = id_to_name(id, "USER", &argv[idx]);
1776 } else if (!strcmp(type, "KERBEROS")) {
1777 status = id_to_name(id, "STRING", &argv[idx]);
1778 } else if (!strcmp(type, "NONE")) {
1781 argv[idx] = strsave("NONE");
1785 argv[idx] = strsave("???");
1787 if (status && status != MR_NO_MATCH)
1790 if (!strcmp(q->shortname, "glin") && atoi(argv[6]) == -1) {
1791 argv[6] = realloc(argv[6], strlen(UNIQUE_GID) + 1);
1792 strcpy(argv[6], UNIQUE_GID);
1796 (*action)(q->vcnt, argv, actarg);
1798 /* free saved data */
1799 for (i = 0; i < q->vcnt; i++)
1805 return (MR_SUCCESS);
1809 /* followup_gqot: Fix the entity name, directory name & modby fields
1810 * argv[0] = filsys_id
1812 * argv[2] = entity_id
1813 * argv[3] = ascii(quota)
1816 followup_gqot(q, sq, v, action, actarg, cl)
1818 register struct save_queue *sq;
1820 register int (*action)();
1821 register int actarg;
1825 char **argv, *malloc();
1826 EXEC SQL BEGIN DECLARE SECTION;
1829 EXEC SQL END DECLARE SECTION;
1832 if (!strcmp(q->name, "get_quota") ||
1833 !strcmp(q->name, "get_quota_by_filesys"))
1837 while (sq_get_data(sq, &argv)) {
1839 switch (argv[1][0]) {
1841 status = id_to_name(atoi(argv[2]), "USER", &argv[2]);
1845 status = id_to_name(atoi(argv[2]), "LIST", &argv[2]);
1849 argv[2] = strsave("system:anyuser");
1853 argv[2] = malloc(8);
1854 sprintf(argv[2], "%d", id);
1857 id = atoi(argv[idx]);
1859 argv[idx] = malloc(256);
1863 EXEC SQL REPEATED SELECT name INTO :name FROM filesys
1864 WHERE label = :label;
1866 EXEC SQL REPEATED SELECT dir INTO :name FROM nfsphys
1867 WHERE nfsphys_id = :id;
1869 if (sqlca.sqlerrd[2] != 1) {
1870 sprintf(argv[idx], "#%d", id);
1873 id = atoi(argv[idx+3]);
1875 status = id_to_name(id, "USER", &argv[idx+3]);
1877 status = id_to_name(-id, "STRING", &argv[idx+3]);
1878 if (status && status != MR_NO_MATCH)
1880 (*action)(q->vcnt, argv, actarg);
1881 for (j = 0; j < q->vcnt; j++)
1890 /* followup_aqot: Add allocation to nfsphys after creating quota.
1891 * argv[0] = filsys_id
1892 * argv[1] = type if "add_quota" or "update_quota"
1894 * argv[3 or 2] = ascii(quota)
1897 followup_aqot(q, argv, cl)
1902 EXEC SQL BEGIN DECLARE SECTION;
1903 int quota, id, fs, who, physid;
1904 char *entity, *qtype, *table_name;
1905 EXEC SQL END DECLARE SECTION;
1910 table_name=q->rtable;
1911 fs = *(int *)argv[0];
1912 EXEC SQL REPEATED SELECT phys_id INTO :physid FROM filesys
1913 WHERE filsys_id = :fs;
1917 if (!strcmp(q->shortname, "aqot") || !strcmp(q->shortname, "uqot")) {
1919 id = *(int *)argv[2];
1920 quota = atoi(argv[3]);
1921 sprintf(incr_qual,"q.filsys_id = %d",fs);
1924 id = *(int *)argv[1];
1925 quota = atoi(argv[2]);
1926 sprintf(incr_qual,"q.filsys_id=%d AND q.type='%s' AND q.entity_id=%d",
1930 /* quota case of incremental_{before|after} only looks at slot 1 */
1933 /* Follows one of many possible gross hacks to fix these particular
1934 * conflicts between what is possible in the query table and what
1935 * is possible in SQL.
1937 if(q->type==APPEND) {
1938 incremental_clear_before();
1939 EXEC SQL INSERT INTO quota
1940 (filsys_id, type, entity_id, quota, phys_id)
1941 VALUES (:fs, :qtype, :id, :quota, :physid);
1942 incremental_after(table_name, incr_qual, incr_argv);
1944 incremental_before(table_name, incr_qual, incr_argv);
1945 EXEC SQL UPDATE quota SET quota = :quota
1946 WHERE filsys_id = :fs AND type = :qtype AND entity_id = :id;
1947 status = mr_errcode;
1948 incremental_after(table_name, incr_qual, incr_argv);
1953 flush_name(argv[0], q->rtable);
1954 if(q->type==APPEND) {
1955 EXEC SQL UPDATE tblstats SET appends = appends + 1, modtime = 'now'
1956 WHERE table_name = :table_name;
1958 EXEC SQL UPDATE tblstats SET updates = updates + 1, modtime = 'now'
1959 WHERE table_name = :table_name;
1962 /* Proceed with original followup */
1963 who = cl->client_id;
1964 entity = cl->entity;
1966 EXEC SQL REPEATED UPDATE quota
1967 SET modtime = 'now', modby = :who, modwith = :entity
1968 WHERE filsys_id = :fs and type = :qtype and entity_id = :id;
1969 EXEC SQL REPEATED UPDATE nfsphys SET allocated = allocated + :quota
1970 WHERE nfsphys_id = :physid;
1971 if (ingres_errno) return(mr_errcode);
1976 /* Necessitated by the requirement of a correlation name by the incremental
1977 * routines, since query table deletes don't provide one.
1979 followup_dqot(q,argv,cl)
1987 EXEC SQL BEGIN DECLARE SECTION;
1990 EXEC SQL END DECLARE SECTION;
1992 fs = *(int *)argv[0];
1993 if (!strcmp(q->shortname, "dqot")) {
1995 id = *(int *)argv[2];
1998 id = *(int *)argv[1];
2000 sprintf(incr_qual,"q.filsys_id=%d AND q.type='%s' AND q.entity_id=%d",
2003 /* quota case of incremental_{before|after} only looks at slot 1 */
2006 incremental_before(q->rtable, incr_qual, incr_argv);
2007 EXEC SQL DELETE FROM quota q WHERE :incr_qual;
2008 incremental_clear_after();
2012 flush_name(argv[0], q->rtable);
2014 tblname = q->rtable;
2015 EXEC SQL UPDATE tblstats SET deletes = deletes + 1, modtime = 'now'
2016 WHERE table_name = :tblname;
2021 followup_gpce(q, sq, v, action, actarg, cl)
2023 register struct save_queue *sq;
2025 register int (*action)();
2026 register int actarg;
2030 char **argv, *malloc();
2034 while (sq_get_data(sq, &argv)) {
2035 id = atoi(argv[PCAP_QSERVER]);
2036 status = id_to_name(id, "MACHINE", &argv[PCAP_QSERVER]);
2037 if (status) return (status);
2040 status = id_to_name(id, "USER", &argv[i]);
2042 status = id_to_name(-id, "STRING", &argv[i]);
2043 if (status && status != MR_NO_MATCH)
2045 (*action)(q->vcnt, argv, actarg);
2046 for (j = 0; j < q->vcnt; j++)
2058 followup_gzcl(q, sq, v, action, actarg, cl)
2059 register struct query *q;
2060 register struct save_queue *sq;
2061 register struct validate *v;
2062 register int (*action)();
2069 while (sq_get_data(sq, &argv)) {
2070 mr_trim_args(q->vcnt, argv);
2072 id = atoi(argv[i = q->vcnt - 2]);
2074 status = id_to_name(id, "USER", &argv[i]);
2076 status = id_to_name(-id, "STRING", &argv[i]);
2077 if (status && status != MR_NO_MATCH)
2080 for (i = 1; i < 8; i+=2) {
2081 id = atoi(argv[i+1]);
2082 if (!strcmp(argv[i], "LIST")) {
2083 status = id_to_name(id, "LIST", &argv[i+1]);
2084 } else if (!strcmp(argv[i], "USER")) {
2085 status = id_to_name(id, "USER", &argv[i+1]);
2086 } else if (!strcmp(argv[i], "KERBEROS")) {
2087 status = id_to_name(id, "STRING", &argv[i+1]);
2088 } else if (!strcmp(argv[i], "NONE")) {
2091 argv[i+1] = strsave("NONE");
2095 argv[i+1] = strsave("???");
2097 if (status && status != MR_NO_MATCH)
2102 (*action)(q->vcnt, argv, actarg);
2104 /* free saved data */
2105 for (i = 0; i < q->vcnt; i++)
2117 followup_gsha(q, sq, v, action, actarg, cl)
2118 register struct query *q;
2119 register struct save_queue *sq;
2120 register struct validate *v;
2121 register int (*action)();
2128 while (sq_get_data(sq, &argv)) {
2129 mr_trim_args(q->vcnt, argv);
2133 status = id_to_name(id, "USER", &argv[4]);
2135 status = id_to_name(-id, "STRING", &argv[4]);
2136 if (status && status != MR_NO_MATCH)
2140 if (!strcmp(argv[1], "LIST")) {
2141 status = id_to_name(id, "LIST", &argv[2]);
2142 } else if (!strcmp(argv[1], "USER")) {
2143 status = id_to_name(id, "USER", &argv[2]);
2144 } else if (!strcmp(argv[1], "KERBEROS")) {
2145 status = id_to_name(id, "STRING", &argv[2]);
2146 } else if (!strcmp(argv[1], "NONE")) {
2149 argv[2] = strsave("NONE");
2153 argv[2] = strsave("???");
2155 if (status && status != MR_NO_MATCH)
2159 (*action)(q->vcnt, argv, actarg);
2161 /* free saved data */
2162 for (i = 0; i < q->vcnt; i++)
2172 /* Special query routines */
2174 /* set_pobox - this does all of the real work.
2175 * argv = user_id, type, box
2176 * if type is POP, then box should be a machine, and its ID should be put in
2177 * pop_id. If type is SMTP, then box should be a string and its ID should
2178 * be put in box_id. If type is NONE, then box doesn't matter.
2181 int set_pobox(q, argv, cl)
2186 EXEC SQL BEGIN DECLARE SECTION;
2188 char *box, potype[9];
2189 EXEC SQL END DECLARE SECTION;
2193 user = *(int *)argv[0];
2195 EXEC SQL REPEATED SELECT pop_id, potype INTO :id, :potype FROM users
2196 WHERE users_id = :user;
2197 if (ingres_errno) return(mr_errcode);
2198 if (!strcmp(strtrim(potype), "POP"))
2199 set_pop_usage(id, -1);
2201 if (!strcmp(argv[1], "POP")) {
2202 status = name_to_id(box, "MACHINE", &id);
2203 if (status == MR_NO_MATCH)
2207 EXEC SQL REPEATED UPDATE users SET potype = 'POP', pop_id = :id
2208 WHERE users_id = :user;
2209 set_pop_usage(id, 1);
2210 } else if (!strcmp(argv[1], "SMTP")) {
2211 if (index(box, '/') || index(box, '|'))
2212 return(MR_BAD_CHAR);
2213 status = name_to_id(box, "STRING", &id);
2214 if (status == MR_NO_MATCH) {
2218 EXEC SQL REPEATED UPDATE users SET potype='SMTP', box_id = :id
2219 WHERE users_id = :user;
2220 } else /* argv[1] == "NONE" */ {
2221 EXEC SQL REPEATED UPDATE users SET potype='NONE'
2222 WHERE users_id = :user;
2225 set_pobox_modtime(q, argv, cl);
2226 EXEC SQL REPEATED UPDATE tblstats SET updates = updates+1, modtime='now'
2227 WHERE table_name='users';
2228 if (ingres_errno) return(mr_errcode);
2233 /* get_list_info: passed a wildcard list name, returns lots of stuff about
2234 * each list. This is tricky: first build a queue of all requested
2235 * data. Rest of processing consists of fixing gid, ace_name, and modby.
2238 get_list_info(q, aargv, cl, action, actarg)
2239 register struct query *q;
2242 register int (*action)();
2245 char *argv[13], *malloc(), *realloc();
2246 EXEC SQL BEGIN DECLARE SECTION;
2247 char *name, acl_type[9], listname[33], active[5], public[5], hidden[5];
2248 char maillist[5], grouplist[5], gid_str[6], acl_name[256], desc[256];
2249 char modtime[27], modby[256], modwith[9];
2250 int id, rowcount, acl_id, hid, modby_id;
2252 EXEC SQL END DECLARE SECTION;
2253 int returned, status;
2254 struct save_queue *sq, *sq_create();
2256 returned = rowcount = 0;
2258 convert_wildcards(name);
2261 sprintf(qual,"name LIKE '%s' ESCAPE '*'",name);
2262 optimize_sql_stmt(qual);
2263 EXEC SQL DECLARE csr102 CURSOR FOR SELECT list_id FROM list
2267 EXEC SQL OPEN csr102;
2272 EXEC SQL FETCH csr102 INTO :id;
2273 if(sqlca.sqlcode!=0) break;
2274 sq_save_data(sq, id);
2277 EXEC SQL CLOSE csr102;
2279 if (ingres_errno) return(mr_errcode);
2281 return(MR_NO_MATCH);
2283 argv[0] = listname; argv[1] = active; argv[2] = public; argv[3] = hidden;
2284 argv[4] = maillist; argv[5] = grouplist; argv[6] = gid_str;
2285 argv[7] = acl_type; argv[9] = desc; argv[10] = modtime; argv[12] = modwith;
2287 while (sq_get_data(sq, &id)) {
2291 EXEC SQL REPEATED SELECT name, CHAR(active), CHAR(publicflg),
2292 CHAR(hidden), hidden, CHAR(maillist), CHAR(grouplist), CHAR(gid),
2293 TRIM(acl_type), acl_id, description, CHAR(modtime), modby, modwith
2294 INTO :listname, :active, :public, :hidden, :hid, :maillist,
2295 :grouplist, :gid_str, :acl_type, :acl_id, :desc,
2296 :modtime, :modby_id, :modwith
2297 FROM list WHERE list_id = :id;
2299 if (ingres_errno) return(mr_errcode);
2301 if (atoi(gid_str) == -1)
2302 argv[6] = UNIQUE_GID;
2304 argv[8] = malloc(0);
2305 if (!strcmp(acl_type, "LIST")) {
2306 status = id_to_name(acl_id, "LIST", &argv[8]);
2307 } else if (!strcmp(acl_type, "USER")) {
2308 status = id_to_name(acl_id, "USER", &argv[8]);
2309 } else if (!strcmp(acl_type, "KERBEROS")) {
2310 status = id_to_name(acl_id, "STRING", &argv[8]);
2311 } else if (!strcmp(acl_type, "NONE")) {
2314 argv[8] = strsave("NONE");
2318 argv[8] = strsave("???");
2320 if (status && status != MR_NO_MATCH) return(status);
2322 argv[11] = malloc(0);
2324 status = id_to_name(modby_id, "USER", &argv[11]);
2326 status = id_to_name(-modby_id, "STRING", &argv[11]);
2327 if (status && status != MR_NO_MATCH) return(status);
2329 mr_trim_args(q->vcnt, argv);
2331 (*action)(q->vcnt, argv, actarg);
2337 if (ingres_errno) return(mr_errcode);
2338 return (MR_SUCCESS);
2342 /* Add_member_to_list: do list flattening as we go! MAXLISTDEPTH is
2343 * how many different ancestors a member is allowed to have.
2346 #define MAXLISTDEPTH 1024
2348 int add_member_to_list(q, argv, cl)
2353 EXEC SQL BEGIN DECLARE SECTION;
2354 int id, lid, mid, error, who, ref, rowcnt;
2355 char *mtype, dtype[9], *entity;
2356 EXEC SQL END DECLARE SECTION;
2357 int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a;
2358 int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d;
2360 char *dtypes[MAXLISTDEPTH];
2361 char *iargv[3], *buf;
2363 lid = *(int *)argv[0];
2365 mid = *(int *)argv[2];
2366 /* if the member is already a direct member of the list, punt */
2367 EXEC SQL REPEATED SELECT COUNT(list_id) INTO :rowcnt FROM imembers
2368 WHERE list_id = :lid AND member_id = :mid
2369 AND member_type = :mtype AND direct = 1;
2372 if (!strcasecmp(mtype, "STRING")) {
2374 status = id_to_name(mid, "STRING", &buf);
2375 if (status) return(status);
2376 if (index(buf, '/') || index(buf, '|')) {
2378 return(MR_BAD_CHAR);
2386 EXEC SQL DECLARE csr103 CURSOR FOR
2387 SELECT list_id, ref_count FROM imembers
2388 WHERE member_id = :lid AND member_type='LIST';
2391 EXEC SQL OPEN csr103;
2395 EXEC SQL FETCH csr103 INTO :id, :ref;
2396 if(sqlca.sqlcode != 0) break;
2398 ancestors[acount++] = id;
2399 if (acount >= MAXLISTDEPTH) break;
2401 EXEC SQL CLOSE csr103;
2402 if (ingres_errno) return(mr_errcode);
2403 if (acount >= MAXLISTDEPTH) {
2404 return(MR_INTERNAL);
2406 descendants[0] = mid;
2411 if (!strcmp(mtype, "LIST")) {
2412 EXEC SQL DECLARE csr104 CURSOR FOR
2413 SELECT member_id, member_type, ref_count
2415 WHERE list_id = :mid;
2418 EXEC SQL OPEN csr104;
2422 EXEC SQL FETCH csr104 INTO :id, :dtype, :ref;
2423 if(sqlca.sqlcode != 0) break;
2426 dtypes[dcount] = "LIST";
2429 dtypes[dcount] = "USER";
2432 dtypes[dcount] = "STRING";
2435 dtypes[dcount] = "KERBEROS";
2442 descendants[dcount++] = id;
2443 if (dcount >= MAXLISTDEPTH) {
2448 EXEC SQL CLOSE csr104;
2449 if (ingres_errno) return(mr_errcode);
2451 return(MR_INTERNAL);
2453 for (a = 0; a < acount; a++) {
2455 for (d = 0; d < dcount; d++) {
2456 mid = descendants[d];
2458 if (mid == lid && !strcmp(mtype, "LIST")) {
2459 return(MR_LISTLOOP);
2461 EXEC SQL REPEATED SELECT COUNT(ref_count) INTO :rowcnt
2463 WHERE list_id = :lid AND member_id = :mid
2464 AND member_type = :mtype;
2465 ref = aref[a] * dref[d];
2467 if (a == 0 && d == 0) {
2468 EXEC SQL UPDATE imembers
2469 SET ref_count = ref_count+:ref, direct=1
2470 WHERE list_id = :lid AND member_id = :mid
2471 AND member_type = :mtype;
2473 EXEC SQL UPDATE imembers
2474 SET ref_count = ref_count+:ref
2475 WHERE list_id = :lid AND member_id = :mid
2476 AND member_type = :mtype;
2479 incremental_clear_before();
2480 if (a == 0 && d == 0) {
2481 EXEC SQL INSERT INTO imembers
2482 (list_id, member_id, direct, member_type, ref_count)
2483 VALUES (:lid, :mid, 1, :mtype, 1);
2485 EXEC SQL INSERT INTO imembers
2486 (list_id, member_id, member_type, ref_count)
2487 VALUES (:lid, :mid, :mtype, 1);
2489 iargv[0] = (char *)lid;
2491 iargv[2] = (char *)mid;
2492 incremental_after("members", 0, iargv);
2496 lid = *(int *)argv[0];
2497 entity = cl->entity;
2498 who = cl->client_id;
2499 EXEC SQL REPEATED UPDATE list
2500 SET modtime='now', modby = :who, modwith = :entity
2501 WHERE list_id = :lid;
2502 if (ingres_errno) return(mr_errcode);
2507 /* Delete_member_from_list: do list flattening as we go!
2510 int delete_member_from_list(q, argv, cl)
2515 EXEC SQL BEGIN DECLARE SECTION;
2516 int id, lid, mid, cnt, error, who, ref;
2517 char *mtype, dtype[9], *entity;
2518 EXEC SQL END DECLARE SECTION;
2519 int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a;
2520 int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d;
2521 char *dtypes[MAXLISTDEPTH];
2524 lid = *(int *)argv[0];
2526 mid = *(int *)argv[2];
2527 /* if the member is not a direct member of the list, punt */
2528 EXEC SQL REPEATED SELECT COUNT(list_id) INTO :cnt FROM imembers
2529 WHERE list_id = :lid AND member_id = :mid
2530 AND member_type = :mtype AND direct = 1;
2531 if (ingres_errno) return(mr_errcode);
2533 return(MR_NO_MATCH);
2537 EXEC SQL DECLARE csr105 CURSOR FOR
2538 SELECT list_id, ref_count FROM imembers
2539 WHERE member_id = :lid AND member_type = 'LIST';
2542 EXEC SQL OPEN csr105;
2546 EXEC SQL FETCH csr105 INTO :id, :ref;
2547 if(sqlca.sqlcode!=0) break;
2549 ancestors[acount++] = id;
2550 if (acount >= MAXLISTDEPTH) break;
2552 EXEC SQL CLOSE csr105;
2555 if (acount >= MAXLISTDEPTH)
2556 return(MR_INTERNAL);
2557 descendants[0] = mid;
2562 if (!strcmp(mtype, "LIST")) {
2563 EXEC SQL DECLARE csr106 CURSOR FOR
2564 SELECT member_id, member_type, ref_count FROM imembers
2565 WHERE list_id = :mid;
2568 EXEC SQL OPEN csr106;
2572 EXEC SQL FETCH csr106 INTO :id, :dtype, :ref;
2573 if(sqlca.sqlcode!=0) break;
2576 dtypes[dcount] = "LIST";
2579 dtypes[dcount] = "USER";
2582 dtypes[dcount] = "STRING";
2585 dtypes[dcount] = "KERBEROS";
2592 descendants[dcount++] = id;
2593 if (dcount >= MAXLISTDEPTH) break;
2595 EXEC SQL CLOSE csr106;
2599 return(MR_INTERNAL);
2601 for (a = 0; a < acount; a++) {
2603 for (d = 0; d < dcount; d++) {
2604 mid = descendants[d];
2606 if (mid == lid && !strcmp(mtype, "LIST")) {
2607 return(MR_LISTLOOP);
2609 EXEC SQL REPEATED SELECT ref_count INTO :cnt FROM imembers
2610 WHERE list_id = :lid AND member_id = :mid AND member_type = :mtype;
2611 ref = aref[a] * dref[d];
2613 iargv[0] = (char *)lid;
2615 iargv[2] = (char *)mid;
2616 incremental_before("members", 0, iargv);
2617 EXEC SQL DELETE FROM imembers
2618 WHERE list_id = :lid AND member_id = :mid
2619 AND member_type= :mtype;
2620 incremental_clear_after();
2621 } else if (a == 0 && d == 0) {
2622 EXEC SQL UPDATE imembers
2623 SET ref_count = ref_count - :ref, direct = 0
2624 WHERE list_id = :lid AND member_id = :mid
2625 AND member_type = :mtype;
2627 EXEC SQL UPDATE imembers
2628 SET ref_count = ref_count - :ref
2629 WHERE list_id = :lid AND member_id = :mid
2630 AND member_type = :mtype;
2634 lid = *(int *)argv[0];
2635 entity = cl->entity;
2636 who = cl->client_id;
2637 EXEC SQL UPDATE list SET modtime = 'now', modby = :who, modwith = :entity
2638 WHERE list_id = :lid;
2639 if (ingres_errno) return(mr_errcode);
2644 /* get_ace_use - given a type and a name, return a type and a name.
2645 * The ace_type is one of "LIST", "USER", "RLIST", or "RUSER" in argv[0],
2646 * and argv[1] will contain the ID of the entity in question. The R*
2647 * types mean to recursively look at every containing list, not just
2648 * when the object in question is a direct member. On return, the
2649 * usage type will be one of LIST, SERVICE, FILESYS, QUOTA, QUERY, or ZEPHYR.
2652 int get_ace_use(q, argv, cl, action, actarg)
2660 EXEC SQL BEGIN DECLARE SECTION;
2662 int aid, listid, id;
2663 EXEC SQL END DECLARE SECTION;
2664 struct save_queue *sq, *sq_create();
2667 aid = *(int *)argv[1];
2668 if (!strcmp(atype, "LIST") || !strcmp(atype, "USER") ||
2669 !strcmp(atype, "KERBEROS")) {
2670 return(get_ace_internal(atype, aid, action, actarg));
2674 if (!strcmp(atype, "RLIST")) {
2675 sq_save_data(sq, aid);
2676 /* get all the list_id's of containing lists */
2677 EXEC SQL DECLARE csr107 CURSOR FOR
2678 SELECT list_id FROM imembers
2679 WHERE member_type='LIST' AND member_id = :aid;
2682 EXEC SQL OPEN csr107;
2686 EXEC SQL FETCH csr107 INTO :listid;
2687 if(sqlca.sqlcode != 0) break;
2688 sq_save_unique_data(sq, listid);
2690 EXEC SQL CLOSE csr107;
2691 /* now process each one */
2692 while (sq_get_data(sq, &id)) {
2693 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2698 if (!strcmp(atype, "RUSER")) {
2699 EXEC SQL DECLARE csr108 CURSOR FOR
2700 SELECT list_id FROM imembers
2701 WHERE member_type='USER' AND member_id = :aid;
2704 EXEC SQL OPEN csr108;
2708 EXEC SQL FETCH csr108 INTO :listid;
2709 if(sqlca.sqlcode != 0) break;
2710 sq_save_data(sq, listid);
2712 EXEC SQL CLOSE csr108;
2713 /* now process each one */
2714 while (sq_get_data(sq, &id)) {
2715 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2718 if (get_ace_internal("USER", aid, action, actarg) == MR_SUCCESS)
2722 if (!strcmp(atype, "RKERBERO")) {
2723 EXEC SQL DECLARE csr109 CURSOR FOR
2724 SELECT list_id FROM imembers
2725 WHERE member_type='KERBEROS' AND member_id = :aid;
2728 EXEC SQL OPEN csr109;
2732 EXEC SQL FETCH csr109 INTO :listid;
2733 if(sqlca.sqlcode != 0) break;
2734 sq_save_data(sq, listid);
2736 EXEC SQL CLOSE csr109;
2737 /* now process each one */
2738 while (sq_get_data(sq, &id)) {
2739 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2742 if (get_ace_internal("KERBEROS", aid, action, actarg) == MR_SUCCESS)
2747 if (ingres_errno) return(mr_errcode);
2748 if (!found) return(MR_NO_MATCH);
2753 /* This looks up a single list or user for ace use. atype must be "USER"
2754 * or "LIST", and aid is the ID of the corresponding object. This is used
2755 * by get_ace_use above.
2758 get_ace_internal(atype, aid, action, actarg)
2759 EXEC SQL BEGIN DECLARE SECTION;
2762 EXEC SQL END DECLARE SECTION;
2768 EXEC SQL BEGIN DECLARE SECTION;
2770 EXEC SQL END DECLARE SECTION;
2773 if (!strcmp(atype, "LIST")) {
2774 rargv[0] = "FILESYS";
2775 EXEC SQL DECLARE csr110 CURSOR FOR
2776 SELECT label FROM filesys
2777 WHERE owners = :aid;
2780 EXEC SQL OPEN csr110;
2784 EXEC SQL FETCH csr110 INTO :name;
2785 if(sqlca.sqlcode != 0) break;
2786 (*action)(2, rargv, actarg);
2789 EXEC SQL CLOSE csr110;
2792 EXEC SQL DECLARE csr111 CURSOR FOR
2793 SELECT capability FROM capacls
2794 WHERE list_id = :aid ;
2797 EXEC SQL OPEN csr111;
2801 EXEC SQL FETCH csr111 INTO :name ;
2802 if(sqlca.sqlcode != 0) break;
2803 (*action)(2, rargv, actarg);
2806 EXEC SQL CLOSE csr111;
2807 } else if (!strcmp(atype, "USER")) {
2808 rargv[0] = "FILESYS";
2809 EXEC SQL DECLARE csr112 CURSOR FOR
2810 SELECT label FROM filesys
2814 EXEC SQL OPEN csr112;
2818 EXEC SQL FETCH csr112 INTO :name ;
2819 if(sqlca.sqlcode != 0) break;
2820 (*action)(2, rargv, actarg);
2823 EXEC SQL CLOSE csr112;
2827 EXEC SQL DECLARE csr113 CURSOR FOR
2828 SELECT name FROM list
2829 WHERE acl_type = :atype AND acl_id = :aid;
2832 EXEC SQL OPEN csr113;
2836 EXEC SQL FETCH csr113 INTO :name;
2837 if(sqlca.sqlcode != 0) break;
2838 (*action)(2, rargv, actarg);
2841 EXEC SQL CLOSE csr113;
2843 rargv[0] = "SERVICE";
2844 EXEC SQL DECLARE csr114 CURSOR FOR
2845 SELECT name FROM servers
2846 WHERE acl_type = :atype AND acl_id = :aid;
2849 EXEC SQL OPEN csr114;
2853 EXEC SQL FETCH csr114 INTO :name;
2854 if(sqlca.sqlcode != 0) break;
2855 (*action)(2, rargv, actarg);
2858 EXEC SQL CLOSE csr114;
2860 rargv[0] = "HOSTACCESS";
2861 EXEC SQL DECLARE csr115 CURSOR FOR
2862 SELECT name FROM machine m, hostaccess ha
2863 WHERE m.mach_id = ha.mach_id AND ha.acl_type = :atype
2864 AND ha.acl_id = :aid;
2867 EXEC SQL OPEN csr115;
2871 EXEC SQL FETCH csr115 INTO :name;
2872 if(sqlca.sqlcode != 0) break;
2873 (*action)(2, rargv, actarg);
2876 EXEC SQL CLOSE csr115;
2878 rargv[0] = "ZEPHYR";
2879 EXEC SQL DECLARE csr116 CURSOR FOR
2880 SELECT class FROM zephyr z
2881 WHERE z.xmt_type = :atype AND z.xmt_id = :aid
2882 OR z.sub_type = :atype AND z.sub_id = :aid
2883 OR z.iws_type = :atype AND z.iws_id = :aid
2884 OR z.iui_type = :atype AND z.iui_id = :aid;
2887 EXEC SQL OPEN csr116;
2891 EXEC SQL FETCH csr116 INTO :name;
2892 if(sqlca.sqlcode != 0) break;
2893 (*action)(2, rargv, actarg);
2896 EXEC SQL CLOSE csr116;
2898 if (!found) return(MR_NO_MATCH);
2903 /* get_lists_of_member - given a type and a name, return the name and flags
2904 * of all of the lists of the given member. The member_type is one of
2905 * "LIST", "USER", "STRING", "RLIST", "RUSER", or "RSTRING" in argv[0],
2906 * and argv[1] will contain the ID of the entity in question. The R*
2907 * types mean to recursively look at every containing list, not just
2908 * when the object in question is a direct member.
2911 int get_lists_of_member(q, argv, cl, action, actarg)
2918 int found = 0, direct = 1;
2920 EXEC SQL BEGIN DECLARE SECTION;
2922 int aid, listid, id;
2923 char name[33], active[5], public[5], hidden[5], maillist[5], grouplist[5];
2924 EXEC SQL END DECLARE SECTION;
2927 aid = *(int *)argv[1];
2928 if (!strcmp(atype, "RLIST")) {
2932 if (!strcmp(atype, "RUSER")) {
2936 if (!strcmp(atype, "RSTRING")) {
2940 if (!strcmp(atype, "RKERBEROS")) {
2949 rargv[4] = maillist;
2950 rargv[5] = grouplist;
2952 EXEC SQL DECLARE csr117a CURSOR FOR
2953 SELECT l.name, CHAR(l.active), CHAR(l.publicflg), CHAR(l.hidden),
2954 CHAR(l.maillist), CHAR(l.grouplist)
2955 FROM list l, imembers im
2956 WHERE l.list_id = im.list_id AND im.direct = 1
2957 AND im.member_type = :atype AND im.member_id = :aid;
2960 EXEC SQL OPEN csr117a;
2964 EXEC SQL FETCH csr117a
2965 INTO :name, :active, :public, :hidden, :maillist, :grouplist;
2966 if(sqlca.sqlcode != 0) break;
2967 (*action)(6, rargv, actarg);
2970 EXEC SQL CLOSE csr117a;
2972 EXEC SQL DECLARE csr117b CURSOR FOR
2973 SELECT l.name, CHAR(l.active), CHAR(l.publicflg), CHAR(l.hidden),
2974 CHAR(l.maillist), CHAR(l.grouplist)
2975 FROM list l, imembers im
2976 WHERE l.list_id = im.list_id
2977 AND im.member_type = :atype AND im.member_id = :aid;
2980 EXEC SQL OPEN csr117b;
2984 EXEC SQL FETCH csr117b
2985 INTO :name, :active, :public, :hidden, :maillist, :grouplist;
2986 if(sqlca.sqlcode != 0) break;
2987 (*action)(6, rargv, actarg);
2990 EXEC SQL CLOSE csr117b;
2993 if (ingres_errno) return(mr_errcode);
2994 if (!found) return(MR_NO_MATCH);
2999 /* qualified_get_lists: passed "TRUE", "FALSE", or "DONTCARE" for each of
3000 * the five flags associated with each list. It will return the name of
3001 * each list that meets the quailifications. It does this by building a
3002 * where clause based on the arguments, then doing a retrieve.
3005 static char *lflags[5] = { "active", "publicflg", "hidden", "maillist", "grouplist" };
3007 int qualified_get_lists(q, argv, cl, action, actarg)
3014 return(qualified_get(q, argv, action, actarg, "l.list_id != 0",
3015 "l", "name", lflags));
3019 /* get_members_of_list - this gets only direct members */
3021 get_members_of_list(q, argv, cl, action, actarg)
3028 return(gmol_internal(q, argv, cl, action, actarg, 1));
3031 /* get_end_members_of_list - this gets direct or indirect members */
3033 get_end_members_of_list(q, argv, cl, action, actarg)
3040 return(gmol_internal(q, argv, cl, action, actarg, 0));
3043 /** gmol_internal - optimized query for retrieval of list members
3044 ** used by both get_members_of_list and get_end_members_of_list
3047 ** argv[0] - list_id
3050 ** - retrieve USER members, then LIST members, then STRING members
3053 gmol_internal(q, argv, cl, action, actarg, flag)
3061 EXEC SQL BEGIN DECLARE SECTION;
3062 int list_id, member_id, direct;
3063 char member_name[129], member_type[9];
3064 EXEC SQL END DECLARE SECTION;
3067 struct save_queue *sq;
3069 /* true/false flag indicates whether to display only direct members. */
3075 list_id = *(int *)argv[0];
3079 EXEC SQL DECLARE csr118 CURSOR FOR
3080 SELECT member_type, member_id FROM imembers
3081 WHERE list_id = :list_id AND direct > :direct;
3084 EXEC SQL OPEN csr118;
3088 EXEC SQL FETCH csr118 INTO :member_type, :member_id;
3089 if (sqlca.sqlcode != 0) break;
3092 sq_save_data(sq, ((int)member_type[0] << 24) | (member_id & 0xffffff));
3094 EXEC SQL CLOSE csr118;
3096 if (members <= 49) {
3097 targv[1] = malloc(0);
3098 while (sq_remove_data(sq, &member_id)) {
3099 switch (member_id >> 24) {
3102 id_to_name(member_id & 0xffffff, "USER", &targv[1]);
3103 (*action)(2, targv, actarg);
3107 id_to_name(member_id & 0xffffff, "LIST", &targv[1]);
3108 (*action)(2, targv, actarg);
3111 targv[0] = "STRING";
3112 id_to_name(member_id & 0xffffff, "STRING", &targv[1]);
3113 (*action)(2, targv, actarg);
3116 targv[0] = "KERBEROS";
3117 id_to_name(member_id & 0xffffff, "STRING", &targv[1]);
3118 (*action)(2, targv, actarg);
3122 return(MR_INTERNAL);
3131 targv[1] = member_name;
3133 EXEC SQL DECLARE csr119 CURSOR FOR
3134 SELECT u.login FROM users u, imembers im
3135 WHERE im.list_id = :list_id AND im.member_type = 'USER'
3136 AND im.member_id = u.users_id AND im.direct > :direct
3140 EXEC SQL OPEN csr119;
3144 EXEC SQL FETCH csr119 INTO :member_name;
3145 if(sqlca.sqlcode != 0) break;
3146 (*action)(2, targv, actarg);
3148 EXEC SQL CLOSE csr119;
3149 if (ingres_errno) return(mr_errcode);
3152 EXEC SQL DECLARE csr120 CURSOR FOR
3153 SELECT l.name FROM list l, imembers im
3154 WHERE im.list_id = :list_id AND im.member_type='LIST'
3155 AND im.member_id = l.list_id AND im.direct > :direct
3159 EXEC SQL OPEN csr120;
3163 EXEC SQL FETCH csr120 INTO :member_name;
3164 if(sqlca.sqlcode != 0) break;
3165 (*action)(2, targv, actarg);
3167 EXEC SQL CLOSE csr120;
3168 if (ingres_errno) return(mr_errcode);
3170 targv[0] = "STRING";
3171 EXEC SQL DECLARE csr121 CURSOR FOR
3172 SELECT CHAR(str.string) FROM strings str, imembers im
3173 WHERE im.list_id = :list_id AND im.member_type='STRING'
3174 AND im.member_id = str.string_id AND im.direct > :direct
3178 EXEC SQL OPEN csr121;
3182 EXEC SQL FETCH csr121 INTO :member_name;
3183 if(sqlca.sqlcode != 0) break;
3184 (*action)(2, targv, actarg);
3186 EXEC SQL CLOSE csr121;
3187 if (ingres_errno) return(mr_errcode);
3189 targv[0] = "KERBEROS";
3190 EXEC SQL DECLARE csr122 CURSOR FOR
3191 SELECT CHAR(str.string) FROM strings str, imembers im
3192 WHERE im.list_id = :list_id AND im.member_type='KERBEROS'
3193 AND im.member_id = str.string_id
3194 AND im.direct > :direct
3198 EXEC SQL OPEN csr122;
3202 EXEC SQL FETCH csr122 INTO :member_name;
3203 if(sqlca.sqlcode != 0) break;
3204 (*action)(2, targv, actarg);
3206 EXEC SQL CLOSE csr122;
3207 if (ingres_errno) return(mr_errcode);
3213 /* count_members_of_list: this is a simple query, but it cannot be done
3214 * through the dispatch table.
3217 int count_members_of_list(q, argv, cl, action, actarg)
3224 EXEC SQL BEGIN DECLARE SECTION;
3226 EXEC SQL END DECLARE SECTION;
3227 char *rargv[1], countbuf[5];
3229 list = *(int *)argv[0];
3230 rargv[0] = countbuf;
3231 EXEC SQL REPEATED SELECT count (*) INTO :ct FROM imembers
3232 WHERE list_id = :list AND direct=1;
3233 if (ingres_errno) return(mr_errcode);
3234 sprintf(countbuf, "%d", ct);
3235 (*action)(1, rargv, actarg);
3240 /* qualified_get_server: passed "TRUE", "FALSE", or "DONTCARE" for each of
3241 * the three flags associated with each service. It will return the name of
3242 * each service that meets the quailifications. It does this by building a
3243 * where clause based on the arguments, then doing a retrieve.
3246 static char *sflags[3] = { "enable", "inprogress", "harderror" };
3248 int qualified_get_server(q, argv, cl, action, actarg)
3255 return(qualified_get(q, argv, action, actarg, "s.name != ''",
3256 "s", "name", sflags));
3260 /* generic qualified get routine, used by qualified_get_lists,
3261 * qualified_get_server, and qualified_get_serverhost.
3263 * start - a simple where clause, must not be empty
3264 * range - the name of the range variable
3265 * field - the field to return
3266 * flags - an array of strings, names of the flag variables
3269 int qualified_get(q, argv, action, actarg, start, range, field, flags)
3279 char name[33], qual[256];
3281 char *rargv[1], buf[32];
3283 strcpy(qual, start);
3284 for (i = 0; i < q->argc; i++) {
3285 if (!strcmp(argv[i], "TRUE")) {
3286 sprintf(buf, " AND %s.%s != 0", range, flags[i]);
3287 (void) strcat(qual, buf);
3288 } else if (!strcmp(argv[i], "FALSE")) {
3289 sprintf(buf, " AND %s.%s = 0", range, flags[i]);
3290 (void) strcat(qual, buf);
3294 rargv[0] = SQLDA->sqlvar[0].sqldata;
3295 sprintf(stmt_buf,"SELECT CHAR(%s.%s) FROM %s %s WHERE %s",range,field,q->rtable,range,qual);
3296 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3298 return(MR_INTERNAL);
3299 EXEC SQL DECLARE csr123 CURSOR FOR stmt;
3300 EXEC SQL OPEN csr123;
3302 EXEC SQL FETCH csr123 USING DESCRIPTOR :SQLDA;
3303 if(sqlca.sqlcode != 0) break;
3305 (*action)(1, rargv, actarg);
3307 EXEC SQL CLOSE csr123;
3308 if (ingres_errno) return(mr_errcode);
3310 return(MR_NO_MATCH);
3315 /* qualified_get_serverhost: passed "TRUE", "FALSE", or "DONTCARE" for each of
3316 * the five flags associated with each serverhost. It will return the name of
3317 * each service and host that meets the quailifications. It does this by
3318 * building a where clause based on the arguments, then doing a retrieve.
3321 static char *shflags[6] = { "service", "enable", "override", "success",
3322 "inprogress", "hosterror" };
3324 int qualified_get_serverhost(q, argv, cl, action, actarg)
3331 EXEC SQL BEGIN DECLARE SECTION;
3332 char sname[33], mname[33], qual[256];
3333 EXEC SQL END DECLARE SECTION;
3334 char *rargv[2], buf[32];
3337 sprintf(qual, "m.mach_id = sh.mach_id AND sh.service = uppercase('%s')",
3339 for (i = 1; i < q->argc; i++) {
3340 if (!strcmp(argv[i], "TRUE")) {
3341 sprintf(buf, " AND sh.%s != 0", shflags[i]);
3343 } else if (!strcmp(argv[i], "FALSE")) {
3344 sprintf(buf, " AND sh.%s = 0", shflags[i]);
3351 EXEC SQL DECLARE csr124 CURSOR FOR
3352 SELECT sh.service, m.name FROM serverhosts sh, machine m
3356 EXEC SQL OPEN csr124;
3360 EXEC SQL FETCH csr124 INTO :sname, :mname;
3361 if(sqlca.sqlcode != 0) break;
3363 (*action)(2, rargv, actarg);
3365 EXEC SQL CLOSE csr124;
3367 if (ingres_errno) return(mr_errcode);
3369 return(MR_NO_MATCH);
3374 /* register_user - change user's login name and allocate a pobox, group,
3375 * filesystem, and quota for them. The user's status must start out as 0,
3376 * and is left as 2. Arguments are: user's UID, new login name, and user's
3377 * type for filesystem allocation (MR_FS_STUDENT, MR_FS_FACULTY,
3378 * MR_FS_STAFF, MR_FS_MISC).
3381 register_user(q, argv, cl)
3386 EXEC SQL BEGIN DECLARE SECTION;
3387 char *login, dir[65], *entity, directory[129], machname[33];
3388 int who, rowcount, mid, uid, users_id, flag, utype, nid, list_id, quota;
3389 int size, alloc, pid, ostatus, nstatus, gidval, fsidval, npidval;
3390 static int m_id = 0, def_quota = 0;
3391 EXEC SQL END DECLARE SECTION;
3392 char buffer[256], *aargv[3];
3394 entity = cl->entity;
3395 who = cl->client_id;
3397 uid = atoi(argv[0]);
3399 utype = atoi(argv[2]);
3402 EXEC SQL REPEATED SELECT users_id, status INTO :users_id, :ostatus
3404 WHERE uid = :uid AND (status=0 OR status=5 OR status=6);
3406 if (sqlca.sqlerrd[2] == 0)
3407 return(MR_NO_MATCH);
3408 if (sqlca.sqlerrd[2] > 1)
3409 return(MR_NOT_UNIQUE);
3411 /* check new login name */
3412 EXEC SQL REPEATED SELECT COUNT(login) INTO :rowcount FROM users
3413 WHERE login = :login AND users_id != :users_id;
3414 if (ingres_errno) return(mr_errcode);
3415 if (rowcount > 0) return(MR_IN_USE);
3416 EXEC SQL REPEATED SELECT COUNT(name) INTO :rowcount FROM list
3417 WHERE name = :login;
3418 if (ingres_errno) return(mr_errcode);
3419 if (rowcount > 0) return(MR_IN_USE);
3420 EXEC SQL REPEATED SELECT COUNT(label) INTO :rowcount FROM filesys
3421 WHERE label = :login;
3422 if (ingres_errno) return(mr_errcode);
3423 if (rowcount > 0) return(MR_IN_USE);
3424 com_err(whoami, 0, "login name OK");
3426 /* choose place for pobox, put in mid */
3427 EXEC SQL DECLARE csr130 CURSOR FOR
3428 SELECT sh.mach_id, m.name FROM serverhosts sh, machine m
3429 WHERE sh.service='POP' AND sh.mach_id=m.mach_id
3430 AND sh.value2 - sh.value1 =
3431 (SELECT MAX(value2 - value1) FROM serverhosts
3432 WHERE service = 'POP');
3435 EXEC SQL OPEN csr130;
3438 EXEC SQL FETCH csr130 INTO :mid, :machname;
3439 if (sqlca.sqlerrd[2] == 0) {
3440 EXEC SQL CLOSE csr130;
3441 if (ingres_errno) return(mr_errcode);
3442 return(MR_NO_POBOX);
3444 EXEC SQL CLOSE csr130;
3445 if (ingres_errno) return(mr_errcode);
3448 /* change login name, set pobox */
3449 sprintf(buffer, "u.users_id = %d", users_id);
3450 incremental_before("users", buffer, 0);
3452 if (ostatus == 5 || ostatus == 6)
3454 EXEC SQL REPEATED UPDATE users SET login = :login, status = :nstatus,
3455 modtime='now', modby = :who, modwith = :entity, potype='POP',
3456 pop_id = :mid, pmodtime='now', pmodby = :who, pmodwith = :entity
3457 WHERE users_id = :users_id;
3459 if (ingres_errno) return(mr_errcode);
3460 if (sqlca.sqlerrd[2] != 1)
3461 return(MR_INTERNAL);
3462 set_pop_usage(mid, 1);
3463 com_err(whoami, 0, "set login name to %s and pobox to %s", login,
3465 incremental_after("users", buffer, 0);
3467 /* create group list */
3468 if (set_next_object_id("gid", "list", 1))
3470 if (set_next_object_id("list_id", "list", 0))
3472 EXEC SQL REPEATED SELECT value INTO :list_id FROM numvalues
3473 WHERE name='list_id';
3474 if (ingres_errno) return(mr_errcode);
3475 if (sqlca.sqlerrd[2] != 1)
3476 return(MR_INTERNAL);
3477 incremental_clear_before();
3478 EXEC SQL SELECT value INTO :gidval FROM numvalues WHERE name = 'gid';
3479 EXEC SQL REPEATED INSERT INTO list
3480 (name, list_id, active, publicflg, hidden, maillist, grouplist,
3481 gid, description, acl_type, acl_id,
3482 modtime, modby, modwith)
3483 VALUES (:login, :list_id, 1, 0, 0, 0, 1,
3484 :gidval, 'User Group', 'USER', :users_id,
3485 'now', :who, :entity);
3486 if (ingres_errno) return(mr_errcode);
3487 if (sqlca.sqlerrd[2] != 1)
3488 return(MR_INTERNAL);
3489 sprintf(buffer, "l.list_id = %d", list_id);
3490 incremental_after("list", buffer, 0);
3491 aargv[0] = (char *) list_id;
3493 aargv[2] = (char *) users_id;
3494 incremental_clear_before();
3495 EXEC SQL REPEATED INSERT INTO imembers
3496 (list_id, member_type, member_id, ref_count, direct)
3497 VALUES (:list_id, 'USER', :users_id, 1, 1);
3498 if (ingres_errno) return(mr_errcode);
3499 if (sqlca.sqlerrd[2] != 1)
3500 return(MR_INTERNAL);
3501 incremental_after("members", 0, aargv);
3504 /* Cell Name (I know, it shouldn't be hard coded...) */
3505 strcpy(machname, "ATHENA.MIT.EDU");
3506 EXEC SQL SELECT mach_id INTO :m_id FROM machine
3507 WHERE name = :machname;
3510 /* create filesystem */
3511 if (set_next_object_id("filsys_id", "filesys", 0))
3513 incremental_clear_before();
3514 if (islower(login[0]) && islower(login[1])) {
3515 sprintf(directory, "/afs/athena.mit.edu/user/%c/%c/%s",
3516 login[0], login[1], login);
3518 sprintf(directory, "/afs/athena.mit.edu/user/other/%s", login);
3521 EXEC SQL SELECT value INTO :fsidval FROM numvalues
3522 WHERE numvalues.name='filsys_id';
3523 EXEC SQL REPEATED INSERT INTO filesys
3524 (filsys_id, phys_id, label, type, mach_id, name,
3525 mount, access, comments, owner, owners, createflg,
3526 lockertype, modtime, modby, modwith)
3528 (:fsidval, 0, :login, 'AFS', :m_id, :directory,
3529 '/mit/'+:login, 'w', 'User Locker', :users_id, :list_id, 1,
3530 'HOMEDIR', 'now', :who, :entity);
3532 if (ingres_errno) return(mr_errcode);
3533 if (sqlca.sqlerrd[2] != 1)
3534 return(MR_INTERNAL);
3535 sprintf(buffer,"fs.filsys_id = %d",fsidval);
3536 incremental_after("filesys", buffer, 0);
3539 if (def_quota == 0) {
3540 EXEC SQL REPEATED SELECT value INTO :def_quota FROM numvalues
3541 WHERE name='def_quota';
3542 if (ingres_errno) return(mr_errcode);
3543 if (sqlca.sqlerrd[2] != 1)
3544 return(MR_NO_QUOTA);
3547 incremental_clear_before();
3548 EXEC SQL REPEATED INSERT INTO quota
3549 (entity_id, filsys_id, type, quota, phys_id, modtime, modby, modwith)
3551 (0, :fsidval, 'ANY', :def_quota, 0, 'now', :who, :entity);
3552 if (ingres_errno) return(mr_errcode);
3553 if (sqlca.sqlerrd[2] != 1)
3554 return(MR_INTERNAL);
3558 sprintf(buffer, "q.entity_id = 0 and q.filsys_id = %d and q.type = 'ANY'", fsidval);
3559 incremental_after("quota", buffer, aargv);
3560 com_err(whoami, 0, "quota of %d assigned", def_quota);
3561 if (ingres_errno) return(mr_errcode);
3563 cache_entry(login, "USER", users_id);
3565 EXEC SQL REPEATED UPDATE tblstats SET updates=updates+1, modtime='now'
3566 WHERE table_name='users';
3567 EXEC SQL REPEATED UPDATE tblstats SET appends=appends+1, modtime='now'
3568 WHERE table_name='list' OR table_name='filesys' OR table_name='quota';
3569 if (ingres_errno) return(mr_errcode);
3575 /** set_pop_usage - incr/decr usage count for pop server in serverhosts talbe
3579 ** delta (will be +/- 1)
3582 ** - incr/decr value field in serverhosts table for pop/mach_id
3586 static int set_pop_usage(id, cnt)
3587 EXEC SQL BEGIN DECLARE SECTION;
3590 EXEC SQL END DECLARE SECTION;
3592 EXEC SQL REPEATED UPDATE serverhosts SET value1 = value1 + :cnt
3593 WHERE serverhosts.service = 'POP' AND serverhosts.mach_id = :id;
3595 if (ingres_errno) return(mr_errcode);
3599 int _sdl_followup(q, argv, cl)
3608 EXEC SQL set printqry;
3610 EXEC SQL set noprintqry;
3617 /* Validation Routines */
3619 validate_row(q, argv, v)
3620 register struct query *q;
3622 register struct validate *v;
3624 EXEC SQL BEGIN DECLARE SECTION;
3628 EXEC SQL END DECLARE SECTION;
3630 /* build where clause */
3631 build_qual(v->qual, v->argc, argv, qual);
3633 if (log_flags & LOG_VALID)
3634 /* tell the logfile what we're doing */
3635 com_err(whoami, 0, "validating row: %s", qual);
3637 /* look for the record */
3638 sprintf(stmt_buf,"SELECT COUNT (*) FROM %s WHERE %s",q->rtable,qual);
3639 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3641 return(MR_INTERNAL);
3642 EXEC SQL DECLARE csr126 CURSOR FOR stmt;
3643 EXEC SQL OPEN csr126;
3644 EXEC SQL FETCH csr126 USING DESCRIPTOR :SQLDA;
3645 EXEC SQL CLOSE csr126;
3646 rowcount = *(int *)SQLDA->sqlvar[0].sqldata;
3648 if (ingres_errno) return(mr_errcode);
3649 if (rowcount == 0) return(MR_NO_MATCH);
3650 if (rowcount > 1) return(MR_NOT_UNIQUE);
3654 validate_fields(q, argv, vo, n)
3656 register char *argv[];
3657 register struct valobj *vo;
3660 register int status;
3665 if (log_flags & LOG_VALID)
3666 com_err(whoami, 0, "validating %s in %s: %s",
3667 vo->namefield, vo->table, argv[vo->index]);
3668 status = validate_name(argv, vo);
3672 if (log_flags & LOG_VALID)
3673 com_err(whoami, 0, "validating %s in %s: %s",
3674 vo->idfield, vo->table, argv[vo->index]);
3675 status = validate_id(q, argv, vo);
3679 if (log_flags & LOG_VALID)
3680 com_err(whoami, 0, "validating date: %s", argv[vo->index]);
3681 status = validate_date(argv, vo);
3685 if (log_flags & LOG_VALID)
3686 com_err(whoami, 0, "validating %s type: %s",
3687 vo->table, argv[vo->index]);
3688 status = validate_type(argv, vo);
3692 if (log_flags & LOG_VALID)
3693 com_err(whoami, 0, "validating typed data (%s): %s",
3694 argv[vo->index - 1], argv[vo->index]);
3695 status = validate_typedata(q, argv, vo);
3699 if (log_flags & LOG_VALID)
3700 com_err(whoami, 0, "validating rename %s in %s",
3701 argv[vo->index], vo->table);
3702 status = validate_rename(argv, vo);
3706 if (log_flags & LOG_VALID)
3707 com_err(whoami, 0, "validating chars: %s", argv[vo->index]);
3708 status = validate_chars(argv[vo->index]);
3716 status = lock_table(vo);
3720 status = convert_wildcards(argv[vo->index]);
3724 status = convert_wildcards_uppercase(argv[vo->index]);
3729 if (status != MR_EXISTS) return(status);
3733 if (ingres_errno) return(mr_errcode);
3738 /* validate_chars: verify that there are no illegal characters in
3739 * the string. Legal characters are printing chars other than
3740 * ", *, ?, \, [ and ].
3742 static int illegalchars[] = {
3743 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
3744 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
3745 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
3746 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
3747 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* : - O */
3748 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* P - _ */
3749 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
3750 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
3751 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3752 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3753 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3754 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3755 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3756 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3757 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3758 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3765 if (illegalchars[*s++])
3766 return(MR_BAD_CHAR);
3771 validate_id(q, argv, vo)
3774 register struct valobj *vo;
3776 EXEC SQL BEGIN DECLARE SECTION;
3777 char *name, *tbl, *namefield, *idfield;
3779 EXEC SQL END DECLARE SECTION;
3783 name = argv[vo->index];
3785 namefield = vo->namefield;
3786 idfield = vo->idfield;
3788 if ((!strcmp(tbl, "users") && !strcmp(namefield, "login")) ||
3789 !strcmp(tbl, "machine") ||
3790 !strcmp(tbl, "filesys") ||
3791 !strcmp(tbl, "list") ||
3792 !strcmp(tbl, "cluster") ||
3793 !strcmp(tbl, "strings")) {
3794 if (!strcmp(tbl, "machine"))
3795 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3796 status = name_to_id(name, tbl, &id);
3798 *(int *)argv[vo->index] = id;
3800 } else if (status == MR_NO_MATCH && !strcmp(tbl, "strings") &&
3801 (q->type == APPEND || q->type == UPDATE)) {
3802 id=add_string(name);
3803 cache_entry(name, "STRING", id);
3804 *(int *)argv[vo->index] = id;
3806 } else if (status == MR_NO_MATCH || status == MR_NOT_UNIQUE)
3812 if (!strcmp(namefield, "uid")) {
3813 sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s = %s",idfield,tbl,namefield,name);
3815 sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s = '%s'",idfield,tbl,namefield,name);
3817 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3819 return(MR_INTERNAL);
3820 EXEC SQL DECLARE csr127 CURSOR FOR stmt;
3821 EXEC SQL OPEN csr127;
3823 EXEC SQL FETCH csr127 USING DESCRIPTOR :SQLDA;
3824 if(sqlca.sqlcode == 0) {
3826 EXEC SQL FETCH csr127 USING DESCRIPTOR :SQLDA;
3827 if(sqlca.sqlcode == 0) rowcount++;
3829 EXEC SQL CLOSE csr127;
3833 if (rowcount != 1) return(vo->error);
3834 bcopy(SQLDA->sqlvar[0].sqldata,argv[vo->index],sizeof(int));
3838 validate_name(argv, vo)
3840 register struct valobj *vo;
3842 EXEC SQL BEGIN DECLARE SECTION;
3843 char *name, *tbl, *namefield;
3845 EXEC SQL END DECLARE SECTION;
3848 name = argv[vo->index];
3850 namefield = vo->namefield;
3851 if (!strcmp(tbl, "servers") && !strcmp(namefield, "name")) {
3852 for (c = name; *c; c++)
3856 sprintf(stmt_buf,"SELECT DISTINCT COUNT(*) FROM %s WHERE %s.%s = '%s'",
3857 tbl,tbl,namefield,name);
3858 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3860 return(MR_INTERNAL);
3861 EXEC SQL DECLARE csr128 CURSOR FOR stmt;
3862 EXEC SQL OPEN csr128;
3863 EXEC SQL FETCH csr128 USING DESCRIPTOR :SQLDA;
3864 rowcount = *(int *)SQLDA->sqlvar[0].sqldata;
3865 EXEC SQL CLOSE csr128;
3867 if (ingres_errno) return(mr_errcode);
3868 return ((rowcount == 1) ? MR_EXISTS : vo->error);
3871 validate_date(argv, vo)
3875 EXEC SQL BEGIN DECLARE SECTION;
3879 EXEC SQL END DECLARE SECTION;
3881 idate = argv[vo->index];
3882 EXEC SQL SELECT interval('years',date(:idate)-date('today')) INTO :dd;
3884 if (sqlca.sqlcode != 0 || dd > 5.0) return(MR_DATE);
3889 validate_rename(argv, vo)
3893 EXEC SQL BEGIN DECLARE SECTION;
3894 char *name, *tbl, *namefield, *idfield;
3896 EXEC SQL END DECLARE SECTION;
3900 c = name = argv[vo->index];
3902 if (illegalchars[*c++])
3903 return(MR_BAD_CHAR);
3905 /* minor kludge to upcasify machine names */
3906 if (!strcmp(tbl, "machine"))
3907 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3908 namefield = vo->namefield;
3909 idfield = vo->idfield;
3912 if (!strcmp(argv[vo->index], argv[vo->index - 1]))
3914 sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s = LEFT('%s',SIZE(%s))",
3915 namefield,tbl,namefield,name,namefield);
3916 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3918 return(MR_INTERNAL);
3919 EXEC SQL DECLARE csr129 CURSOR FOR stmt;
3920 EXEC SQL OPEN csr129;
3921 EXEC SQL FETCH csr129 USING DESCRIPTOR :SQLDA;
3922 if(sqlca.sqlcode == 0) id=1; else id=0;
3923 EXEC SQL CLOSE csr129;
3925 if (ingres_errno) return(mr_errcode);
3931 status = name_to_id(name, tbl, &id);
3932 if (status == MR_NO_MATCH || id == *(int *)argv[vo->index - 1])
3939 validate_type(argv, vo)
3941 register struct valobj *vo;
3943 EXEC SQL BEGIN DECLARE SECTION;
3947 EXEC SQL END DECLARE SECTION;
3950 typename = vo->table;
3951 c = val = argv[vo->index];
3953 if (illegalchars[*c++])
3954 return(MR_BAD_CHAR);
3957 /* uppercase type fields */
3958 for (c = val; *c; c++) if (islower(*c)) *c = toupper(*c);
3960 EXEC SQL SELECT COUNT(trans) INTO :cnt FROM alias
3961 WHERE name = :typename AND type='TYPE' AND trans = :val;
3962 if (ingres_errno) return(mr_errcode);
3963 return (cnt ? MR_EXISTS : vo->error);
3966 /* validate member or type-specific data field */
3968 validate_typedata(q, argv, vo)
3969 register struct query *q;
3970 register char *argv[];
3971 register struct valobj *vo;
3973 EXEC SQL BEGIN DECLARE SECTION;
3976 char data_type[129];
3978 EXEC SQL END DECLARE SECTION;
3983 /* get named object */
3984 name = argv[vo->index];
3986 /* get field type string (known to be at index-1) */
3987 field_type = argv[vo->index-1];
3989 /* get corresponding data type associated with field type name */
3990 EXEC SQL SELECT trans INTO :data_type FROM alias
3991 WHERE name = :field_type AND type='TYPEDATA';
3992 if (ingres_errno) return(mr_errcode);
3993 if (sqlca.sqlerrd[2] != 1) return(MR_TYPE);
3995 /* now retrieve the record id corresponding to the named object */
3996 if (index(data_type, ' '))
3997 *index(data_type, ' ') = 0;
3998 if (!strcmp(data_type, "user")) {
4000 if (index(name, '@'))
4002 status = name_to_id(name, data_type, &id);
4003 if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
4005 if (status) return(status);
4006 } else if (!strcmp(data_type, "list")) {
4008 status = name_to_id(name, data_type, &id);
4009 if (status && status == MR_NOT_UNIQUE)
4011 if (status == MR_NO_MATCH) {
4012 /* if idfield is non-zero, then if argv[0] matches the string
4013 * that we're trying to resolve, we should get the value of
4014 * numvalues.[idfield] for the id.
4016 if (vo->idfield && !strcmp(argv[0], argv[vo->index])) {
4017 set_next_object_id(q->validate->object_id, q->rtable, 0);
4019 EXEC SQL REPEATED SELECT value INTO :id FROM numvalues
4021 if (sqlca.sqlerrd[2] != 1) return(MR_LIST);
4024 } else if (status) return(status);
4025 } else if (!strcmp(data_type, "machine")) {
4027 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
4028 status = name_to_id(name, data_type, &id);
4029 if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
4031 if (status) return(status);
4032 } else if (!strcmp(data_type, "string")) {
4034 status = name_to_id(name, data_type, &id);
4035 if (status && status == MR_NOT_UNIQUE)
4037 if (status == MR_NO_MATCH) {
4038 if (q->type != APPEND && q->type != UPDATE) return(MR_STRING);
4039 id=add_string(name);
4040 cache_entry(name, "STRING", id);
4041 } else if (status) return(status);
4042 } else if (!strcmp(data_type, "none")) {
4048 /* now set value in argv */
4049 *(int *)argv[vo->index] = id;
4055 /* Lock the table named by the validation object */
4060 sprintf(stmt_buf,"UPDATE %s SET modtime='now' WHERE %s.%s = 0",
4061 vo->table,vo->table,vo->idfield);
4062 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
4063 if (ingres_errno) return(mr_errcode);
4064 if (sqlca.sqlerrd[2] != 1)
4071 /* Check the database at startup time. For now this just resets the
4072 * inprogress flags that the DCM uses.
4075 sanity_check_database()
4080 /* Dynamic SQL support routines */
4081 MR_SQLDA_T *mr_alloc_SQLDA()
4084 short *null_indicators;
4087 if((it=(MR_SQLDA_T *)malloc(sizeof(MR_SQLDA_T)))==NULL) {
4088 com_err(whoami, MR_NO_MEM, "setting up SQLDA");
4092 if((null_indicators=(short *)calloc(QMAXARGS,sizeof(short)))==NULL) {
4093 com_err(whoami, MR_NO_MEM, "setting up SQLDA null indicators");
4097 for(j=0; j<QMAXARGS; j++) {
4098 if((it->sqlvar[j].sqldata=malloc(sizeof(short)+ARGLEN))==NULL) {
4099 com_err(whoami, MR_NO_MEM, "setting up SQLDA variables");
4102 it->sqlvar[j].sqllen=ARGLEN;
4103 it->sqlvar[j].sqlind=null_indicators+j;
4104 null_indicators[j]=0;
4111 /* Use this after FETCH USING DESCRIPTOR one or more
4112 * result columns may contain NULLs. This routine is
4113 * not currently needed, since db/schema creates all
4114 * columns with a NOT NULL WITH DEFAULT clause.
4116 * This is currently dead flesh, since no Moira columns
4117 * allow null values; all use default values.
4119 mr_fix_nulls_in_SQLDA(da)
4122 register IISQLVAR *var;
4126 for(j=0, var=da->sqlvar; j<da->sqld; j++, var++) {
4127 switch(var->sqltype) {
4128 case -IISQ_CHA_TYPE:
4132 case -IISQ_INT_TYPE:
4134 intp=(int *)var->sqldata;
4142 /* prefetch_value():
4143 * This routine fetches an appropriate value from the numvalues table.
4144 * It is a little hack to get around the fact that SQL doesn't let you
4145 * do something like INSERT INTO table (foo) VALUES (other_table.bar).
4147 * It is called from the query table as (*v->pre_rtn)(q,Argv,cl) or
4148 * from within a setup_...() routine with the appropriate arguments.
4150 * Correct functioning of this routine may depend on the assumption
4151 * that this query is an APPEND.
4154 prefetch_value(q,argv,cl)
4159 EXEC SQL BEGIN DECLARE SECTION;
4160 char *name = q->validate->object_id;
4162 EXEC SQL END DECLARE SECTION;
4163 int status, limit, argc;
4165 /* set next object id, limiting it if necessary */
4166 if(!strcmp(name, "uid") || !strcmp(name, "gid"))
4167 limit = 1; /* So far as I know, this isn't needed. Just CMA. */
4170 if((status = set_next_object_id(name, q->rtable, limit)) != MR_SUCCESS)
4173 /* fetch object id */
4174 EXEC SQL SELECT value INTO :value FROM numvalues WHERE name=:name;
4175 if(ingres_errno) return(mr_errcode);
4176 if(sqlca.sqlerrd[2] != 1) return(MR_INTERNAL);
4178 argc = q->argc + q->vcnt; /* end of Argv for APPENDs */
4179 sprintf(argv[argc],"%d",value); /** Could save this step by changing tlist from %s to %d **/
4184 /* prefetch_filesys():
4185 * Fetches the phys_id from filesys based on the filsys_id in argv[0].
4186 * Appends the filsys_id and the phys_id to the argv so they can be
4187 * referenced in an INSERT into a table other than filesys. Also
4188 * see comments at prefetch_value().
4190 * Assumes the existence of a row where filsys_id = argv[0], since a
4191 * filesys label has already been resolved to a filsys_id.
4193 prefetch_filesys(q,argv,cl)
4198 EXEC SQL BEGIN DECLARE SECTION;
4200 EXEC SQL END DECLARE SECTION;
4203 fid = *(int *)argv[0];
4204 EXEC SQL SELECT phys_id INTO :phid FROM filesys WHERE filsys_id = :fid;
4205 if(ingres_errno) return(mr_errcode);
4207 argc=q->argc+q->vcnt;
4208 sprintf(argv[argc++],"%d",phid);
4209 sprintf(argv[argc],"%d",fid);
4214 /* Convert normal Unix-style wildcards to SQL voodoo */
4215 convert_wildcards(arg)
4218 static char buffer[ARGLEN];
4219 register char *s, *d;
4221 for(d=buffer,s=arg;*s;s++) {
4223 case '*': *d++='%'; *d++='%'; break;
4224 case '?': *d++='_'; break;
4227 case ']': *d++='*'; *d++ = *s; break;
4228 case '%': *d++='*'; *d++='%'; *d++='%'; break;
4229 default: *d++ = *s; break;
4234 /* Copy back into argv */
4240 /* This version includes uppercase conversion, for things like gmac.
4241 * This is necessary because "LIKE" doesn't work with "uppercase()".
4242 * Including it in a wildcard routine saves making two passes over
4243 * the argument string.
4245 convert_wildcards_uppercase(arg)
4248 static char buffer[ARGLEN];
4249 register char *s, *d;
4251 for(d=buffer,s=arg;*s;s++) {
4253 case '*': *d++='%'; *d++='%'; break;
4254 case '?': *d++='_'; break;
4257 case ']': *d++='*'; *d++ = *s; break;
4258 case '%': *d++='*'; *d++='%'; *d++='%'; break;
4259 default: *d++=toupper(*s); break; /* This is the only diff. */
4264 /* Copy back into argv */
4271 /* Looks like it's time to build an abstraction barrier, Yogi */
4273 EXEC SQL BEGIN DECLARE SECTION;
4275 EXEC SQL END DECLARE SECTION;
4279 EXEC SQL PREPARE stmt FROM :stmt;
4280 EXEC SQL DESCRIBE stmt INTO :SQLDA;
4281 if(SQLDA->sqld==0) /* Not a SELECT */
4282 return(MR_INTERNAL);
4283 EXEC SQL DECLARE csr CURSOR FOR stmt;
4285 EXEC SQL FETCH csr USING DESCRIPTOR :SQLDA;
4286 if(sqlca.sqlcode==0)
4288 else if((sqlca.sqlcode<0) && mr_errcode)
4304 fprintf(stderr, "Size: %d\n", strlen(p));
4305 while (strlen(p) >= 8) {
4306 fprintf(stderr, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
4307 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
4310 switch (strlen(p)) {
4312 fprintf(stderr, "%02x %02x %02x %02x %02x %02x %02x\n",
4313 p[0], p[1], p[2], p[3], p[4], p[5], p[6]);
4316 fprintf(stderr, "%02x %02x %02x %02x %02x %02x\n",
4317 p[0], p[1], p[2], p[3], p[4], p[5]);
4320 fprintf(stderr, "%02x %02x %02x %02x %02x\n",
4321 p[0], p[1], p[2], p[3], p[4]);
4324 fprintf(stderr, "%02x %02x %02x %02x\n",
4325 p[0], p[1], p[2], p[3]);
4328 fprintf(stderr, "%02x %02x %02x\n",
4332 fprintf(stderr, "%02x %02x\n",
4336 fprintf(stderr, "%02x\n",
4346 /* Adds a string to the string table. Returns the id number.
4349 int add_string(name)
4350 EXEC SQL BEGIN DECLARE SECTION;
4352 EXEC SQL END DECLARE SECTION;
4354 EXEC SQL BEGIN DECLARE SECTION;
4357 EXEC SQL END DECLARE SECTION;
4359 EXEC SQL SELECT value INTO :id FROM numvalues WHERE name = 'strings_id';
4361 EXEC SQL UPDATE numvalues SET value = :id WHERE name = 'strings_id';
4363 /* Use sprintf to get around problem with doubled single quotes */
4364 sprintf(buf,"INSERT INTO strings (string_id, string) VALUES (%d, '%s')",id,name);
4365 EXEC SQL EXECUTE IMMEDIATE :buf;
4371 /* eof:qsupport.dc */