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[];
34 EXEC SQL END DECLARE SECTION;
36 /* Specialized Access Routines */
38 /* access_user - verify that client name equals specified login name
40 * - since field validation routines are called first, a users_id is
41 * now in argv[0] instead of the login name.
44 EXEC SQL WHENEVER SQLERROR CALL ingerr;
46 access_user(q, argv, cl)
51 if (cl->users_id != *(int *)argv[0])
59 /* access_login - verify that client name equals specified login name
61 * argv[0...n] contain search info. q->
64 access_login(q, argv, cl)
69 EXEC SQL BEGIN DECLARE SECTION;
72 EXEC SQL END DECLARE SECTION;
74 build_qual(q->qual, q->argc, argv, qual);
75 if (!strncmp(q->name,"get_user_account",strlen("get_user_account"))) {
76 EXEC SQL SELECT users_id INTO :id FROM users u, strings str WHERE :qual;
78 EXEC SQL SELECT users_id INTO :id FROM users u WHERE :qual;
81 if (sqlca.sqlerrd[2] != 1 || id != cl->users_id)
89 /* access_list - check access for most list operations
91 * Inputs: argv[0] - list_id
93 * argv[2] - member ID (only for queries "amtl" and "dmfl")
94 * argv[7] - group IID (only for query "ulis")
97 * - check that client is a member of the access control list
98 * - OR, if the query is add_member_to_list or delete_member_from_list
99 * and the list is public, allow access if client = member
102 access_list(q, argv, cl)
107 EXEC SQL BEGIN DECLARE SECTION;
108 int list_id, acl_id, flags, gid;
110 EXEC SQL END DECLARE SECTION;
112 int client_id, status;
114 list_id = *(int *)argv[0];
115 EXEC SQL SELECT acl_id, acl_type, gid, publicflg
116 INTO :acl_id, :acl_type, :gid, :flags
118 WHERE list_id = :list_id;
120 if (sqlca.sqlerrd[2] != 1)
123 /* parse client structure */
124 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
127 /* if amtl or dmfl and list is public allow client to add or delete self */
128 if (((!strcmp("amtl", q->shortname) && flags) ||
129 (!strcmp("dmfl", q->shortname))) &&
130 (!strcmp("USER", argv[1]))) {
131 if (*(int *)argv[2] == client_id) return(MR_SUCCESS);
132 /* if update_list, don't allow them to change the GID */
133 } else if (!strcmp("ulis", q->shortname)) {
134 if ((!strcmp(argv[7], UNIQUE_GID) && (gid != -1)) ||
135 (strcmp(argv[7], UNIQUE_GID) && (gid != atoi(argv[7]))))
139 /* check for client in access control list */
140 status = find_member(acl_type, acl_id, client_type, client_id, 0);
141 if (!status) return(MR_PERM);
147 /* access_visible_list - allow access to list only if it is not hidden,
148 * or if the client is on the ACL
150 * Inputs: argv[0] - list_id
151 * cl - client identifier
154 access_visible_list(q, argv, cl)
159 EXEC SQL BEGIN DECLARE SECTION;
160 int list_id, acl_id, flags ;
162 EXEC SQL END DECLARE SECTION;
164 int client_id, status;
166 list_id = *(int *)argv[0];
167 EXEC SQL SELECT hidden, acl_id, acl_type
168 INTO :flags, :acl_id, :acl_type
170 WHERE list_id = :list_id;
171 if (sqlca.sqlerrd[2] != 1)
176 /* parse client structure */
177 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
180 /* check for client in access control list */
181 status = find_member(acl_type, acl_id, client_type, client_id, 0);
189 /* access_vis_list_by_name - allow access to list only if it is not hidden,
190 * or if the client is on the ACL
192 * Inputs: argv[0] - list name
193 * cl - client identifier
196 access_vis_list_by_name(q, argv, cl)
201 EXEC SQL BEGIN DECLARE SECTION;
202 int acl_id, flags, rowcount;
203 char acl_type[9], *listname;
204 EXEC SQL END DECLARE SECTION;
206 int client_id, status;
209 EXEC SQL SELECT hidden, acl_id, acl_type INTO :flags, :acl_id, :acl_type
210 FROM list WHERE name = :listname;
212 rowcount=sqlca.sqlerrd[2];
220 /* parse client structure */
221 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
224 /* check for client in access control list */
225 status = find_member(acl_type, acl_id, client_type, client_id, 0);
233 /* access_member - allow user to access member of type "USER" and name matches
234 * username, or to access member of type "LIST" and list is one that user is
235 * on the acl of, or the list is visible.
238 access_member(q, argv, cl)
243 if (!strcmp(argv[0], "LIST") || !strcmp(argv[0], "RLIST"))
244 return(access_visible_list(q, &argv[1], cl));
246 if (!strcmp(argv[0], "USER") || !strcmp(argv[0], "RUSER")) {
247 if (cl->users_id == *(int *)argv[1])
251 if (!strcmp(argv[0], "KERBEROS") || !strcmp(argv[0], "RKERBERO")) {
252 if (cl->client_id == *(int *)argv[1])
260 /* access_qgli - special access routine for Qualified_get_lists. Allows
261 * access iff argv[0] == "TRUE" and argv[2] == "FALSE".
264 access_qgli(q, argv, cl)
269 if (!strcmp(argv[0], "TRUE") && !strcmp(argv[2], "FALSE"))
275 /* access_service - allow access if user is on ACL of service. Don't
276 * allow access if a wildcard is used.
279 access_service(q, argv, cl)
284 EXEC SQL BEGIN DECLARE SECTION;
286 char *name, acl_type[9];
287 EXEC SQL END DECLARE SECTION;
288 int client_id, status;
289 char *client_type, *c;
292 for(c=name;*c;c++) if(islower(*c)) *c = toupper(*c); /* uppercasify */
293 EXEC SQL SELECT acl_id, acl_type INTO :acl_id, :acl_type FROM servers
295 if (sqlca.sqlerrd[2] > 1)
298 /* parse client structure */
299 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
302 /* check for client in access control list */
303 status = find_member(acl_type, acl_id, client_type, client_id, 0);
304 if (!status) return(MR_PERM);
310 /* access_filesys - verify that client is owner or on owners list of filesystem
314 access_filesys(q, argv, cl)
319 EXEC SQL BEGIN DECLARE SECTION;
320 int users_id, list_id;
322 EXEC SQL END DECLARE SECTION;
323 int status, client_id;
327 EXEC SQL SELECT owner, owners INTO :users_id, :list_id FROM filesys
330 if (sqlca.sqlerrd[2] != 1)
332 if (users_id == cl->users_id)
334 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
336 status = find_member("LIST", list_id, client_type, client_id, 0);
347 /* Setup routine for add_user
349 * Inputs: argv[0] - login
354 * - if argv[1] == UNIQUE_UID then set argv[1] = next(uid)
355 * - if argv[0] == UNIQUE_LOGIN then set argv[0] = "#<uid>"
358 setup_ausr(q, argv, cl)
360 register char *argv[];
364 EXEC SQL BEGIN DECLARE SECTION;
366 EXEC SQL END DECLARE SECTION;
368 if (!strcmp(q->shortname, "uusr") || !strcmp(q->shortname, "uuac"))
372 if (!strcmp(argv[row], UNIQUE_UID) || atoi(argv[row]) == -1) {
373 if (set_next_object_id("uid", "users", 1))
374 return(MR_INGRES_ERR);
375 EXEC SQL SELECT value INTO :nuid FROM numvalues WHERE name = 'uid';
376 if (sqlca.sqlerrd[2] != 1)
378 sprintf(argv[row], "%d", nuid);
381 if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[row]) == -1) {
382 sprintf(argv[0], "#%s", argv[row]);
385 if((mr_errcode=prefetch_value(q,argv,cl))!=MR_SUCCESS)
392 /* setup_dusr - verify that the user is no longer being referenced
393 * and may safely be deleted.
396 int setup_dusr(q, argv)
400 EXEC SQL BEGIN DECLARE SECTION;
402 EXEC SQL END DECLARE SECTION;
404 id = *(int *)argv[0];
406 /* For now, only allow users to be deleted if their status is 0 */
407 EXEC SQL REPEATED SELECT status INTO :flag FROM users
408 WHERE users_id = :id;
409 if (flag != 0 && flag != 4)
412 EXEC SQL REPEATED DELETE FROM quota WHERE entity_id = :id AND type = 'USER';
413 EXEC SQL REPEATED DELETE FROM krbmap WHERE users_id = :id;
414 EXEC SQL REPEATED SELECT member_id INTO :idummy FROM imembers
415 WHERE member_id = :id AND member_type = 'USER';
416 if (sqlca.sqlerrd[2] > 0)
418 EXEC SQL REPEATED SELECT label INTO :cdummy FROM filesys WHERE owner = :id;
419 if (sqlca.sqlerrd[2]> 0)
421 EXEC SQL REPEATED SELECT name INTO :cdummy FROM list
422 WHERE acl_id = :id AND acl_type = 'USER';
423 if (sqlca.sqlerrd[2] > 0)
425 EXEC SQL REPEATED SELECT name INTO :cdummy FROM servers
426 WHERE acl_id = :id AND acl_type = 'USER';
427 if (sqlca.sqlerrd[2] > 0)
429 EXEC SQL REPEATED SELECT acl_id INTO :idummy FROM hostaccess
430 WHERE acl_id = :id AND acl_type = 'USER';
431 if (sqlca.sqlerrd[2] > 0)
439 /* setup_spop: verify that there is already a valid POP machine_id in the
440 * pop_id field. Also take care of keeping track of the post office usage.
442 int setup_spop(q, argv)
446 EXEC SQL BEGIN DECLARE SECTION;
449 EXEC SQL END DECLARE SECTION;
451 id = *(int *)argv[0];
452 EXEC SQL REPEATED SELECT potype, pop_id INTO :type, :mid FROM users
453 WHERE users_id = :id;
454 if(sqlca.sqlerrd[2] = 0)
456 EXEC SQL REPEATED SELECT mach_id INTO :mid FROM machine
457 WHERE mach_id = :mid;
458 if (sqlca.sqlerrd[2] = 0)
460 if (strcmp(strtrim(type), "POP"))
461 set_pop_usage(mid, 1);
466 /* setup_dpob: Take care of keeping track of the post office usage.
468 int setup_dpob(q, argv)
472 EXEC SQL BEGIN DECLARE SECTION;
475 EXEC SQL END DECLARE SECTION;
477 user = *(int *)argv[0];
478 EXEC SQL REPEATED SELECT potype, pop_id INTO :type, :id FROM users
479 WHERE users_id = :user;
480 if (ingres_errno) return(mr_errcode);
482 if (!strcmp(strtrim(type), "POP"))
483 set_pop_usage(id, -1);
488 /* setup_dmac - verify that the machine is no longer being referenced
489 * and may safely be deleted.
492 int setup_dmac(q, argv)
496 EXEC SQL BEGIN DECLARE SECTION;
498 EXEC SQL END DECLARE SECTION;
500 id = *(int *)argv[0];
501 EXEC SQL REPEATED SELECT login INTO :cdummy FROM users
502 WHERE potype='POP' AND pop_id = :id;
503 if (sqlca.sqlerrd[2] > 0)
505 EXEC SQL REPEATED SELECT mach_id INTO :idummy FROM serverhosts
507 if (sqlca.sqlerrd[2] > 0)
509 EXEC SQL REPEATED SELECT mach_id INTO :idummy FROM nfsphys
511 if (sqlca.sqlerrd[2] > 0)
513 EXEC SQL REPEATED SELECT mach_id INTO :idummy FROM hostaccess
515 if (sqlca.sqlerrd[2] > 0)
517 EXEC SQL REPEATED SELECT mach_id INTO :idummy FROM printcap
519 if (sqlca.sqlerrd[2] > 0)
521 EXEC SQL REPEATED SELECT quotaserver INTO :idummy FROM printcap
522 WHERE quotaserver = :id;
523 if (sqlca.sqlerrd[2] > 0)
525 EXEC SQL REPEATED SELECT mach_id INTO :idummy FROM palladium
527 if (sqlca.sqlerrd[2] > 0)
530 EXEC SQL REPEATED DELETE FROM mcmap WHERE mach_id = :id;
531 if (ingres_errno) return(mr_errcode);
536 /* setup_dclu - verify that the cluster is no longer being referenced
537 * and may safely be deleted.
540 int setup_dclu(q, argv)
544 EXEC SQL BEGIN DECLARE SECTION;
546 EXEC SQL END DECLARE SECTION;
548 id = *(int *)argv[0];
549 EXEC SQL REPEATED SELECT mach_id INTO :idummy FROM mcmap
551 if (sqlca.sqlerrd[2] > 0)
553 EXEC SQL REPEATED SELECT clu_id INTO :idummy FROM svc
555 if (sqlca.sqlerrd[2] > 0)
563 /* setup_alis - if argv[5] is non-zero and argv[6] is UNIQUE_ID, then allocate
564 * a new gid and put it in argv[6]. Otherwise if argv[6] is UNIQUE_ID but
565 * argv[5] is not, then remember that UNIQUE_ID is being stored by putting
566 * a -1 there. Remember that this is also used for ulis, with the indexes
567 * at 6 & 7. Also check that the list name does not contain uppercase
568 * characters, control characters, @, or :.
571 static int badlistchars[] = {
572 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
573 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
574 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
575 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, /* 0 - ? */
576 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
577 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, /* P - _ */
578 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
579 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
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,
587 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
590 int setup_alis(q, argv, cl)
595 EXEC SQL BEGIN DECLARE SECTION;
597 EXEC SQL END DECLARE SECTION;
602 if (!strcmp(q->shortname, "alis"))
604 else if (!strcmp(q->shortname, "ulis"))
607 for (p = (unsigned char *) argv[idx]; *p; p++)
608 if (badlistchars[*p])
611 if (!strcmp(argv[6 + idx], UNIQUE_GID) || atoi(argv[6 + idx]) == -1) {
612 if (atoi(argv[5 + idx])) {
613 if (set_next_object_id("gid", "list", 1))
614 return(MR_INGRES_ERR);
615 EXEC SQL REPEATED SELECT value INTO :ngid FROM numvalues
617 if (ingres_errno) return(mr_errcode);
618 sprintf(argv[6 + idx], "%d", ngid);
620 strcpy(argv[6 + idx], "-1");
624 if((mr_errcode=prefetch_value(q,argv,cl))!=MR_SUCCESS)
631 /* setup_dlis - verify that the list is no longer being referenced
632 * and may safely be deleted.
635 int setup_dlis(q, argv)
641 id = *(int *)argv[0];
642 sprintf(stmt_buf,"SELECT member_id FROM imembers WHERE member_id = %d AND member_type='LIST'",id);
643 if(ec=mr_select_any(stmt_buf)) {
644 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
647 sprintf(stmt_buf,"SELECT member_id FROM imembers WHERE list_id = %d",id);
648 if(ec=mr_select_any(stmt_buf)) {
649 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
652 sprintf(stmt_buf,"SELECT label FROM filesys WHERE owners = %d",id);
653 if(ec=mr_select_any(stmt_buf)) {
654 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
657 sprintf(stmt_buf,"SELECT tag FROM capacls WHERE list_id = %d",id);
658 if(ec=mr_select_any(stmt_buf)) {
659 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
662 sprintf(stmt_buf,"SELECT name FROM list WHERE acl_id = %d AND acl_type='LIST' AND list_id != %d",id,id);
663 if(ec=mr_select_any(stmt_buf)) {
664 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
667 sprintf(stmt_buf,"SELECT name FROM servers WHERE acl_id = %d AND acl_type='LIST'",id);
668 if(ec=mr_select_any(stmt_buf)) {
669 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
672 sprintf(stmt_buf,"SELECT entity_id FROM quota WHERE entity_id = %d AND type='GROUP'",id);
673 if(ec=mr_select_any(stmt_buf)) {
674 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
677 sprintf(stmt_buf,"SELECT acl_id FROM hostaccess WHERE acl_id = %d AND acl_type='LIST'",id);
678 if(ec=mr_select_any(stmt_buf)) {
679 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
682 sprintf(stmt_buf,"SELECT class FROM zephyr z \
683 WHERE z.xmt_type = 'LIST' AND z.xmt_id = %d \
684 OR z.sub_type = 'LIST' AND z.sub_id = %d \
685 OR z.iws_type = 'LIST' AND z.iws_id = %d \
686 OR z.iui_type = 'LIST' AND z.iui_id = %d",id,id,id,id);
687 if(ec=mr_select_any(stmt_buf)) {
688 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
695 /* setup_dsin - verify that the service is no longer being referenced
696 * and may safely be deleted.
699 int setup_dsin(q, argv)
703 EXEC SQL BEGIN DECLARE SECTION;
706 EXEC SQL END DECLARE SECTION;
708 sprintf(stmt_buf,"SELECT service FROM serverhosts WHERE service = UPPERCASE('%s')",argv[0]);
709 if(ec=mr_select_any(stmt_buf)) {
717 EXEC SQL SELECT inprogress INTO :ec FROM servers
718 WHERE name=UPPERCASE(:svrname);
728 /* setup_dshi - verify that the service-host is no longer being referenced
729 * and may safely be deleted.
732 int setup_dshi(q, argv)
736 EXEC SQL BEGIN DECLARE SECTION;
739 EXEC SQL END DECLARE SECTION;
742 id = *(int *)argv[1];
744 EXEC SQL SELECT inprogress INTO :ec FROM serverhosts
745 WHERE service=UPPERCASE(:svrname) AND mach_id = :id;
757 ** setup_add_filesys - verify existance of referenced file systems
769 ** * extract directory prefix from name
770 ** * verify mach_id/dir in nfsphys
771 ** * verify access in {r, w, R, W}
773 ** Side effect: sets variable var_phys_id to the ID of the physical
774 ** filesystem (nfsphys_id for NFS, 0 for RVD)
777 ** MR_NFS - specified directory not exported
778 ** MR_FILESYS_ACCESS - invalid filesys access
782 EXEC SQL BEGIN DECLARE SECTION;
783 static int var_phys_id;
784 EXEC SQL END DECLARE SECTION;
786 setup_afil(q, argv, cl)
793 EXEC SQL BEGIN DECLARE SECTION;
795 char ftype[32], *access;
796 EXEC SQL END DECLARE SECTION;
799 mach_id = *(int *)argv[2];
804 sprintf(ftype, "fs_access_%s", type);
805 EXEC SQL SELECT trans INTO :cdummy FROM alias
806 WHERE name = :ftype AND type = 'TYPE' and trans = :access; /** Use mr_select_any() */
807 if (ingres_errno) return(mr_errcode);
808 if (sqlca.sqlerrd[2] == 0) return(MR_FILESYS_ACCESS);
810 if((mr_errcode=prefetch_value(q,argv,cl))!=MR_SUCCESS)
813 if (!strcmp(type, "NFS"))
814 return (check_nfs(mach_id, name, access));
820 /* Verify the arguments, depending on the FStype. Also, if this is an
821 * NFS filesystem, then update any quotas for that filesystem to reflect
825 setup_ufil(q, argv, cl)
832 EXEC SQL BEGIN DECLARE SECTION;
834 char *entity, ftype[32], *access;
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 trans INTO :cdummy FROM alias
848 WHERE name = :ftype AND type='TYPE' AND trans = :access;
849 if (ingres_errno) return(mr_errcode);
850 if (sqlca.sqlerrd[2] == 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 FROM quota
868 WHERE filsys_id = :fid AND phys_id != 0;
869 if (ingres_errno) return(mr_errcode);
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
916 EXEC SQL OPEN csr101;
918 EXEC SQL FETCH csr101 INTO :var_phys_id, :dir;
919 if(sqlca.sqlcode != 0) break;
923 if (*cp1++ != *cp2) break;
931 EXEC SQL CLOSE csr101;
938 /* setup_dfil: free any quota records and fsgroup info associated with
939 * a filesystem when it is deleted. Also adjust the allocation numbers.
942 setup_dfil(q, argv, cl)
947 EXEC SQL BEGIN DECLARE SECTION;
948 int id, total, phys_id;
950 EXEC SQL END DECLARE SECTION;
952 id = *(int *)argv[0];
953 EXEC SQL REPEATED SELECT SUM (quota) INTO :total:none FROM quota
954 WHERE filsys_id = :id;
958 /** What if there are multiple phys_id's per f/s? (bad data) **/
959 EXEC SQL REPEATED SELECT phys_id INTO :phys_id FROM filesys
960 WHERE filsys_id = :id;
961 EXEC SQL REPEATED UPDATE nfsphys SET allocated = allocated - :total
962 WHERE nfsphys_id = :phys_id;
965 EXEC SQL REPEATED DELETE FROM quota WHERE filsys_id = :id;
967 EXEC SQL REPEATED DELETE FROM fsgroup WHERE filsys_id = :id;
968 EXEC SQL REPEATED DELETE FROM fsgroup WHERE group_id = :id;
969 if (ingres_errno) return(mr_errcode);
974 /* setup_dnfp: check to see that the nfs physical partition does not have
975 * any filesystems assigned to it before allowing it to be deleted.
978 setup_dnfp(q, argv, cl)
983 EXEC SQL BEGIN DECLARE SECTION;
986 EXEC SQL END DECLARE SECTION;
988 id = *(int *)argv[0];
990 EXEC SQL REPEATED SELECT label INTO :cdummy FROM filesys fs, nfsphys np
991 WHERE fs.mach_id = :id AND fs.phys_id = np.nfsphys_id
992 AND np.mach_id = :id AND np.dir = :dir;
993 if (sqlca.sqlerrd[2] > 0)
1001 /* setup_dqot: Remove allocation from nfsphys before deleting quota.
1002 * argv[0] = filsys_id
1003 * argv[1] = type if "update_quota" or "delete_quota"
1004 * argv[2 or 1] = users_id or list_id
1007 setup_dqot(q, argv, cl)
1012 EXEC SQL BEGIN DECLARE SECTION;
1013 int quota, fs, id, physid;
1015 EXEC SQL END DECLARE SECTION;
1017 fs = *(int *)argv[0];
1018 if (!strcmp(q->name, "update_quota") || !strcmp(q->name, "delete_quota")) {
1020 id = *(int *)argv[2];
1023 id = *(int *)argv[1];
1026 EXEC SQL REPEATED SELECT quota INTO :quota FROM quota
1027 WHERE type = :qtype AND entity_id = :id AND filsys_id = :fs;
1028 EXEC SQL REPEATED SELECT phys_id INTO :physid FROM filesys
1029 WHERE filsys_id = :fs;
1030 EXEC SQL REPEATED UPDATE nfsphys SET allocated = allocated - :quota
1031 WHERE nfsphys_id = :physid;
1033 if (ingres_errno) return(mr_errcode);
1038 /* setup_sshi: don't exclusive lock the machine table during
1039 * set_server_host_internal.
1041 /** Not allowed under (INGRES) SQL **/
1042 setup_sshi(q, argv, cl)
1049 EXEC SQL set lockmode session where readlock = system;
1055 /* setup add_kerberos_user_mapping: add the string to the string
1056 * table if necessary.
1059 setup_akum(q, argv, cl)
1064 EXEC SQL BEGIN DECLARE SECTION;
1067 EXEC SQL END DECLARE SECTION;
1070 if (name_to_id(name, "STRING", &id) != MR_SUCCESS) {
1071 if (q->type != APPEND) return(MR_STRING);
1072 EXEC SQL SELECT value INTO :id FROM numvalues
1073 WHERE name = 'strings_id';
1075 EXEC SQL UPDATE numvalues SET value = :id
1076 WHERE name = 'strings_id';
1077 EXEC SQL INSERT INTO strings (string_id, string) VALUES (:id, :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);
1460 com_err(whoami, 0, "rawsig length = %d, sig=\"%s\"", strlen(si.rawsig), si.rawsig);
1462 GDSS_Recompose(&si, sigbuf);
1464 free(argv[U_SIGNATURE]);
1465 argv[U_SIGNATURE] = strsave(sigbuf);
1467 com_err(whoami, 0, "generated signature length %d", strlen(sigbuf));
1471 (*action)(q->vcnt, argv, actarg);
1472 for (j = 0; j < q->vcnt; j++)
1482 ** followup_ausr - add finger and pobox entries, set_user_modtime
1485 ** argv[0] - login (add_user)
1486 ** argv[3] - last name
1487 ** argv[4] - first name
1488 ** argv[5] - middle name
1492 followup_ausr(q, argv, cl)
1497 EXEC SQL BEGIN DECLARE SECTION;
1498 int who, status, id;
1499 char *login, *entity, *src, *dst, *name;
1501 EXEC SQL END DECLARE SECTION;
1503 char databuf[32], *kname_unparse();
1504 EXEC SQL BEGIN DECLARE SECTION;
1506 int sigwho, timestamp;
1507 EXEC SQL END DECLARE SECTION;
1511 /* build fullname */
1512 if (strlen(argv[4]) && strlen(argv[5]))
1513 sprintf(fullname, "%s %s %s", argv[4], argv[5], argv[3]);
1514 else if (strlen(argv[4]))
1515 sprintf(fullname, "%s %s", argv[4], argv[3]);
1517 sprintf(fullname, "%s", argv[3]);
1520 if (q->vcnt == U_END && *argv[U_SIGNATURE]) {
1521 sprintf(databuf, "%s:%s", argv[U_NAME], argv[U_MITID]);
1522 /* skip bytes for timestamp & kname */
1523 si.rawsig = (unsigned char *) rawsig;
1524 status = GDSS_Verify(databuf, strlen(databuf), argv[U_SIGNATURE], &si);
1525 if (strlen(rawsig) > mr_sig_length) {
1526 com_err(whoami, 0, "GDSS signature would be truncated."); /** untested **/
1527 return(MR_INTERNAL);
1530 name = kname_unparse(si.pname, si.pinst, si.prealm);
1531 status = name_to_id(name, "STRING", &sigwho);
1532 if (status == MR_NO_MATCH) {
1533 EXEC SQL REPEATED SELECT value INTO :sigwho FROM numvalues
1534 WHERE name='strings_id';
1536 EXEC SQL REPEATED UPDATE numvalues SET value = :sigwho
1537 WHERE name='strings_id';
1538 EXEC SQL INSERT INTO strings (string_id, string)
1539 VALUES (:sigwho, :name);
1541 return(gdss2et(status));
1542 timestamp = si.timestamp;
1544 return(gdss2et(status));
1553 who = cl->client_id;
1554 entity = cl->entity;
1556 /* create finger entry, pobox & set modtime on user */
1558 EXEC SQL REPEATED UPDATE users
1559 SET modtime='now', modby=:who, modwith = :entity,
1560 fullname = :fullname, affiliation = type,
1561 signature = :rawsig, sigdate = :timestamp, sigwho = :sigwho,
1562 fmodtime='now', fmodby = :who, fmodwith = :entity,
1563 potype='NONE', pmodtime='now', pmodby = :who, pmodwith = :entity
1564 WHERE login = :login;
1566 EXEC SQL REPEATED UPDATE users
1567 SET modtime='now', modby=:who, modwith = :entity,
1568 fullname = :fullname, affiliation = type,
1569 fmodtime='now', fmodby = :who, fmodwith = :entity,
1570 potype='NONE', pmodtime='now', pmodby = :who, pmodwith = :entity
1571 WHERE login = :login;
1579 ** followup_uusr - do signature, set_user_modtime
1582 ** argv[0] - login (add_user)
1583 ** argv[U_SIGNATURE] - sig
1587 followup_uuac(q, argv, cl)
1592 EXEC SQL BEGIN DECLARE SECTION;
1593 int who, status, id;
1594 char *entity, *name;
1595 EXEC SQL END DECLARE SECTION;
1597 char databuf[32], *kname_unparse();
1598 EXEC SQL BEGIN DECLARE SECTION;
1601 int sigwho, timestamp;
1602 EXEC SQL END DECLARE SECTION;
1606 id = *(int *)argv[0];
1607 who = cl->client_id;
1608 entity = cl->entity;
1611 if (q->vcnt == U_MODTIME && *argv[U_SIGNATURE + 1]) {
1613 status = id_to_name(id, "USER", &login);
1614 sprintf(databuf, "%s:%s", login, argv[U_MITID+1]);
1616 /* skip bytes for timestamp & kname */
1617 si.rawsig = (unsigned char *) rawsig;
1619 com_err(whoami, 0, "verifying sig");
1621 status = GDSS_Verify(databuf, strlen(databuf), argv[U_SIGNATURE+1], &si);
1623 com_err(whoami, 0, "verified");
1625 if (strlen(rawsig) > mr_sig_length) {
1626 com_err(whoami, 0, "GDSS signature would be truncated."); /** untested **/
1627 return(MR_INTERNAL);
1630 name = kname_unparse(si.pname, si.pinst, si.prealm);
1631 status = name_to_id(name, "STRING", &sigwho);
1632 if (status == MR_NO_MATCH) {
1633 EXEC SQL REPEATED SELECT value INTO :sigwho FROM numvalues
1634 WHERE name='strings_id';
1636 EXEC SQL REPEATED UPDATE numvalues SET value = :sigwho
1637 WHERE name='strings_id';
1638 EXEC SQL INSERT INTO strings (string_id, string)
1639 VALUES (:sigwho, :name);
1641 return(gdss2et(status));
1642 timestamp = si.timestamp;
1644 return(gdss2et(status));
1652 /* create finger entry, pobox & set modtime on user */
1655 EXEC SQL REPEATED UPDATE users SET modtime='now', modby = :who, modwith = :entity,
1656 signature = :rawsig, sigdate = :timestamp, sigwho = :sigwho
1657 WHERE users_id = :id;
1659 EXEC SQL REPEATED UPDATE users SET modtime='now', modby = :who, modwith = :entity
1660 WHERE users_id = :id;
1666 /* followup_gpob: fixes argv[2] based on the IDs currently there and the
1667 * type in argv[1]. Then completes the upcall to the user.
1669 * argv[2] is of the form "123:234" where the first integer is the machine
1670 * ID if it is a pop box, and the second is the string ID if it is an SMTP
1671 * box. argv[1] should be "POP", "SMTP", or "NONE". Boxes of type NONE
1675 followup_gpob(q, sq, v, action, actarg, cl)
1676 register struct query *q;
1677 register struct save_queue *sq;
1678 register struct validate *v;
1679 register int (*action)();
1683 char **argv, *index();
1685 int mid, sid, status, i;
1688 while (sq_get_data(sq, &argv)) {
1689 mr_trim_args(2, argv);
1691 p = index(argv[2], ':');
1693 mid = atoi(argv[2]);
1696 if (!strcmp(ptype, "POP")) {
1697 status = id_to_name(mid, "MACHINE", &argv[2]);
1698 if (status == MR_NO_MATCH)
1700 } else if (!strcmp(ptype, "SMTP")) {
1701 status = id_to_name(sid, "STRING", &argv[2]);
1702 if (status == MR_NO_MATCH)
1704 } else /* ptype == "NONE" */ {
1707 if (status) return(status);
1709 if (!strcmp(q->shortname, "gpob")) {
1710 sid = atoi(argv[4]);
1712 status = id_to_name(sid, "USER", &argv[4]);
1714 status = id_to_name(-sid, "STRING", &argv[4]);
1716 if (status && status != MR_NO_MATCH) return(status);
1718 (*action)(q->vcnt, argv, actarg);
1720 /* free saved data */
1721 for (i = 0; i < q->vcnt; i++)
1727 return (MR_SUCCESS);
1731 /* followup_glin: fix the ace_name in argv[8]. argv[7] will contain the
1732 * ace_type: "LIST", "USER", or "NONE". Decode the id in argv[8] into the
1733 * proper name based on the type, and repace that string in the argv.
1734 * Also fixes the modby field by called followup_fix_modby.
1737 followup_glin(q, sq, v, action, actarg, cl)
1738 register struct query *q;
1739 register struct save_queue *sq;
1740 register struct validate *v;
1741 register int (*action)();
1745 char **argv, *malloc(), *realloc(), *type;
1746 int id, i, idx, status;
1749 if (!strcmp(q->shortname, "gsin"))
1752 while (sq_get_data(sq, &argv)) {
1753 mr_trim_args(q->vcnt, argv);
1755 id = atoi(argv[i = q->vcnt - 2]);
1757 status = id_to_name(id, "USER", &argv[i]);
1759 status = id_to_name(-id, "STRING", &argv[i]);
1760 if (status && status != MR_NO_MATCH)
1763 id = atoi(argv[idx]);
1764 type = argv[idx - 1];
1766 if (!strcmp(type, "LIST")) {
1767 status = id_to_name(id, "LIST", &argv[idx]);
1768 } else if (!strcmp(type, "USER")) {
1769 status = id_to_name(id, "USER", &argv[idx]);
1770 } else if (!strcmp(type, "KERBEROS")) {
1771 status = id_to_name(id, "STRING", &argv[idx]);
1772 } else if (!strcmp(type, "NONE")) {
1775 argv[idx] = strsave("NONE");
1779 argv[idx] = strsave("???");
1781 if (status && status != MR_NO_MATCH)
1784 if (!strcmp(q->shortname, "glin") && atoi(argv[6]) == -1) {
1785 argv[6] = realloc(argv[6], strlen(UNIQUE_GID) + 1);
1786 strcpy(argv[6], UNIQUE_GID);
1790 (*action)(q->vcnt, argv, actarg);
1792 /* free saved data */
1793 for (i = 0; i < q->vcnt; i++)
1799 return (MR_SUCCESS);
1803 /* followup_gqot: Fix the entity name, directory name & modby fields
1804 * argv[0] = filsys_id
1806 * argv[2] = entity_id
1807 * argv[3] = ascii(quota)
1810 followup_gqot(q, sq, v, action, actarg, cl)
1812 register struct save_queue *sq;
1814 register int (*action)();
1815 register int actarg;
1819 char **argv, *malloc();
1820 EXEC SQL BEGIN DECLARE SECTION;
1823 EXEC SQL END DECLARE SECTION;
1826 if (!strcmp(q->name, "get_quota") ||
1827 !strcmp(q->name, "get_quota_by_filesys"))
1831 while (sq_get_data(sq, &argv)) {
1833 switch (argv[1][0]) {
1835 status = id_to_name(atoi(argv[2]), "USER", &argv[2]);
1839 status = id_to_name(atoi(argv[2]), "LIST", &argv[2]);
1843 argv[2] = strsave("system:anyuser");
1847 argv[2] = malloc(8);
1848 sprintf(argv[2], "%d", id);
1851 id = atoi(argv[idx]);
1853 argv[idx] = malloc(256);
1857 EXEC SQL REPEATED SELECT name INTO :name FROM filesys
1858 WHERE label = :label;
1860 EXEC SQL REPEATED SELECT dir INTO :name FROM nfsphys
1861 WHERE nfsphys_id = :id;
1863 if (sqlca.sqlerrd[2] != 1) {
1864 sprintf(argv[idx], "#%d", id);
1867 id = atoi(argv[idx+3]);
1869 status = id_to_name(id, "USER", &argv[idx+3]);
1871 status = id_to_name(-id, "STRING", &argv[idx+3]);
1872 if (status && status != MR_NO_MATCH)
1874 (*action)(q->vcnt, argv, actarg);
1875 for (j = 0; j < q->vcnt; j++)
1884 /* followup_aqot: Add allocation to nfsphys after creating quota.
1885 * argv[0] = filsys_id
1886 * argv[1] = type if "add_quota" or "update_quota"
1888 * argv[3 or 2] = ascii(quota)
1891 followup_aqot(q, argv, cl)
1896 EXEC SQL BEGIN DECLARE SECTION;
1897 int quota, id, fs, who, physid;
1898 char *entity, *qtype, *table_name;
1899 EXEC SQL END DECLARE SECTION;
1904 table_name=q->rtable;
1905 fs = *(int *)argv[0];
1906 EXEC SQL REPEATED SELECT phys_id INTO :physid FROM filesys
1907 WHERE filsys_id = :fs;
1911 if (!strcmp(q->shortname, "aqot") || !strcmp(q->shortname, "uqot")) {
1913 id = *(int *)argv[2];
1914 quota = atoi(argv[3]);
1915 sprintf(incr_qual,"q.filsys_id = %d",fs);
1918 id = *(int *)argv[1];
1919 quota = atoi(argv[2]);
1920 sprintf(incr_qual,"q.filsys_id=%d AND q.type='%s' AND q.entity_id=%d",
1924 /* quota case of incremental_{before|after} only looks at slot 1 */
1927 /* Follows one of many possible gross hacks to fix these particular
1928 * conflicts between what is possible in the query table and what
1929 * is possible in SQL.
1931 if(q->type==APPEND) {
1932 incremental_clear_before();
1933 EXEC SQL INSERT INTO quota
1934 (filsys_id, type, entity_id, quota, phys_id)
1935 VALUES (:fs, :qtype, :id, :quota, :physid);
1936 incremental_after(table_name, incr_qual, incr_argv);
1938 incremental_before(table_name, incr_qual, incr_argv);
1939 EXEC SQL UPDATE quota SET quota = :quota
1940 WHERE filsys_id = :fs AND type = :qtype AND entity_id = :id;
1941 status = mr_errcode;
1942 incremental_after(table_name, incr_qual, incr_argv);
1947 flush_name(argv[0], q->rtable);
1948 if(q->type==APPEND) {
1949 EXEC SQL UPDATE tblstats SET appends = appends + 1, modtime = 'now'
1950 WHERE table_name = :table_name;
1952 EXEC SQL UPDATE tblstats SET updates = updates + 1, modtime = 'now'
1953 WHERE table_name = :table_name;
1956 /* Proceed with original followup */
1957 who = cl->client_id;
1958 entity = cl->entity;
1960 EXEC SQL REPEATED UPDATE quota
1961 SET modtime = 'now', modby = :who, modwith = :entity
1962 WHERE filsys_id = :fs and type = :qtype and entity_id = :id;
1963 EXEC SQL REPEATED UPDATE nfsphys SET allocated = allocated + :quota
1964 WHERE nfsphys_id = :physid;
1965 if (ingres_errno) return(mr_errcode);
1970 /* Necessitated by the requirement of a correlation name by the incremental
1971 * routines, since query table deletes don't provide one.
1973 followup_dqot(q,argv,cl)
1981 EXEC SQL BEGIN DECLARE SECTION;
1984 EXEC SQL END DECLARE SECTION;
1986 fs = *(int *)argv[0];
1987 if (!strcmp(q->shortname, "dqot")) {
1989 id = *(int *)argv[2];
1992 id = *(int *)argv[1];
1994 sprintf(incr_qual,"q.filsys_id=%d AND q.type='%s' AND q.entity_id=%d",
1997 /* quota case of incremental_{before|after} only looks at slot 1 */
2000 incremental_before(q->rtable, incr_qual, incr_argv);
2001 EXEC SQL DELETE FROM quota q WHERE :incr_qual;
2002 incremental_clear_after();
2006 flush_name(argv[0], q->rtable);
2008 tblname = q->rtable;
2009 EXEC SQL UPDATE tblstats SET deletes = deletes + 1, modtime = 'now'
2010 WHERE table_name = :tblname;
2015 followup_gpce(q, sq, v, action, actarg, cl)
2017 register struct save_queue *sq;
2019 register int (*action)();
2020 register int actarg;
2024 char **argv, *malloc();
2028 while (sq_get_data(sq, &argv)) {
2029 id = atoi(argv[PCAP_QSERVER]);
2030 status = id_to_name(id, "MACHINE", &argv[PCAP_QSERVER]);
2031 if (status) return (status);
2034 status = id_to_name(id, "USER", &argv[i]);
2036 status = id_to_name(-id, "STRING", &argv[i]);
2037 if (status && status != MR_NO_MATCH)
2039 (*action)(q->vcnt, argv, actarg);
2040 for (j = 0; j < q->vcnt; j++)
2052 followup_gzcl(q, sq, v, action, actarg, cl)
2053 register struct query *q;
2054 register struct save_queue *sq;
2055 register struct validate *v;
2056 register int (*action)();
2063 while (sq_get_data(sq, &argv)) {
2064 mr_trim_args(q->vcnt, argv);
2066 id = atoi(argv[i = q->vcnt - 2]);
2068 status = id_to_name(id, "USER", &argv[i]);
2070 status = id_to_name(-id, "STRING", &argv[i]);
2071 if (status && status != MR_NO_MATCH)
2074 for (i = 1; i < 8; i+=2) {
2075 id = atoi(argv[i+1]);
2076 if (!strcmp(argv[i], "LIST")) {
2077 status = id_to_name(id, "LIST", &argv[i+1]);
2078 } else if (!strcmp(argv[i], "USER")) {
2079 status = id_to_name(id, "USER", &argv[i+1]);
2080 } else if (!strcmp(argv[i], "KERBEROS")) {
2081 status = id_to_name(id, "STRING", &argv[i+1]);
2082 } else if (!strcmp(argv[i], "NONE")) {
2085 argv[i+1] = strsave("NONE");
2089 argv[i+1] = strsave("???");
2091 if (status && status != MR_NO_MATCH)
2096 (*action)(q->vcnt, argv, actarg);
2098 /* free saved data */
2099 for (i = 0; i < q->vcnt; i++)
2111 followup_gsha(q, sq, v, action, actarg, cl)
2112 register struct query *q;
2113 register struct save_queue *sq;
2114 register struct validate *v;
2115 register int (*action)();
2122 while (sq_get_data(sq, &argv)) {
2123 mr_trim_args(q->vcnt, argv);
2127 status = id_to_name(id, "USER", &argv[4]);
2129 status = id_to_name(-id, "STRING", &argv[4]);
2130 if (status && status != MR_NO_MATCH)
2134 if (!strcmp(argv[1], "LIST")) {
2135 status = id_to_name(id, "LIST", &argv[2]);
2136 } else if (!strcmp(argv[1], "USER")) {
2137 status = id_to_name(id, "USER", &argv[2]);
2138 } else if (!strcmp(argv[1], "KERBEROS")) {
2139 status = id_to_name(id, "STRING", &argv[2]);
2140 } else if (!strcmp(argv[1], "NONE")) {
2143 argv[2] = strsave("NONE");
2147 argv[2] = strsave("???");
2149 if (status && status != MR_NO_MATCH)
2153 (*action)(q->vcnt, argv, actarg);
2155 /* free saved data */
2156 for (i = 0; i < q->vcnt; i++)
2166 /* Special query routines */
2168 /* set_pobox - this does all of the real work.
2169 * argv = user_id, type, box
2170 * if type is POP, then box should be a machine, and its ID should be put in
2171 * pop_id. If type is SMTP, then box should be a string and its ID should
2172 * be put in box_id. If type is NONE, then box doesn't matter.
2175 int set_pobox(q, argv, cl)
2180 EXEC SQL BEGIN DECLARE SECTION;
2182 char *box, potype[9];
2183 EXEC SQL END DECLARE SECTION;
2187 user = *(int *)argv[0];
2189 EXEC SQL REPEATED SELECT pop_id, potype INTO :id, :potype FROM users
2190 WHERE users_id = :user;
2191 if (ingres_errno) return(mr_errcode);
2192 if (!strcmp(strtrim(potype), "POP"))
2193 set_pop_usage(id, -1);
2195 if (!strcmp(argv[1], "POP")) {
2196 status = name_to_id(box, "MACHINE", &id);
2197 if (status == MR_NO_MATCH)
2201 EXEC SQL REPEATED UPDATE users SET potype = 'POP', pop_id = :id
2202 WHERE users_id = :user;
2203 set_pop_usage(id, 1);
2204 } else if (!strcmp(argv[1], "SMTP")) {
2205 if (index(box, '/') || index(box, '|'))
2206 return(MR_BAD_CHAR);
2207 status = name_to_id(box, "STRING", &id);
2208 if (status == MR_NO_MATCH) {
2209 EXEC SQL REPEATED SELECT value INTO :id FROM numvalues
2210 WHERE name='strings_id';
2212 EXEC SQL REPEATED UPDATE numvalues SET value = :id
2213 WHERE name='strings_id';
2214 EXEC SQL INSERT INTO strings (string_id, string)
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
2265 EXEC SQL OPEN csr102;
2268 EXEC SQL FETCH csr102 INTO :id;
2269 if(sqlca.sqlcode!=0) break;
2270 sq_save_data(sq, id);
2273 EXEC SQL CLOSE csr102;
2275 if (ingres_errno) return(mr_errcode);
2277 return(MR_NO_MATCH);
2279 argv[0] = listname; argv[1] = active; argv[2] = public; argv[3] = hidden;
2280 argv[4] = maillist; argv[5] = grouplist; argv[6] = gid_str;
2281 argv[7] = acl_type; argv[9] = desc; argv[10] = modtime; argv[12] = modwith;
2283 while (sq_get_data(sq, &id)) {
2287 EXEC SQL REPEATED SELECT name, CHAR(active), CHAR(publicflg),
2288 CHAR(hidden), hidden, CHAR(maillist), CHAR(grouplist), CHAR(gid),
2289 TRIM(acl_type), acl_id, description, CHAR(modtime), modby, modwith
2290 INTO :listname, :active, :public, :hidden, :hid, :maillist,
2291 :grouplist, :gid_str, :acl_type, :acl_id, :desc,
2292 :modtime, :modby_id, :modwith
2293 FROM list WHERE list_id = :id;
2295 if (ingres_errno) return(mr_errcode);
2297 if (atoi(gid_str) == -1)
2298 argv[6] = UNIQUE_GID;
2300 argv[8] = malloc(0);
2301 if (!strcmp(acl_type, "LIST")) {
2302 status = id_to_name(acl_id, "LIST", &argv[8]);
2303 } else if (!strcmp(acl_type, "USER")) {
2304 status = id_to_name(acl_id, "USER", &argv[8]);
2305 } else if (!strcmp(acl_type, "KERBEROS")) {
2306 status = id_to_name(acl_id, "STRING", &argv[8]);
2307 } else if (!strcmp(acl_type, "NONE")) {
2310 argv[8] = strsave("NONE");
2314 argv[8] = strsave("???");
2316 if (status && status != MR_NO_MATCH) return(status);
2318 argv[11] = malloc(0);
2320 status = id_to_name(modby_id, "USER", &argv[11]);
2322 status = id_to_name(-modby_id, "STRING", &argv[11]);
2323 if (status && status != MR_NO_MATCH) return(status);
2325 mr_trim_args(q->vcnt, argv);
2327 (*action)(q->vcnt, argv, actarg);
2333 if (ingres_errno) return(mr_errcode);
2334 return (MR_SUCCESS);
2338 /* Add_member_to_list: do list flattening as we go! MAXLISTDEPTH is
2339 * how many different ancestors a member is allowed to have.
2342 #define MAXLISTDEPTH 1024
2344 int add_member_to_list(q, argv, cl)
2349 EXEC SQL BEGIN DECLARE SECTION;
2350 int id, lid, mid, error, who, ref;
2351 char *mtype, dtype[9], *entity;
2352 EXEC SQL END DECLARE SECTION;
2353 int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a;
2354 int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d;
2356 char *dtypes[MAXLISTDEPTH];
2357 char *iargv[3], *buf;
2359 lid = *(int *)argv[0];
2361 mid = *(int *)argv[2];
2362 /* if the member is already a direct member of the list, punt */
2363 EXEC SQL REPEATED SELECT list_id INTO :idummy FROM imembers
2364 WHERE list_id = :lid AND member_id = :mid
2365 AND member_type = :mtype AND direct = 1;
2366 if (sqlca.sqlerrd[2] > 0)
2368 if (!strcasecmp(mtype, "STRING")) {
2370 status = id_to_name(mid, "STRING", &buf);
2371 if (status) return(status);
2372 if (index(buf, '/') || index(buf, '|')) {
2374 return(MR_BAD_CHAR);
2382 EXEC SQL DECLARE csr103 CURSOR FOR
2383 SELECT list_id, ref_count FROM imembers
2384 WHERE member_id = :lid AND member_type='LIST';
2385 EXEC SQL OPEN csr103;
2387 EXEC SQL FETCH csr103 INTO :id, :ref;
2388 if(sqlca.sqlcode != 0) break;
2390 ancestors[acount++] = id;
2391 if (acount >= MAXLISTDEPTH) break;
2393 EXEC SQL CLOSE csr103;
2394 if (ingres_errno) return(mr_errcode);
2395 if (acount >= MAXLISTDEPTH) {
2396 return(MR_INTERNAL);
2398 descendants[0] = mid;
2403 if (!strcmp(mtype, "LIST")) {
2404 EXEC SQL DECLARE csr104 CURSOR FOR
2405 SELECT member_id, member_type, ref_count
2407 WHERE list_id = :mid;
2408 EXEC SQL OPEN csr104;
2410 EXEC SQL FETCH csr104 INTO :id, :dtype, :ref;
2411 if(sqlca.sqlcode != 0) break;
2414 dtypes[dcount] = "LIST";
2417 dtypes[dcount] = "USER";
2420 dtypes[dcount] = "STRING";
2423 dtypes[dcount] = "KERBEROS";
2430 descendants[dcount++] = id;
2431 if (dcount >= MAXLISTDEPTH) {
2436 EXEC SQL CLOSE csr104;
2437 if (ingres_errno) return(mr_errcode);
2439 return(MR_INTERNAL);
2441 for (a = 0; a < acount; a++) {
2443 for (d = 0; d < dcount; d++) {
2444 mid = descendants[d];
2446 if (mid == lid && !strcmp(mtype, "LIST")) {
2447 return(MR_LISTLOOP);
2449 EXEC SQL REPEATED SELECT ref_count INTO :idummy FROM imembers
2450 WHERE list_id = :lid AND member_id = :mid
2451 AND member_type = :mtype;
2452 ref = aref[a] * dref[d];
2453 if (sqlca.sqlerrd[2] > 0) {
2454 if (a == 0 && d == 0) {
2455 EXEC SQL UPDATE imembers
2456 SET ref_count = ref_count+:ref, direct=1
2457 WHERE list_id = :lid AND member_id = :mid
2458 AND member_type = :mtype;
2460 EXEC SQL UPDATE imembers
2461 SET ref_count = ref_count+:ref
2462 WHERE list_id = :lid AND member_id = :mid
2463 AND member_type = :mtype;
2466 incremental_clear_before();
2467 if (a == 0 && d == 0) {
2468 EXEC SQL INSERT INTO imembers
2469 (list_id, member_id, direct, member_type, ref_count)
2470 VALUES (:lid, :mid, 1, :mtype, 1);
2472 EXEC SQL INSERT INTO imembers
2473 (list_id, member_id, member_type, ref_count)
2474 VALUES (:lid, :mid, :mtype, 1);
2476 iargv[0] = (char *)lid;
2478 iargv[2] = (char *)mid;
2479 incremental_after("members", 0, iargv);
2483 lid = *(int *)argv[0];
2484 entity = cl->entity;
2485 who = cl->client_id;
2486 EXEC SQL REPEATED UPDATE list
2487 SET modtime='now', modby = :who, modwith = :entity
2488 WHERE list_id = :lid;
2489 if (ingres_errno) return(mr_errcode);
2494 /* Delete_member_from_list: do list flattening as we go!
2497 int delete_member_from_list(q, argv, cl)
2502 EXEC SQL BEGIN DECLARE SECTION;
2503 int id, lid, mid, cnt, error, who, ref;
2504 char *mtype, dtype[9], *entity;
2505 EXEC SQL END DECLARE SECTION;
2506 int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a;
2507 int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d;
2508 char *dtypes[MAXLISTDEPTH];
2511 lid = *(int *)argv[0];
2513 mid = *(int *)argv[2];
2514 /* if the member is not a direct member of the list, punt */
2515 EXEC SQL REPEATED SELECT list_id INTO :idummy FROM imembers
2516 WHERE list_id = :lid AND member_id = :mid
2517 AND member_type = :mtype AND direct = 1;
2518 if (ingres_errno) return(mr_errcode);
2519 if (sqlca.sqlcode == 100)
2520 return(MR_NO_MATCH);
2524 EXEC SQL DECLARE csr105 CURSOR FOR
2525 SELECT list_id, ref_count FROM imembers
2526 WHERE member_id = :lid AND member_type = 'LIST';
2527 EXEC SQL OPEN csr105;
2529 EXEC SQL FETCH csr105 INTO :id, :ref;
2530 if(sqlca.sqlcode!=0) break;
2532 ancestors[acount++] = id;
2533 if (acount >= MAXLISTDEPTH) break;
2535 EXEC SQL CLOSE csr105;
2538 if (acount >= MAXLISTDEPTH)
2539 return(MR_INTERNAL);
2540 descendants[0] = mid;
2545 if (!strcmp(mtype, "LIST")) {
2546 EXEC SQL DECLARE csr106 CURSOR FOR
2547 SELECT member_id, member_type, ref_count FROM imembers
2548 WHERE list_id = :mid;
2549 EXEC SQL OPEN csr106;
2551 EXEC SQL FETCH csr106 INTO :id, :dtype, :ref;
2552 if(sqlca.sqlcode!=0) break;
2555 dtypes[dcount] = "LIST";
2558 dtypes[dcount] = "USER";
2561 dtypes[dcount] = "STRING";
2564 dtypes[dcount] = "KERBEROS";
2571 descendants[dcount++] = id;
2572 if (dcount >= MAXLISTDEPTH) break;
2574 EXEC SQL CLOSE csr106;
2578 return(MR_INTERNAL);
2580 for (a = 0; a < acount; a++) {
2582 for (d = 0; d < dcount; d++) {
2583 mid = descendants[d];
2585 if (mid == lid && !strcmp(mtype, "LIST")) {
2586 return(MR_LISTLOOP);
2588 EXEC SQL REPEATED SELECT ref_count INTO :cnt FROM imembers
2589 WHERE list_id = :lid AND member_id = :mid AND member_type = :mtype;
2590 ref = aref[a] * dref[d];
2592 iargv[0] = (char *)lid;
2594 iargv[2] = (char *)mid;
2595 incremental_before("members", 0, iargv);
2596 EXEC SQL DELETE FROM imembers
2597 WHERE list_id = :lid AND member_id = :mid
2598 AND member_type= :mtype;
2599 incremental_clear_after();
2600 } else if (a == 0 && d == 0) {
2601 EXEC SQL UPDATE imembers
2602 SET ref_count = ref_count - :ref, direct = 0
2603 WHERE list_id = :lid AND member_id = :mid
2604 AND member_type = :mtype;
2606 EXEC SQL UPDATE imembers
2607 SET ref_count = ref_count - :ref
2608 WHERE list_id = :lid AND member_id = :mid
2609 AND member_type = :mtype;
2613 lid = *(int *)argv[0];
2614 entity = cl->entity;
2615 who = cl->client_id;
2616 EXEC SQL UPDATE list SET modtime = 'now', modby = :who, modwith = :entity
2617 WHERE list_id = :lid;
2618 if (ingres_errno) return(mr_errcode);
2623 /* get_ace_use - given a type and a name, return a type and a name.
2624 * The ace_type is one of "LIST", "USER", "RLIST", or "RUSER" in argv[0],
2625 * and argv[1] will contain the ID of the entity in question. The R*
2626 * types mean to recursively look at every containing list, not just
2627 * when the object in question is a direct member. On return, the
2628 * usage type will be one of LIST, SERVICE, FILESYS, QUOTA, QUERY, or ZEPHYR.
2631 int get_ace_use(q, argv, cl, action, actarg)
2639 EXEC SQL BEGIN DECLARE SECTION;
2641 int aid, listid, id;
2642 EXEC SQL END DECLARE SECTION;
2643 struct save_queue *sq, *sq_create();
2646 aid = *(int *)argv[1];
2647 if (!strcmp(atype, "LIST") || !strcmp(atype, "USER") ||
2648 !strcmp(atype, "KERBEROS")) {
2649 return(get_ace_internal(atype, aid, action, actarg));
2653 if (!strcmp(atype, "RLIST")) {
2654 sq_save_data(sq, aid);
2655 /* get all the list_id's of containing lists */
2656 EXEC SQL DECLARE csr107 CURSOR FOR
2657 SELECT list_id FROM imembers
2658 WHERE member_type='LIST' AND member_id = :aid;
2659 EXEC SQL OPEN csr107;
2661 EXEC SQL FETCH csr107 INTO :listid;
2662 if(sqlca.sqlcode != 0) break;
2663 sq_save_unique_data(sq, listid);
2665 EXEC SQL CLOSE csr107;
2666 /* now process each one */
2667 while (sq_get_data(sq, &id)) {
2668 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2673 if (!strcmp(atype, "RUSER")) {
2674 EXEC SQL DECLARE csr108 CURSOR FOR
2675 SELECT list_id FROM imembers
2676 WHERE member_type='USER' AND member_id = :aid;
2677 EXEC SQL OPEN csr108;
2679 EXEC SQL FETCH csr108 INTO :listid;
2680 if(sqlca.sqlcode != 0) break;
2681 sq_save_data(sq, listid);
2683 EXEC SQL CLOSE csr108;
2684 /* now process each one */
2685 while (sq_get_data(sq, &id)) {
2686 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2689 if (get_ace_internal("USER", aid, action, actarg) == MR_SUCCESS)
2693 if (!strcmp(atype, "RKERBERO")) {
2694 EXEC SQL DECLARE csr109 CURSOR FOR
2695 SELECT list_id FROM imembers
2696 WHERE member_type='KERBEROS' AND member_id = :aid;
2697 EXEC SQL OPEN csr109;
2699 EXEC SQL FETCH csr109 INTO :listid;
2700 if(sqlca.sqlcode != 0) break;
2701 sq_save_data(sq, listid);
2703 EXEC SQL CLOSE csr109;
2704 /* now process each one */
2705 while (sq_get_data(sq, &id)) {
2706 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2709 if (get_ace_internal("KERBEROS", aid, action, actarg) == MR_SUCCESS)
2714 if (ingres_errno) return(mr_errcode);
2715 if (!found) return(MR_NO_MATCH);
2720 /* This looks up a single list or user for ace use. atype must be "USER"
2721 * or "LIST", and aid is the ID of the corresponding object. This is used
2722 * by get_ace_use above.
2725 get_ace_internal(atype, aid, action, actarg)
2726 EXEC SQL BEGIN DECLARE SECTION;
2729 EXEC SQL END DECLARE SECTION;
2735 EXEC SQL BEGIN DECLARE SECTION;
2737 EXEC SQL END DECLARE SECTION;
2740 if (!strcmp(atype, "LIST")) {
2741 rargv[0] = "FILESYS";
2742 EXEC SQL DECLARE csr110 CURSOR FOR
2743 SELECT label FROM filesys
2744 WHERE owners = :aid;
2745 EXEC SQL OPEN csr110;
2747 EXEC SQL FETCH csr110 INTO :name;
2748 if(sqlca.sqlcode != 0) break;
2749 (*action)(2, rargv, actarg);
2752 EXEC SQL CLOSE csr110;
2755 EXEC SQL DECLARE csr111 CURSOR FOR
2756 SELECT capability FROM capacls
2757 WHERE list_id = :aid ;
2758 EXEC SQL OPEN csr111;
2760 EXEC SQL FETCH csr111 INTO :name ;
2761 if(sqlca.sqlcode != 0) break;
2762 (*action)(2, rargv, actarg);
2765 EXEC SQL CLOSE csr111;
2766 } else if (!strcmp(atype, "USER")) {
2767 rargv[0] = "FILESYS";
2768 EXEC SQL DECLARE csr112 CURSOR FOR
2769 SELECT label FROM filesys
2771 EXEC SQL OPEN csr112;
2773 EXEC SQL FETCH csr112 INTO :name ;
2774 if(sqlca.sqlcode != 0) break;
2775 (*action)(2, rargv, actarg);
2778 EXEC SQL CLOSE csr112;
2782 EXEC SQL DECLARE csr113 CURSOR FOR
2783 SELECT name FROM list
2784 WHERE acl_type = :atype AND acl_id = :aid;
2785 EXEC SQL OPEN csr113;
2787 EXEC SQL FETCH csr113 INTO :name;
2788 if(sqlca.sqlcode != 0) break;
2789 (*action)(2, rargv, actarg);
2792 EXEC SQL CLOSE csr113;
2794 rargv[0] = "SERVICE";
2795 EXEC SQL DECLARE csr114 CURSOR FOR
2796 SELECT name FROM servers
2797 WHERE acl_type = :atype AND acl_id = :aid;
2798 EXEC SQL OPEN csr114;
2800 EXEC SQL FETCH csr114 INTO :name;
2801 if(sqlca.sqlcode != 0) break;
2802 (*action)(2, rargv, actarg);
2805 EXEC SQL CLOSE csr114;
2807 rargv[0] = "HOSTACCESS";
2808 EXEC SQL DECLARE csr115 CURSOR FOR
2809 SELECT name FROM machine m, hostaccess ha
2810 WHERE m.mach_id = ha.mach_id AND ha.acl_type = :atype
2811 AND ha.acl_id = :aid;
2812 EXEC SQL OPEN csr115;
2814 EXEC SQL FETCH csr115 INTO :name;
2815 if(sqlca.sqlcode != 0) break;
2816 (*action)(2, rargv, actarg);
2819 EXEC SQL CLOSE csr115;
2821 rargv[0] = "ZEPHYR";
2822 EXEC SQL DECLARE csr116 CURSOR FOR
2823 SELECT class FROM zephyr z
2824 WHERE z.xmt_type = :atype AND z.xmt_id = :aid
2825 OR z.sub_type = :atype AND z.sub_id = :aid
2826 OR z.iws_type = :atype AND z.iws_id = :aid
2827 OR z.iui_type = :atype AND z.iui_id = :aid;
2828 EXEC SQL OPEN csr116;
2830 EXEC SQL FETCH csr116 INTO :name;
2831 if(sqlca.sqlcode != 0) break;
2832 (*action)(2, rargv, actarg);
2835 EXEC SQL CLOSE csr116;
2837 if (!found) return(MR_NO_MATCH);
2842 /* get_lists_of_member - given a type and a name, return the name and flags
2843 * of all of the lists of the given member. The member_type is one of
2844 * "LIST", "USER", "STRING", "RLIST", "RUSER", or "RSTRING" in argv[0],
2845 * and argv[1] will contain the ID of the entity in question. The R*
2846 * types mean to recursively look at every containing list, not just
2847 * when the object in question is a direct member.
2850 int get_lists_of_member(q, argv, cl, action, actarg)
2857 int found = 0, direct = 1;
2859 EXEC SQL BEGIN DECLARE SECTION;
2861 int aid, listid, id;
2862 char name[33], active[5], public[5], hidden[5], maillist[5], grouplist[5];
2863 EXEC SQL END DECLARE SECTION;
2866 aid = *(int *)argv[1];
2867 if (!strcmp(atype, "RLIST")) {
2871 if (!strcmp(atype, "RUSER")) {
2875 if (!strcmp(atype, "RSTRING")) {
2879 if (!strcmp(atype, "RKERBEROS")) {
2888 rargv[4] = maillist;
2889 rargv[5] = grouplist;
2891 EXEC SQL DECLARE csr117a CURSOR FOR
2892 SELECT l.name, CHAR(l.active), CHAR(l.publicflg), CHAR(l.hidden),
2893 CHAR(l.maillist), CHAR(l.grouplist)
2894 FROM list l, imembers im
2895 WHERE l.list_id = im.list_id AND im.direct = 1
2896 AND im.member_type = :atype AND im.member_id = :aid;
2897 EXEC SQL OPEN csr117a;
2899 EXEC SQL FETCH csr117a
2900 INTO :name, :active, :public, :hidden, :maillist, :grouplist;
2901 if(sqlca.sqlcode != 0) break;
2902 (*action)(6, rargv, actarg);
2905 EXEC SQL CLOSE csr117a;
2907 EXEC SQL DECLARE csr117b CURSOR FOR
2908 SELECT l.name, CHAR(l.active), CHAR(l.publicflg), CHAR(l.hidden),
2909 CHAR(l.maillist), CHAR(l.grouplist)
2910 FROM list l, imembers im
2911 WHERE l.list_id = im.list_id
2912 AND im.member_type = :atype AND im.member_id = :aid;
2913 EXEC SQL OPEN csr117b;
2915 EXEC SQL FETCH csr117b
2916 INTO :name, :active, :public, :hidden, :maillist, :grouplist;
2917 if(sqlca.sqlcode != 0) break;
2918 (*action)(6, rargv, actarg);
2921 EXEC SQL CLOSE csr117b;
2924 if (ingres_errno) return(mr_errcode);
2925 if (!found) return(MR_NO_MATCH);
2930 /* qualified_get_lists: passed "TRUE", "FALSE", or "DONTCARE" for each of
2931 * the five flags associated with each list. It will return the name of
2932 * each list that meets the quailifications. It does this by building a
2933 * where clause based on the arguments, then doing a retrieve.
2936 static char *lflags[5] = { "active", "publicflg", "hidden", "maillist", "grouplist" };
2938 int qualified_get_lists(q, argv, cl, action, actarg)
2945 return(qualified_get(q, argv, action, actarg, "l.list_id != 0",
2946 "l", "name", lflags));
2950 /* get_members_of_list - this gets only direct members */
2952 get_members_of_list(q, argv, cl, action, actarg)
2959 return(gmol_internal(q, argv, cl, action, actarg, 1));
2962 /* get_end_members_of_list - this gets direct or indirect members */
2964 get_end_members_of_list(q, argv, cl, action, actarg)
2971 return(gmol_internal(q, argv, cl, action, actarg, 0));
2974 /** gmol_internal - optimized query for retrieval of list members
2975 ** used by both get_members_of_list and get_end_members_of_list
2978 ** argv[0] - list_id
2981 ** - retrieve USER members, then LIST members, then STRING members
2984 gmol_internal(q, argv, cl, action, actarg, flag)
2992 EXEC SQL BEGIN DECLARE SECTION;
2993 int list_id, member_id, direct;
2994 char member_name[129], member_type[9];
2995 EXEC SQL END DECLARE SECTION;
2998 struct save_queue *sq;
3000 /* true/false flag indicates whether to display only direct members. */
3006 list_id = *(int *)argv[0];
3010 EXEC SQL DECLARE csr118 CURSOR FOR
3011 SELECT member_type, member_id FROM imembers
3012 WHERE list_id = :list_id AND direct > :direct;
3013 EXEC SQL OPEN csr118;
3015 EXEC SQL FETCH csr118 INTO :member_type, :member_id;
3016 if (sqlca.sqlcode != 0) break;
3019 sq_save_data(sq, ((int)member_type[0] << 24) | (member_id & 0xffffff));
3021 EXEC SQL CLOSE csr118;
3023 if (members <= 49) {
3024 targv[1] = malloc(0);
3025 while (sq_remove_data(sq, &member_id)) {
3026 switch (member_id >> 24) {
3029 id_to_name(member_id & 0xffffff, "USER", &targv[1]);
3030 (*action)(2, targv, actarg);
3034 id_to_name(member_id & 0xffffff, "LIST", &targv[1]);
3035 (*action)(2, targv, actarg);
3038 targv[0] = "STRING";
3039 id_to_name(member_id & 0xffffff, "STRING", &targv[1]);
3040 (*action)(2, targv, actarg);
3043 targv[0] = "KERBEROS";
3044 id_to_name(member_id & 0xffffff, "STRING", &targv[1]);
3045 (*action)(2, targv, actarg);
3049 return(MR_INTERNAL);
3058 targv[1] = member_name;
3060 EXEC SQL DECLARE csr119 CURSOR FOR
3061 SELECT u.login FROM users u, imembers im
3062 WHERE im.list_id = :list_id AND im.member_type = 'USER'
3063 AND im.member_id = u.users_id AND im.direct > :direct
3065 EXEC SQL OPEN csr119;
3067 EXEC SQL FETCH csr119 INTO :member_name;
3068 if(sqlca.sqlcode != 0) break;
3069 (*action)(2, targv, actarg);
3071 EXEC SQL CLOSE csr119;
3072 if (ingres_errno) return(mr_errcode);
3075 EXEC SQL DECLARE csr120 CURSOR FOR
3076 SELECT l.name FROM list l, imembers im
3077 WHERE im.list_id = :list_id AND im.member_type='LIST'
3078 AND im.member_id = l.list_id AND im.direct > :direct
3080 EXEC SQL OPEN csr120;
3082 EXEC SQL FETCH csr120 INTO :member_name;
3083 if(sqlca.sqlcode != 0) break;
3084 (*action)(2, targv, actarg);
3086 EXEC SQL CLOSE csr120;
3087 if (ingres_errno) return(mr_errcode);
3089 targv[0] = "STRING";
3090 EXEC SQL DECLARE csr121 CURSOR FOR
3091 SELECT CHAR(str.string) FROM strings str, imembers im
3092 WHERE im.list_id = :list_id AND im.member_type='STRING'
3093 AND im.member_id = str.string_id AND im.direct > :direct
3095 EXEC SQL OPEN csr121;
3097 EXEC SQL FETCH csr121 INTO :member_name;
3098 if(sqlca.sqlcode != 0) break;
3099 (*action)(2, targv, actarg);
3101 EXEC SQL CLOSE csr121;
3102 if (ingres_errno) return(mr_errcode);
3104 targv[0] = "KERBEROS";
3105 EXEC SQL DECLARE csr122 CURSOR FOR
3106 SELECT CHAR(str.string) FROM strings str, imembers im
3107 WHERE im.list_id = :list_id AND im.member_type='KERBEROS'
3108 AND im.member_id = str.string_id
3109 AND im.direct > :direct
3111 EXEC SQL OPEN csr122;
3113 EXEC SQL FETCH csr122 INTO :member_name;
3114 if(sqlca.sqlcode != 0) break;
3115 (*action)(2, targv, actarg);
3117 EXEC SQL CLOSE csr122;
3118 if (ingres_errno) return(mr_errcode);
3124 /* count_members_of_list: this is a simple query, but it cannot be done
3125 * through the dispatch table.
3128 int count_members_of_list(q, argv, cl, action, actarg)
3135 EXEC SQL BEGIN DECLARE SECTION;
3137 EXEC SQL END DECLARE SECTION;
3138 char *rargv[1], countbuf[5];
3140 list = *(int *)argv[0];
3141 rargv[0] = countbuf;
3142 EXEC SQL REPEATED SELECT count (*) INTO :ct FROM imembers
3143 WHERE list_id = :list AND direct=1;
3144 if (ingres_errno) return(mr_errcode);
3145 sprintf(countbuf, "%d", ct);
3146 (*action)(1, rargv, actarg);
3151 /* qualified_get_server: passed "TRUE", "FALSE", or "DONTCARE" for each of
3152 * the three flags associated with each service. It will return the name of
3153 * each service that meets the quailifications. It does this by building a
3154 * where clause based on the arguments, then doing a retrieve.
3157 static char *sflags[3] = { "enable", "inprogress", "harderror" };
3159 int qualified_get_server(q, argv, cl, action, actarg)
3166 return(qualified_get(q, argv, action, actarg, "s.name != ''",
3167 "s", "name", sflags));
3171 /* generic qualified get routine, used by qualified_get_lists,
3172 * qualified_get_server, and qualified_get_serverhost.
3174 * start - a simple where clause, must not be empty
3175 * range - the name of the range variable
3176 * field - the field to return
3177 * flags - an array of strings, names of the flag variables
3180 int qualified_get(q, argv, action, actarg, start, range, field, flags)
3190 char name[33], qual[256];
3192 char *rargv[1], buf[32];
3194 strcpy(qual, start);
3195 for (i = 0; i < q->argc; i++) {
3196 if (!strcmp(argv[i], "TRUE")) {
3197 sprintf(buf, " AND %s.%s != 0", range, flags[i]);
3198 (void) strcat(qual, buf);
3199 } else if (!strcmp(argv[i], "FALSE")) {
3200 sprintf(buf, " AND %s.%s = 0", range, flags[i]);
3201 (void) strcat(qual, buf);
3205 rargv[0] = SQLDA->sqlvar[0].sqldata;
3206 sprintf(stmt_buf,"SELECT CHAR(%s.%s) FROM %s %s WHERE %s",range,field,q->rtable,range,qual);
3207 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3209 return(MR_INTERNAL);
3210 EXEC SQL DECLARE csr123 CURSOR FOR stmt;
3211 EXEC SQL OPEN csr123;
3213 EXEC SQL FETCH csr123 USING DESCRIPTOR :SQLDA;
3214 if(sqlca.sqlcode != 0) break;
3216 (*action)(1, rargv, actarg);
3218 EXEC SQL CLOSE csr123;
3219 if (ingres_errno) return(mr_errcode);
3221 return(MR_NO_MATCH);
3226 /* qualified_get_serverhost: passed "TRUE", "FALSE", or "DONTCARE" for each of
3227 * the five flags associated with each serverhost. It will return the name of
3228 * each service and host that meets the quailifications. It does this by
3229 * building a where clause based on the arguments, then doing a retrieve.
3232 static char *shflags[6] = { "service", "enable", "override", "success",
3233 "inprogress", "hosterror" };
3235 int qualified_get_serverhost(q, argv, cl, action, actarg)
3242 EXEC SQL BEGIN DECLARE SECTION;
3243 char sname[33], mname[33], qual[256];
3244 EXEC SQL END DECLARE SECTION;
3245 char *rargv[2], buf[32];
3248 sprintf(qual, "m.mach_id = sh.mach_id AND sh.service = uppercase('%s')",
3250 for (i = 1; i < q->argc; i++) {
3251 if (!strcmp(argv[i], "TRUE")) {
3252 sprintf(buf, " AND sh.%s != 0", shflags[i]);
3254 } else if (!strcmp(argv[i], "FALSE")) {
3255 sprintf(buf, " AND sh.%s = 0", shflags[i]);
3262 EXEC SQL DECLARE csr124 CURSOR FOR
3263 SELECT sh.service, m.name FROM serverhosts sh, machine m
3265 EXEC SQL OPEN csr124;
3267 EXEC SQL FETCH csr124 INTO :sname, :mname;
3268 if(sqlca.sqlcode != 0) break;
3270 (*action)(2, rargv, actarg);
3272 EXEC SQL CLOSE csr124;
3274 if (ingres_errno) return(mr_errcode);
3276 return(MR_NO_MATCH);
3281 /* register_user - change user's login name and allocate a pobox, group,
3282 * filesystem, and quota for them. The user's status must start out as 0,
3283 * and is left as 2. Arguments are: user's UID, new login name, and user's
3284 * type for filesystem allocation (MR_FS_STUDENT, MR_FS_FACULTY,
3285 * MR_FS_STAFF, MR_FS_MISC).
3288 register_user(q, argv, cl)
3293 EXEC SQL BEGIN DECLARE SECTION;
3294 char *login, dir[65], *entity, directory[129], machname[33];
3295 int who, rowcount, mid, uid, users_id, flag, utype, nid, list_id, quota;
3296 int size, alloc, pid, ostatus, nstatus, gidval, fsidval, npidval;
3297 static int m_id = 0, def_quota = 0;
3298 EXEC SQL END DECLARE SECTION;
3299 char buffer[256], *aargv[3];
3301 entity = cl->entity;
3302 who = cl->client_id;
3304 uid = atoi(argv[0]);
3306 utype = atoi(argv[2]);
3309 EXEC SQL REPEATED SELECT users_id, status INTO :users_id, :ostatus
3311 WHERE uid = :uid AND (status=0 OR status=5 OR status=6);
3313 if (sqlca.sqlerrd[2] == 0)
3314 return(MR_NO_MATCH);
3315 if (sqlca.sqlerrd[2] > 1)
3316 return(MR_NOT_UNIQUE);
3318 /* check new login name */
3319 EXEC SQL REPEATED SELECT login INTO :cdummy FROM users
3320 WHERE login = LEFT(:login,SIZE(login)) AND users_id != :users_id;
3321 if (ingres_errno) return(mr_errcode);
3322 if (sqlca.sqlerrd[2] > 0) return(MR_IN_USE);
3323 EXEC SQL REPEATED SELECT name INTO :cdummy FROM list
3324 WHERE name = LEFT(:login,SIZE(name));
3325 if (ingres_errno) return(mr_errcode);
3326 if (sqlca.sqlerrd[2] > 0) return(MR_IN_USE);
3327 EXEC SQL REPEATED SELECT label INTO :cdummy FROM filesys
3328 WHERE label = LEFT(:login,SIZE(label));
3329 if (ingres_errno) return(mr_errcode);
3330 if (sqlca.sqlerrd[2] > 0) return(MR_IN_USE);
3331 com_err(whoami, 0, "login name OK");
3333 /* choose place for pobox, put in mid */
3334 EXEC SQL DECLARE csr130 CURSOR FOR
3335 SELECT sh.mach_id, m.name FROM serverhosts sh, machine m
3336 WHERE sh.service='POP' AND sh.mach_id=m.mach_id
3337 AND sh.value2 - sh.value1 =
3338 (SELECT MAX(value2 - value1) FROM serverhosts
3339 WHERE service = 'POP');
3340 EXEC SQL OPEN csr130;
3341 EXEC SQL FETCH csr130 INTO :mid, :machname;
3342 if (sqlca.sqlerrd[2] == 0) {
3343 EXEC SQL CLOSE csr130;
3344 if (ingres_errno) return(mr_errcode);
3345 return(MR_NO_POBOX);
3347 EXEC SQL CLOSE csr130;
3348 if (ingres_errno) return(mr_errcode);
3351 /* change login name, set pobox */
3352 sprintf(buffer, "u.users_id = %d", users_id);
3353 incremental_before("users", buffer, 0);
3355 if (ostatus == 5 || ostatus == 6)
3357 EXEC SQL REPEATED UPDATE users SET login = :login, status = :nstatus,
3358 modtime='now', modby = :who, modwith = :entity, potype='POP',
3359 pop_id = :mid, pmodtime='now', pmodby = :who, pmodwith = :entity
3360 WHERE users_id = :users_id;
3362 if (ingres_errno) return(mr_errcode);
3363 if (sqlca.sqlerrd[2] != 1)
3364 return(MR_INTERNAL);
3365 set_pop_usage(mid, 1);
3366 com_err(whoami, 0, "set login name to %s and pobox to %s", login,
3368 incremental_after("users", buffer, 0);
3370 /* create group list */
3371 if (set_next_object_id("gid", "list", 1))
3373 if (set_next_object_id("list_id", "list", 0))
3375 EXEC SQL REPEATED SELECT value INTO :list_id FROM numvalues
3376 WHERE name='list_id';
3377 if (ingres_errno) return(mr_errcode);
3378 if (sqlca.sqlerrd[2] != 1)
3379 return(MR_INTERNAL);
3380 incremental_clear_before();
3381 EXEC SQL SELECT value INTO :gidval FROM numvalues WHERE name = 'gid';
3382 EXEC SQL REPEATED INSERT INTO list
3383 (name, list_id, active, publicflg, hidden, maillist, grouplist,
3384 gid, description, acl_type, acl_id,
3385 modtime, modby, modwith)
3386 VALUES (:login, :list_id, 1, 0, 0, 0, 1,
3387 :gidval, 'User Group', 'USER', :users_id,
3388 'now', :who, :entity);
3389 if (ingres_errno) return(mr_errcode);
3390 if (sqlca.sqlerrd[2] != 1)
3391 return(MR_INTERNAL);
3392 sprintf(buffer, "l.list_id = %d", list_id);
3393 incremental_after("list", buffer, 0);
3394 aargv[0] = (char *) list_id;
3396 aargv[2] = (char *) users_id;
3397 incremental_clear_before();
3398 EXEC SQL REPEATED INSERT INTO imembers
3399 (list_id, member_type, member_id, ref_count, direct)
3400 VALUES (:list_id, 'USER', :users_id, 1, 1);
3401 if (ingres_errno) return(mr_errcode);
3402 if (sqlca.sqlerrd[2] != 1)
3403 return(MR_INTERNAL);
3404 incremental_after("members", 0, aargv);
3407 /* Cell Name (I know, it shouldn't be hard coded...) */
3408 strcpy(machname, "ATHENA.MIT.EDU");
3409 EXEC SQL SELECT mach_id INTO :m_id FROM machine
3410 WHERE name = :machname;
3413 /* create filesystem */
3414 if (set_next_object_id("filsys_id", "filesys", 0))
3416 incremental_clear_before();
3417 if (islower(login[0]) && islower(login[1])) {
3418 sprintf(directory, "/afs/athena.mit.edu/user/%c/%c/%s",
3419 login[0], login[1], login);
3421 sprintf(directory, "/afs/athena.mit.edu/user/other/%s", login);
3424 EXEC SQL SELECT value INTO :fsidval FROM numvalues
3425 WHERE numvalues.name='filsys_id';
3426 EXEC SQL REPEATED INSERT INTO filesys
3427 (filsys_id, phys_id, label, type, mach_id, name,
3428 mount, access, comments, owner, owners, createflg,
3429 lockertype, modtime, modby, modwith)
3431 (:fsidval, 0, :login, 'AFS', :m_id, :directory,
3432 '/mit/'+:login, 'w', 'User Locker', :users_id, :list_id, 1,
3433 'HOMEDIR', 'now', :who, :entity);
3435 if (ingres_errno) return(mr_errcode);
3436 if (sqlca.sqlerrd[2] != 1)
3437 return(MR_INTERNAL);
3438 sprintf(buffer,"fs.filsys_id = %d",fsidval);
3439 incremental_after("filesys", buffer, 0);
3442 if (def_quota == 0) {
3443 EXEC SQL REPEATED SELECT value INTO :def_quota FROM numvalues
3444 WHERE name='def_quota';
3445 if (ingres_errno) return(mr_errcode);
3446 if (sqlca.sqlerrd[2] != 1)
3447 return(MR_NO_QUOTA);
3450 incremental_clear_before();
3451 EXEC SQL REPEATED INSERT INTO quota
3452 (entity_id, filsys_id, type, quota, phys_id, modtime, modby, modwith)
3454 (0, :fsidval, 'ANY', :def_quota, 0, 'now', :who, :entity);
3455 if (ingres_errno) return(mr_errcode);
3456 if (sqlca.sqlerrd[2] != 1)
3457 return(MR_INTERNAL);
3461 sprintf(buffer, "q.entity_id = 0 and q.filsys_id = %d and q.type = 'ANY'", fsidval);
3462 incremental_after("quota", buffer, aargv);
3463 com_err(whoami, 0, "quota of %d assigned", def_quota);
3464 if (ingres_errno) return(mr_errcode);
3466 cache_entry(login, "USER", users_id);
3468 EXEC SQL REPEATED UPDATE tblstats SET updates=updates+1, modtime='now'
3469 WHERE table_name='users';
3470 EXEC SQL REPEATED UPDATE tblstats SET appends=appends+1, modtime='now'
3471 WHERE table_name='list' OR table_name='filesys' OR table_name='quota';
3472 if (ingres_errno) return(mr_errcode);
3478 /** set_pop_usage - incr/decr usage count for pop server in serverhosts talbe
3482 ** delta (will be +/- 1)
3485 ** - incr/decr value field in serverhosts table for pop/mach_id
3489 static int set_pop_usage(id, cnt)
3490 EXEC SQL BEGIN DECLARE SECTION;
3493 EXEC SQL END DECLARE SECTION;
3495 EXEC SQL REPEATED UPDATE serverhosts SET value1 = value1 + :cnt
3496 WHERE serverhosts.service = 'POP' AND serverhosts.mach_id = :id;
3498 if (ingres_errno) return(mr_errcode);
3504 /* Validation Routines */
3506 validate_row(q, argv, v)
3507 register struct query *q;
3509 register struct validate *v;
3511 EXEC SQL BEGIN DECLARE SECTION;
3515 EXEC SQL END DECLARE SECTION;
3517 /* build where clause */
3518 build_qual(v->qual, v->argc, argv, qual);
3520 if (log_flags & LOG_VALID)
3521 /* tell the logfile what we're doing */
3522 com_err(whoami, 0, "validating row: %s", qual);
3524 /* look for the record */
3525 sprintf(stmt_buf,"SELECT COUNT (*) FROM %s WHERE %s",q->rtable,qual);
3526 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3528 return(MR_INTERNAL);
3529 EXEC SQL DECLARE csr126 CURSOR FOR stmt;
3530 EXEC SQL OPEN csr126;
3531 EXEC SQL FETCH csr126 USING DESCRIPTOR :SQLDA;
3532 EXEC SQL CLOSE csr126;
3533 rowcount = *(int *)SQLDA->sqlvar[0].sqldata;
3535 if (ingres_errno) return(mr_errcode);
3536 if (rowcount == 0) return(MR_NO_MATCH);
3537 if (rowcount > 1) return(MR_NOT_UNIQUE);
3541 validate_fields(q, argv, vo, n)
3543 register char *argv[];
3544 register struct valobj *vo;
3547 register int status;
3552 if (log_flags & LOG_VALID)
3553 com_err(whoami, 0, "validating %s in %s: %s",
3554 vo->namefield, vo->table, argv[vo->index]);
3555 status = validate_name(argv, vo);
3559 if (log_flags & LOG_VALID)
3560 com_err(whoami, 0, "validating %s in %s: %s",
3561 vo->idfield, vo->table, argv[vo->index]);
3562 status = validate_id(q, argv, vo);
3566 if (log_flags & LOG_VALID)
3567 com_err(whoami, 0, "validating date: %s", argv[vo->index]);
3568 status = validate_date(argv, vo);
3572 if (log_flags & LOG_VALID)
3573 com_err(whoami, 0, "validating %s type: %s",
3574 vo->table, argv[vo->index]);
3575 status = validate_type(argv, vo);
3579 if (log_flags & LOG_VALID)
3580 com_err(whoami, 0, "validating typed data (%s): %s",
3581 argv[vo->index - 1], argv[vo->index]);
3582 status = validate_typedata(q, argv, vo);
3586 if (log_flags & LOG_VALID)
3587 com_err(whoami, 0, "validating rename %s in %s",
3588 argv[vo->index], vo->table);
3589 status = validate_rename(argv, vo);
3593 if (log_flags & LOG_VALID)
3594 com_err(whoami, 0, "validating chars: %s", argv[vo->index]);
3595 status = validate_chars(argv[vo->index]);
3603 status = lock_table(vo);
3607 status = convert_wildcards(argv[vo->index]);
3611 status = convert_wildcards_uppercase(argv[vo->index]);
3616 if (status != MR_EXISTS) return(status);
3620 if (ingres_errno) return(mr_errcode);
3625 /* validate_chars: verify that there are no illegal characters in
3626 * the string. Legal characters are printing chars other than
3627 * ", *, ?, \, [ and ].
3629 static int illegalchars[] = {
3630 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
3631 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
3632 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
3633 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
3634 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* : - O */
3635 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* P - _ */
3636 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
3637 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
3638 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3639 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3640 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3641 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3642 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3643 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3644 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3645 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3652 if (illegalchars[*s++])
3653 return(MR_BAD_CHAR);
3658 validate_id(q, argv, vo)
3661 register struct valobj *vo;
3663 EXEC SQL BEGIN DECLARE SECTION;
3664 char *name, *tbl, *namefield, *idfield;
3666 EXEC SQL END DECLARE SECTION;
3670 name = argv[vo->index];
3672 namefield = vo->namefield;
3673 idfield = vo->idfield;
3675 if ((!strcmp(tbl, "users") && !strcmp(namefield, "login")) ||
3676 !strcmp(tbl, "machine") ||
3677 !strcmp(tbl, "filesys") ||
3678 !strcmp(tbl, "list") ||
3679 !strcmp(tbl, "cluster") ||
3680 !strcmp(tbl, "strings")) {
3681 if (!strcmp(tbl, "machine"))
3682 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3683 status = name_to_id(name, tbl, &id);
3685 *(int *)argv[vo->index] = id;
3687 } else if (status == MR_NO_MATCH && !strcmp(tbl, "strings") &&
3688 (q->type == APPEND || q->type == UPDATE)) {
3689 EXEC SQL SELECT value INTO :id FROM numvalues
3690 WHERE name = 'strings_id';
3692 EXEC SQL UPDATE numvalues SET value = :id WHERE name = 'strings_id';
3693 EXEC SQL INSERT INTO strings (string_id, string) VALUES (:id, :name);
3694 cache_entry(name, "STRING", id);
3695 *(int *)argv[vo->index] = id;
3697 } else if (status == MR_NO_MATCH || status == MR_NOT_UNIQUE)
3703 if (!strcmp(namefield, "uid")) {
3704 sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s = %s",idfield,tbl,namefield,name);
3706 sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s = '%s'",idfield,tbl,namefield,name);
3708 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3710 return(MR_INTERNAL);
3711 EXEC SQL DECLARE csr127 CURSOR FOR stmt;
3712 EXEC SQL OPEN csr127;
3714 EXEC SQL FETCH csr127 USING DESCRIPTOR :SQLDA;
3715 if(sqlca.sqlcode == 0) {
3717 EXEC SQL FETCH csr127 USING DESCRIPTOR :SQLDA;
3718 if(sqlca.sqlcode == 0) rowcount++;
3720 EXEC SQL CLOSE csr127;
3724 if (rowcount != 1) return(vo->error);
3725 bcopy(SQLDA->sqlvar[0].sqldata,argv[vo->index],sizeof(int));
3729 validate_name(argv, vo)
3731 register struct valobj *vo;
3733 EXEC SQL BEGIN DECLARE SECTION;
3734 char *name, *tbl, *namefield;
3736 EXEC SQL END DECLARE SECTION;
3739 name = argv[vo->index];
3741 namefield = vo->namefield;
3742 if (!strcmp(tbl, "servers") && !strcmp(namefield, "name")) {
3743 for (c = name; *c; c++)
3747 sprintf(stmt_buf,"SELECT DISTINCT COUNT(*) FROM %s WHERE %s.%s = '%s'",
3748 tbl,tbl,namefield,name);
3749 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3751 return(MR_INTERNAL);
3752 EXEC SQL DECLARE csr128 CURSOR FOR stmt;
3753 EXEC SQL OPEN csr128;
3754 EXEC SQL FETCH csr128 USING DESCRIPTOR :SQLDA;
3755 rowcount = *(int *)SQLDA->sqlvar[0].sqldata;
3756 EXEC SQL CLOSE csr128;
3758 if (ingres_errno) return(mr_errcode);
3759 return ((rowcount == 1) ? MR_EXISTS : vo->error);
3762 validate_date(argv, vo)
3766 EXEC SQL BEGIN DECLARE SECTION;
3770 EXEC SQL END DECLARE SECTION;
3772 idate = argv[vo->index];
3773 EXEC SQL SELECT interval('years',date(:idate)-date('today')) INTO :dd;
3775 if (sqlca.sqlcode != 0 || dd > 5.0) return(MR_DATE);
3780 validate_rename(argv, vo)
3784 EXEC SQL BEGIN DECLARE SECTION;
3785 char *name, *tbl, *namefield, *idfield;
3787 EXEC SQL END DECLARE SECTION;
3791 c = name = argv[vo->index];
3793 if (illegalchars[*c++])
3794 return(MR_BAD_CHAR);
3796 /* minor kludge to upcasify machine names */
3797 if (!strcmp(tbl, "machine"))
3798 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3799 namefield = vo->namefield;
3800 idfield = vo->idfield;
3803 if (!strcmp(argv[vo->index], argv[vo->index - 1]))
3805 sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s = LEFT('%s',SIZE(%s))",
3806 namefield,tbl,namefield,name,namefield);
3807 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3809 return(MR_INTERNAL);
3810 EXEC SQL DECLARE csr129 CURSOR FOR stmt;
3811 EXEC SQL OPEN csr129;
3812 EXEC SQL FETCH csr129 USING DESCRIPTOR :SQLDA;
3813 if(sqlca.sqlcode == 0) id=1; else id=0;
3814 EXEC SQL CLOSE csr129;
3816 if (ingres_errno) return(mr_errcode);
3822 status = name_to_id(name, tbl, &id);
3823 if (status == MR_NO_MATCH || id == *(int *)argv[vo->index - 1])
3830 validate_type(argv, vo)
3832 register struct valobj *vo;
3834 EXEC SQL BEGIN DECLARE SECTION;
3837 EXEC SQL END DECLARE SECTION;
3840 typename = vo->table;
3841 c = val = argv[vo->index];
3843 if (illegalchars[*c++])
3844 return(MR_BAD_CHAR);
3847 /* uppercase type fields */
3848 for (c = val; *c; c++) if (islower(*c)) *c = toupper(*c);
3850 EXEC SQL SELECT trans INTO :cdummy FROM alias
3851 WHERE name = :typename AND type='TYPE' AND trans = :val;
3852 if (ingres_errno) return(mr_errcode);
3853 return (sqlca.sqlerrd[2] ? MR_EXISTS : vo->error);
3856 /* validate member or type-specific data field */
3858 validate_typedata(q, argv, vo)
3859 register struct query *q;
3860 register char *argv[];
3861 register struct valobj *vo;
3863 EXEC SQL BEGIN DECLARE SECTION;
3866 char data_type[129];
3868 EXEC SQL END DECLARE SECTION;
3873 /* get named object */
3874 name = argv[vo->index];
3876 /* get field type string (known to be at index-1) */
3877 field_type = argv[vo->index-1];
3879 /* get corresponding data type associated with field type name */
3880 EXEC SQL SELECT trans INTO :data_type FROM alias
3881 WHERE name = :field_type AND type='TYPEDATA';
3882 if (ingres_errno) return(mr_errcode);
3883 if (sqlca.sqlerrd[2] != 1) return(MR_TYPE);
3885 /* now retrieve the record id corresponding to the named object */
3886 if (index(data_type, ' '))
3887 *index(data_type, ' ') = 0;
3888 if (!strcmp(data_type, "user")) {
3890 status = name_to_id(name, data_type, &id);
3891 if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
3893 if (status) return(status);
3894 } else if (!strcmp(data_type, "list")) {
3896 status = name_to_id(name, data_type, &id);
3897 if (status && status == MR_NOT_UNIQUE)
3899 if (status == MR_NO_MATCH) {
3900 /* if idfield is non-zero, then if argv[0] matches the string
3901 * that we're trying to resolve, we should get the value of
3902 * numvalues.[idfield] for the id.
3904 if (vo->idfield && !strcmp(argv[0], argv[vo->index])) {
3905 set_next_object_id(q->validate->object_id, q->rtable, 0);
3907 EXEC SQL REPEATED SELECT value INTO :id FROM numvalues
3909 if (sqlca.sqlerrd[2] != 1) return(MR_LIST);
3912 } else if (status) return(status);
3913 } else if (!strcmp(data_type, "machine")) {
3915 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3916 status = name_to_id(name, data_type, &id);
3917 if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
3919 if (status) return(status);
3920 } else if (!strcmp(data_type, "string")) {
3922 status = name_to_id(name, data_type, &id);
3923 if (status && status == MR_NOT_UNIQUE)
3925 if (status == MR_NO_MATCH) {
3926 if (q->type != APPEND && q->type != UPDATE) return(MR_STRING);
3927 EXEC SQL SELECT value INTO :id FROM numvalues WHERE name = 'strings_id';
3929 EXEC SQL UPDATE numvalues SET value = :id WHERE name = 'strings_id';
3930 EXEC SQL INSERT INTO strings (string_id, string) VALUES (:id, :name);
3931 cache_entry(name, "STRING", id);
3932 } else if (status) return(status);
3933 } else if (!strcmp(data_type, "none")) {
3939 /* now set value in argv */
3940 *(int *)argv[vo->index] = id;
3946 /* Lock the table named by the validation object */
3951 sprintf(stmt_buf,"UPDATE %s SET modtime='now' WHERE %s.%s = 0",
3952 vo->table,vo->table,vo->idfield);
3953 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
3954 if (ingres_errno) return(mr_errcode);
3955 if (sqlca.sqlerrd[2] != 1)
3962 /* Check the database at startup time. For now this just resets the
3963 * inprogress flags that the DCM uses.
3966 sanity_check_database()
3971 /* Dynamic SQL support routines */
3972 MR_SQLDA_T *mr_alloc_SQLDA()
3975 short *null_indicators;
3978 if((it=(MR_SQLDA_T *)malloc(sizeof(MR_SQLDA_T)))==NULL) {
3979 com_err(whoami, MR_NO_MEM, "setting up SQLDA");
3983 if((null_indicators=(short *)calloc(QMAXARGS,sizeof(short)))==NULL) {
3984 com_err(whoami, MR_NO_MEM, "setting up SQLDA null indicators");
3988 for(j=0; j<QMAXARGS; j++) {
3989 if((it->sqlvar[j].sqldata=malloc(sizeof(short)+QMAXARGSIZE))==NULL) {
3990 com_err(whoami, MR_NO_MEM, "setting up SQLDA variables");
3993 it->sqlvar[j].sqllen=QMAXARGSIZE;
3994 it->sqlvar[j].sqlind=null_indicators+j;
3995 null_indicators[j]=0;
4002 /* Use this after FETCH USING DESCRIPTOR one or more
4003 * result columns may contain NULLs. This routine is
4004 * not currently needed, since db/schema creates all
4005 * columns with a NOT NULL WITH DEFAULT clause.
4007 * This is currently dead flesh, since no Moira columns
4008 * allow null values; all use default values.
4010 mr_fix_nulls_in_SQLDA(da)
4013 register IISQLVAR *var;
4017 for(j=0, var=da->sqlvar; j<da->sqld; j++, var++) {
4018 switch(var->sqltype) {
4019 case -IISQ_CHA_TYPE:
4023 case -IISQ_INT_TYPE:
4025 intp=(int *)var->sqldata;
4033 /* prefetch_value():
4034 * This routine fetches an appropriate value from the numvalues table.
4035 * It is a little hack to get around the fact that SQL doesn't let you
4036 * do something like INSERT INTO table (foo) VALUES (other_table.bar).
4038 * It is called from the query table as (*v->pre_rtn)(q,Argv,cl) or
4039 * from within a setup_...() routine with the appropriate arguments.
4041 * Correct functioning of this routine may depend on the assumption
4042 * that this query is an APPEND.
4045 prefetch_value(q,argv,cl)
4050 EXEC SQL BEGIN DECLARE SECTION;
4051 char *name = q->validate->object_id;
4053 EXEC SQL END DECLARE SECTION;
4054 int status, limit, argc;
4056 /* set next object id, limiting it if necessary */
4057 if(!strcmp(name, "uid") || !strcmp(name, "gid"))
4058 limit = 1; /* So far as I know, this isn't needed. Just CMA. */
4061 if((status = set_next_object_id(name, q->rtable, limit)) != MR_SUCCESS)
4064 /* fetch object id */
4065 EXEC SQL SELECT value INTO :value FROM numvalues WHERE name=:name;
4066 if(ingres_errno) return(mr_errcode);
4067 if(sqlca.sqlerrd[2] != 1) return(MR_INTERNAL);
4069 argc = q->argc + q->vcnt; /* end of Argv for APPENDs */
4070 sprintf(argv[argc],"%d",value); /** Could save this step by changing tlist from %s to %d **/
4075 /* prefetch_filesys():
4076 * Fetches the phys_id from filesys based on the filsys_id in argv[0].
4077 * Appends the filsys_id and the phys_id to the argv so they can be
4078 * referenced in an INSERT into a table other than filesys. Also
4079 * see comments at prefetch_value().
4081 * Assumes the existence of a row where filsys_id = argv[0], since a
4082 * filesys label has already been resolved to a filsys_id.
4084 prefetch_filesys(q,argv,cl)
4089 EXEC SQL BEGIN DECLARE SECTION;
4091 EXEC SQL END DECLARE SECTION;
4094 fid = *(int *)argv[0];
4095 EXEC SQL SELECT phys_id INTO :phid FROM filesys WHERE filsys_id = :fid;
4096 if(ingres_errno) return(mr_errcode);
4098 argc=q->argc+q->vcnt;
4099 sprintf(argv[argc++],"%d",phid);
4100 sprintf(argv[argc],"%d",fid);
4105 /* Convert normal Unix-style wildcards to SQL voodoo */
4106 convert_wildcards(arg)
4109 static char buffer[QMAXARGSIZE];
4110 register char *s, *d;
4112 for(d=buffer,s=arg;*s;s++) {
4114 case '*': *d++='%'; *d++='%'; break;
4115 case '?': *d++='_'; break;
4118 case ']': *d++='*'; *d++ = *s; break;
4119 case '%': *d++='*'; *d++='%'; *d++='%'; break;
4120 default: *d++ = *s; break;
4125 /* Copy back into argv */
4131 /* This version includes uppercase conversion, for things like gmac.
4132 * This is necessary because "LIKE" doesn't work with "uppercase()".
4133 * Including it in a wildcard routine saves making two passes over
4134 * the argument string.
4136 convert_wildcards_uppercase(arg)
4139 static char buffer[QMAXARGSIZE];
4140 register char *s, *d;
4142 for(d=buffer,s=arg;*s;s++) {
4144 case '*': *d++='%'; *d++='%'; break;
4145 case '?': *d++='_'; break;
4148 case ']': *d++='*'; *d++ = *s; break;
4149 case '%': *d++='*'; *d++='%'; *d++='%'; break;
4150 default: *d++=toupper(*s); break; /* This is the only diff. */
4155 /* Copy back into argv */
4162 /* Looks like it's time to build an abstraction barrier, Yogi */
4164 EXEC SQL BEGIN DECLARE SECTION;
4166 EXEC SQL END DECLARE SECTION;
4170 EXEC SQL PREPARE stmt FROM :stmt;
4171 EXEC SQL DESCRIBE stmt INTO :SQLDA;
4172 if(SQLDA->sqld==0) /* Not a SELECT */
4173 return(MR_INTERNAL);
4174 EXEC SQL DECLARE csr CURSOR FOR stmt;
4176 EXEC SQL FETCH csr USING DESCRIPTOR :SQLDA;
4177 if(sqlca.sqlcode==0)
4179 else if((sqlca.sqlcode<0) && mr_errcode)
4188 /* eof:qsupport.dc */