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[];
33 extern char cdummy[]; /** Routines which need these vars should use mr_select_any() **/
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(!strcmp(q->shortname,"guau")) {
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 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)
705 sprintf(stmt_buf,"SELECT service FROM serverhosts WHERE service = UPPERCASE('%s')",argv[0]);
706 if(ec=mr_select_any(stmt_buf)) {
707 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
710 sprintf(stmt_buf,"SELECT inprogress FROM servers WHERE name = UPPERCASE('%s')",argv[0]);
711 if(ec=mr_select_any(stmt_buf)) {
712 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
719 /* setup_dshi - verify that the service-host is no longer being referenced
720 * and may safely be deleted.
723 int setup_dshi(q, argv)
727 EXEC SQL BEGIN DECLARE SECTION;
729 EXEC SQL END DECLARE SECTION;
731 id = *(int *)argv[1];
733 sprintf(stmt_buf,"SELECT inprogress FROM serverhosts \
734 WHERE service = UPPERCASE('%s') AND mach_id = %d",argv[0],id);
735 if(ec=mr_select_any(stmt_buf)) {
736 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
744 ** setup_add_filesys - verify existance of referenced file systems
756 ** * extract directory prefix from name
757 ** * verify mach_id/dir in nfsphys
758 ** * verify access in {r, w, R, W}
760 ** Side effect: sets variable var_phys_id to the ID of the physical
761 ** filesystem (nfsphys_id for NFS, 0 for RVD)
764 ** MR_NFS - specified directory not exported
765 ** MR_FILESYS_ACCESS - invalid filesys access
769 EXEC SQL BEGIN DECLARE SECTION;
770 static int var_phys_id;
771 EXEC SQL END DECLARE SECTION;
773 setup_afil(q, argv, cl)
780 EXEC SQL BEGIN DECLARE SECTION;
782 char ftype[32], *access;
783 EXEC SQL END DECLARE SECTION;
786 mach_id = *(int *)argv[2];
791 sprintf(ftype, "fs_access_%s", type);
792 EXEC SQL SELECT trans INTO :cdummy FROM alias
793 WHERE name = :ftype AND type = 'TYPE' and trans = :access; /** Use mr_select_any() */
794 if (ingres_errno) return(mr_errcode);
795 if (sqlca.sqlerrd[2] == 0) return(MR_FILESYS_ACCESS);
797 if (!strcmp(type, "NFS"))
798 return (check_nfs(mach_id, name, access));
800 if((mr_errcode=prefetch_value(q,argv,cl))!=MR_SUCCESS)
807 /* Verify the arguments, depending on the FStype. Also, if this is an
808 * NFS filesystem, then update any quotas for that filesystem to reflect
812 setup_ufil(q, argv, cl)
819 EXEC SQL BEGIN DECLARE SECTION;
821 char *entity, ftype[32], *access;
823 EXEC SQL END DECLARE SECTION;
826 mach_id = *(int *)argv[3];
829 fid = *(int *)argv[0];
833 sprintf(ftype, "fs_access_%s", type);
834 EXEC SQL SELECT trans INTO :cdummy FROM alias
835 WHERE name = :ftype AND type='TYPE' AND trans = :access;
836 if (ingres_errno) return(mr_errcode);
837 if (sqlca.sqlerrd[2] == 0) return(MR_FILESYS_ACCESS);
839 if (!strcmp(type, "NFS")) {
840 status = check_nfs(mach_id, name, access);
841 EXEC SQL UPDATE quota SET phys_id = :var_phys_id
842 WHERE filsys_id = :fid;
843 if (ingres_errno) return(mr_errcode);
845 } else if (!strcmp(type, "AFS")) {
847 EXEC SQL REPEATED DELETE FROM quota
848 WHERE type = 'ANY' AND filsys_id = :fid;
849 EXEC SQL SELECT SUM (quota) INTO :total FROM quota
850 WHERE filsys_id = :fid AND phys_id != 0;
851 if (ingres_errno) return(mr_errcode);
854 * append quota (quota = total, filsys_id = fid,
855 * phys_id = 0, entity_id = 0, type = "ANY",
856 * modtime = "now", modby = who, modwith = entity)
858 EXEC SQL INSERT INTO quota (quota, filsys_id, phys_id, entity_id,
859 type, modtime, modby, modwith)
860 VALUES (:total, :fid, 0, 0,
861 'ANY', 'now', :who, :entity) ;
862 if (ingres_errno) return(mr_errcode);
865 EXEC SQL UPDATE quota SET phys_id = 0 WHERE filsys_id = :fid;
866 if (ingres_errno) return(mr_errcode);
872 /* Find the NFS physical partition that the named directory is on.
873 * This is done by comparing the dir against the mount point of the
874 * partition. To make sure we get the correct match when there is
875 * more than one, we sort the query in reverse order by dir name.
878 check_nfs(mach_id, name, access)
879 EXEC SQL BEGIN DECLARE SECTION;
881 EXEC SQL END DECLARE SECTION;
885 EXEC SQL BEGIN DECLARE SECTION;
887 EXEC SQL END DECLARE SECTION;
894 EXEC SQL DECLARE csr101 CURSOR FOR
895 SELECT nfsphys_id, TRIM (dir) FROM nfsphys
896 WHERE mach_id = :mach_id
898 EXEC SQL OPEN csr101;
900 EXEC SQL FETCH csr101 INTO :var_phys_id, :dir;
901 if(sqlca.sqlcode != 0) break;
905 if (*cp1++ != *cp2) break;
913 EXEC SQL CLOSE csr101;
920 /* setup_dfil: free any quota records and fsgroup info associated with
921 * a filesystem when it is deleted. Also adjust the allocation numbers.
924 setup_dfil(q, argv, cl)
929 EXEC SQL BEGIN DECLARE SECTION;
931 EXEC SQL END DECLARE SECTION;
933 id = *(int *)argv[0];
934 EXEC SQL REPEATED SELECT SUM (quota) INTO :total FROM quota
935 WHERE filsys_id = :id;
936 EXEC SQL REPEATED UPDATE nfsphys SET allocated = allocated - :total
937 WHERE nfsphys_id = filesys.phys_id AND filesys.filsys_id = :id;
938 /** Is SQL smart enough to do the PRODUCT above? */
939 /** Or should we code it using another SELECT? */
941 EXEC SQL REPEATED DELETE FROM quota WHERE filsys_id = :id;
942 EXEC SQL REPEATED DELETE FROM fsgroup WHERE filsys_id = :id;
943 EXEC SQL REPEATED DELETE FROM fsgroup WHERE group_id = :id;
944 if (ingres_errno) return(mr_errcode);
949 /* setup_dnfp: check to see that the nfs physical partition does not have
950 * any filesystems assigned to it before allowing it to be deleted.
953 setup_dnfp(q, argv, cl)
958 EXEC SQL BEGIN DECLARE SECTION;
961 EXEC SQL END DECLARE SECTION;
963 id = *(int *)argv[0];
965 EXEC SQL REPEATED SELECT label INTO :cdummy FROM filesys fs, nfsphys np
966 WHERE fs.mach_id = :id AND fs.phys_id = np.nfsphys_id
967 AND np.mach_id = :id AND np.dir = :dir;
968 if (sqlca.sqlerrd[2] > 0)
976 /* setup_dqot: Remove allocation from nfsphys before deleting quota.
977 * argv[0] = filsys_id
978 * argv[1] = type if "update_quota" or "delete_quota"
979 * argv[2 or 1] = users_id or list_id
982 setup_dqot(q, argv, cl)
987 EXEC SQL BEGIN DECLARE SECTION;
988 int quota, fs, id, physid;
990 EXEC SQL END DECLARE SECTION;
992 fs = *(int *)argv[0];
993 if (!strcmp(q->name, "update_quota") || !strcmp(q->name, "delete_quota")) {
995 id = *(int *)argv[2];
998 id = *(int *)argv[1];
1001 EXEC SQL REPEATED SELECT quota INTO :quota FROM quota
1002 WHERE type = :qtype AND entity_id = :id AND filsys_id = :fs;
1003 EXEC SQL REPEATED SELECT phys_id INTO :physid FROM filesys
1004 WHERE filsys_id = :fs;
1005 EXEC SQL REPEATED UPDATE nfsphys SET allocated = allocated - :quota
1006 WHERE nfsphys_id = :physid;
1008 if (ingres_errno) return(mr_errcode);
1013 /* setup_sshi: don't exclusive lock the machine table during
1014 * set_server_host_internal.
1017 setup_sshi(q, argv, cl)
1023 EXEC SQL set lockmode session where readlock = system;
1028 /* setup add_kerberos_user_mapping: add the string to the string
1029 * table if necessary.
1032 setup_akum(q, argv, cl)
1037 EXEC SQL BEGIN DECLARE SECTION;
1040 EXEC SQL END DECLARE SECTION;
1043 if (name_to_id(name, "STRING", &id) != MR_SUCCESS) {
1044 if (q->type != APPEND) return(MR_STRING);
1045 EXEC SQL SELECT value INTO :id FROM numvalues
1046 WHERE name = 'strings_id';
1048 EXEC SQL UPDATE numvalues SET value = :id
1049 WHERE name = 'strings_id';
1050 EXEC SQL INSERT INTO strings (string_id, string) VALUES (:id, :name);
1051 cache_entry(name, "STRING", id);
1053 if (ingres_errno) return(mr_errcode);
1054 *(int *)argv[1] = id;
1060 /* FOLLOWUP ROUTINES */
1062 /* generic set_modtime routine. This takes the table name from the query,
1063 * and will update the modtime, modby, and modwho fields in the entry in
1064 * the table whose name field matches argv[0].
1067 set_modtime(q, argv, cl)
1072 char *name, *entity, *table;
1075 entity = cl->entity;
1076 who = cl->client_id;
1080 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);
1081 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
1086 /* generic set_modtime_by_id routine. This takes the table name from
1087 * the query, and the id name from the validate record,
1088 * and will update the modtime, modby, and modwho fields in the entry in
1089 * the table whose id matches argv[0].
1092 set_modtime_by_id(q, argv, cl)
1097 char *entity, *table, *id_name;
1100 entity = cl->entity;
1101 who = cl->client_id;
1103 id_name = q->validate->object_id;
1105 id = *(int *)argv[0];
1106 sprintf(stmt_buf,"UPDATE %s SET modtime = 'now', modby = %d, \
1107 modwith = '%s' WHERE %s.%s = %d",table,who,entity,table,id_name,id);
1108 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
1113 /* Sets the finger modtime on a user record. The users_id will be in argv[0].
1116 set_finger_modtime(q, argv, cl)
1121 EXEC SQL BEGIN DECLARE SECTION;
1124 EXEC SQL END DECLARE SECTION;
1126 entity = cl->entity;
1127 who = cl->client_id;
1128 users_id = *(int *)argv[0];
1130 EXEC SQL UPDATE users SET fmodtime='now', fmodby = :who, fmodwith = :entity
1131 WHERE users.users_id = :users_id;
1137 /* Sets the pobox modtime on a user record. The users_id will be in argv[0].
1140 set_pobox_modtime(q, argv, cl)
1145 EXEC SQL BEGIN DECLARE SECTION;
1148 EXEC SQL END DECLARE SECTION;
1150 entity = cl->entity;
1151 who = cl->client_id;
1152 users_id = *(int *)argv[0];
1154 EXEC SQL UPDATE users SET pmodtime='now', pmodby = :who, pmodwith = :entity
1155 WHERE users.users_id = :users_id;
1161 /* Like set_modtime, but uppercases the name first.
1164 set_uppercase_modtime(q, argv, cl)
1169 char *name, *entity, *table;
1172 entity = cl->entity;
1173 who = cl->client_id;
1177 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);
1178 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
1184 /* Sets the modtime on the machine whose mach_id is in argv[0]. This routine
1185 * is necessary for add_machine_to_cluster becuase the table that query
1186 * operates on is "mcm", not "machine".
1189 set_mach_modtime_by_id(q, argv, cl)
1194 EXEC SQL BEGIN DECLARE SECTION;
1197 EXEC SQL END DECLARE SECTION;
1199 entity = cl->entity;
1200 who = cl->client_id;
1201 id = *(int *)argv[0];
1202 EXEC SQL UPDATE machine SET modtime='now', modby = :who, modwith = :entity
1203 WHERE machine.mach_id = :id;
1209 /* Sets the modtime on the cluster whose mach_id is in argv[0]. This routine
1210 * is necessary for add_cluster_data and delete_cluster_data becuase the
1211 * table that query operates on is "svc", not "cluster".
1214 set_cluster_modtime_by_id(q, argv, cl)
1219 EXEC SQL BEGIN DECLARE SECTION;
1222 EXEC SQL END DECLARE SECTION;
1224 entity = cl->entity;
1225 who = cl->client_id;
1227 id = *(int *)argv[0];
1228 EXEC SQL UPDATE cluster SET modtime='now', modby = :who, modwith = :entity
1229 WHERE cluster.clu_id = :id;
1234 /* sets the modtime on the serverhost where the service name is in argv[0]
1235 * and the mach_id is in argv[1].
1238 set_serverhost_modtime(q, argv, cl)
1243 EXEC SQL BEGIN DECLARE SECTION;
1244 char *entity, *serv;
1246 EXEC SQL END DECLARE SECTION;
1248 entity = cl->entity;
1249 who = cl->client_id;
1252 id = *(int *)argv[1];
1253 EXEC SQL UPDATE serverhosts
1254 SET modtime = 'now', modby = :who, modwith = :entity
1255 WHERE service = :serv AND mach_id = :id;
1260 /* sets the modtime on the nfsphys where the mach_id is in argv[0] and the
1261 * directory name is in argv[1].
1264 set_nfsphys_modtime(q, argv, cl)
1269 EXEC SQL BEGIN DECLARE SECTION;
1272 EXEC SQL END DECLARE SECTION;
1274 entity = cl->entity;
1275 who = cl->client_id;
1277 id = *(int *)argv[0];
1279 EXEC SQL UPDATE nfsphys SET modtime = 'now', modby = :who, modwith = :entity
1280 WHERE dir = :dir AND mach_id = :id;
1285 /* sets the modtime on a filesystem, where argv[0] contains the filesys
1289 set_filesys_modtime(q, argv, cl)
1294 EXEC SQL BEGIN DECLARE SECTION;
1295 char *label, *entity;
1297 EXEC SQL END DECLARE SECTION;
1299 entity = cl->entity;
1300 who = cl->client_id;
1303 if (!strcmp(q->shortname, "ufil"))
1306 EXEC SQL UPDATE filesys SET modtime = 'now', modby = :who,
1307 modwith = :entity, phys_id = :var_phys_id
1308 WHERE label = LEFT(:label,SIZE(label));
1313 /* sets the modtime on a zephyr class, where argv[0] contains the class
1317 set_zephyr_modtime(q, argv, cl)
1322 EXEC SQL BEGIN DECLARE SECTION;
1323 char *class, *entity;
1325 EXEC SQL END DECLARE SECTION;
1327 entity = cl->entity;
1328 who = cl->client_id;
1332 EXEC SQL UPDATE zephyr SET modtime = 'now', modby = :who, modwith = :entity
1333 WHERE class = LEFT(:class,SIZE(class));
1339 /* fixes the modby field. This will be the second to last thing in the
1340 * argv, the argv length is determined from the query structure. It is
1341 * passed as a pointer to an integer. This will either turn it into a
1342 * username, or # + the users_id.
1344 followup_fix_modby(q, sq, v, action, actarg, cl)
1346 register struct save_queue *sq;
1348 register int (*action)();
1349 register int actarg;
1353 char **argv, *malloc();
1357 while (sq_get_data(sq, &argv)) {
1360 status = id_to_name(id, "USER", &argv[i]);
1362 status = id_to_name(-id, "STRING", &argv[i]);
1363 if (status && status != MR_NO_MATCH)
1365 (*action)(q->vcnt, argv, actarg);
1366 for (j = 0; j < q->vcnt; j++)
1375 /* After retrieving a user account, fix the modby field and signature.
1376 * The modby field is the second to last thing in the
1377 * argv, the argv length is determined from the query structure. It is
1378 * passed as a pointer to an integer. This will either turn it into a
1379 * username, or # + the users_id. Only "gua*" queries have a signature,
1380 * these are ones with U_END return values. "gub*" queries also use this
1381 * routine but don't have a signature.
1383 followup_guax(q, sq, v, action, actarg, cl)
1385 register struct save_queue *sq;
1387 register int (*action)();
1388 register int actarg;
1392 char **argv, *malloc();
1394 unsigned char sigbuf[256];
1397 EXEC SQL BEGIN DECLARE SECTION;
1400 EXEC SQL END DECLARE SECTION;
1405 while (sq_get_data(sq, &argv)) {
1408 status = id_to_name(id, "USER", &argv[i]);
1410 status = id_to_name(-id, "STRING", &argv[i]);
1411 if (status && status != MR_NO_MATCH)
1414 if (q->vcnt == U_END && strlen(argv[U_SIGNATURE])) {
1415 login = argv[U_NAME];
1416 EXEC SQL REPEATED SELECT sigdate, sigwho
1417 INTO :timestamp, :who FROM users
1418 WHERE login = LEFT(:login,SIZE(login));
1419 /** What about (INGRES) error handling? **/
1421 status = id_to_name(who, "STRING", &kname);
1422 si.timestamp = timestamp;
1423 si.SigInfoVersion = 0; /* XXXXX this isn't used */
1424 kname_parse(si.pname, si.pinst, si.prealm, kname);
1426 si.rawsig = (unsigned char *)argv[U_SIGNATURE];
1427 GDSS_Recompose(&si, sigbuf);
1428 argv[U_SIGNATURE] = strsave(sigbuf);
1431 (*action)(q->vcnt, argv, actarg);
1432 for (j = 0; j < q->vcnt; j++)
1442 ** followup_ausr - add finger and pobox entries, set_user_modtime
1445 ** argv[0] - login (add_user)
1446 ** argv[3] - last name
1447 ** argv[4] - first name
1448 ** argv[5] - middle name
1452 followup_ausr(q, argv, cl)
1457 EXEC SQL BEGIN DECLARE SECTION;
1458 int who, status, id;
1459 char *login, *entity, *src, *dst, *name;
1461 EXEC SQL END DECLARE SECTION;
1463 char databuf[32], *kname_unparse();
1464 EXEC SQL BEGIN DECLARE SECTION;
1466 int sigwho, timestamp;
1467 EXEC SQL END DECLARE SECTION;
1471 /* build fullname */
1472 if (strlen(argv[4]) && strlen(argv[5]))
1473 sprintf(fullname, "%s %s %s", argv[4], argv[5], argv[3]);
1474 else if (strlen(argv[4]))
1475 sprintf(fullname, "%s %s", argv[4], argv[3]);
1477 sprintf(fullname, "%s", argv[3]);
1480 if (q->vcnt == U_END && *argv[U_SIGNATURE]) {
1481 sprintf(databuf, "%s:%s", argv[U_NAME], argv[U_MITID]);
1482 /* skip bytes for timestamp & kname */
1483 si.rawsig = (unsigned char *) rawsig;
1484 status = GDSS_Verify(databuf, strlen(databuf), argv[U_SIGNATURE], &si);
1485 if (strlen(rawsig) > mr_sig_length) {
1486 com_err(whoami, 0, "GDSS signature would be truncated."); /** untested **/
1487 return(MR_INTERNAL);
1490 name = kname_unparse(si.pname, si.pinst, si.prealm);
1491 status = name_to_id(name, "STRING", &sigwho);
1492 if (status == MR_NO_MATCH) {
1493 EXEC SQL REPEATED SELECT value INTO :sigwho FROM numvalues
1494 WHERE name='strings_id';
1496 EXEC SQL REPEATED UPDATE numvalues SET value = :sigwho
1497 WHERE name='strings_id';
1498 INSERT INTO strings (string_id, string)
1499 VALUES (:sigwho, :name);
1501 return(gdss2et(status));
1502 timestamp = si.timestamp;
1504 return(gdss2et(status));
1513 who = cl->client_id;
1514 entity = cl->entity;
1516 /* create finger entry & pobox, set modtime on user, and update search fields */
1518 EXEC SQL REPEATED UPDATE users
1519 SET modtime='now', modby=:who, modwith = :entity,
1520 fullname = :fullname, affiliation = type,
1521 searchfirst = UPPERCASE(first), searchlast = UPPERCASE(last),
1522 signature = :rawsig, sigdate = :timestamp, sigwho = :sigwho,
1523 fmodtime='now', fmodby = :who, fmodwith = :entity,
1524 potype='NONE', pmodtime='now', pmodby = :who, pmodwith = :entity
1525 WHERE login = :login;
1527 EXEC SQL REPEATED UPDATE users
1528 SET modtime='now', modby=:who, modwith = :entity,
1529 fullname = :fullname, affiliation = type,
1530 searchfirst = UPPERCASE(first), searchlast = UPPERCASE(last),
1531 fmodtime='now', fmodby = :who, fmodwith = :entity,
1532 potype='NONE', pmodtime='now', pmodby = :who, pmodwith = :entity
1533 WHERE login = :login;
1541 ** followup_uusr - do signature, set_user_modtime
1544 ** argv[0] - login (add_user)
1545 ** argv[U_SIGNATURE] - sig
1549 followup_uuac(q, argv, cl)
1554 EXEC SQL BEGIN DECLARE SECTION;
1555 int who, status, id;
1556 char *entity, *name;
1557 EXEC SQL END DECLARE SECTION;
1559 char databuf[32], *kname_unparse();
1560 EXEC SQL BEGIN DECLARE SECTION;
1563 int sigwho, timestamp;
1564 EXEC SQL END DECLARE SECTION;
1568 id = *(int *)argv[0];
1569 who = cl->client_id;
1570 entity = cl->entity;
1573 if (q->vcnt == U_MODTIME && *argv[U_SIGNATURE + 1]) {
1575 status = id_to_name(id, "USER", &login);
1576 sprintf(databuf, "%s:%s", login, argv[U_MITID+1]);
1578 /* skip bytes for timestamp & kname */
1579 si.rawsig = (unsigned char *) rawsig;
1580 status = GDSS_Verify(databuf, strlen(databuf), argv[U_SIGNATURE+1], &si);
1581 if (strlen(rawsig) > mr_sig_length) {
1582 com_err(whoami, 0, "GDSS signature would be truncated."); /** untested **/
1583 return(MR_INTERNAL);
1586 name = kname_unparse(si.pname, si.pinst, si.prealm);
1587 status = name_to_id(name, "STRING", &sigwho);
1588 if (status == MR_NO_MATCH) {
1589 EXEC SQL REPEATED SELECT value INTO :sigwho FROM numvalues
1590 WHERE name='strings_id';
1592 EXEC SQL REPEATED UPDATE numvalues SET value = :sigwho
1593 WHERE name='strings_id';
1594 INSERT INTO strings (string_id, string)
1595 VALUES (:sigwho, :name);
1597 return(gdss2et(status));
1598 timestamp = si.timestamp;
1600 return(gdss2et(status));
1608 /* set modtime on user and update search fields */
1611 EXEC SQL REPEATED UPDATE users SET modtime='now', modby = :who, modwith = :entity,
1612 signature = :rawsig, sigdate = :timestamp, sigwho = :sigwho,
1613 searchfirst = UPPERCASE(first), searchlast = UPPERCASE(last)
1614 WHERE users_id = :id;
1616 EXEC SQL REPEATED UPDATE users SET modtime='now', modby = :who, modwith = :entity,
1617 searchfirst = UPPERCASE(first), searchlast = UPPERCASE(last)
1618 WHERE users_id = :id;
1624 /* followup_gpob: fixes argv[2] based on the IDs currently there and the
1625 * type in argv[1]. Then completes the upcall to the user.
1627 * argv[2] is of the form "123:234" where the first integer is the machine
1628 * ID if it is a pop box, and the second is the string ID if it is an SMTP
1629 * box. argv[1] should be "POP", "SMTP", or "NONE". Boxes of type NONE
1633 followup_gpob(q, sq, v, action, actarg, cl)
1634 register struct query *q;
1635 register struct save_queue *sq;
1636 register struct validate *v;
1637 register int (*action)();
1641 char **argv, *index();
1643 int mid, sid, status, i;
1646 while (sq_get_data(sq, &argv)) {
1647 mr_trim_args(2, argv);
1649 p = index(argv[2], ':');
1651 mid = atoi(argv[2]);
1654 if (!strcmp(ptype, "POP")) {
1655 status = id_to_name(mid, "MACHINE", &argv[2]);
1656 if (status == MR_NO_MATCH)
1658 } else if (!strcmp(ptype, "SMTP")) {
1659 status = id_to_name(sid, "STRING", &argv[2]);
1660 if (status == MR_NO_MATCH)
1662 } else /* ptype == "NONE" */ {
1665 if (status) return(status);
1667 if (!strcmp(q->shortname, "gpob")) {
1668 sid = atoi(argv[4]);
1670 status = id_to_name(sid, "USER", &argv[4]);
1672 status = id_to_name(-sid, "STRING", &argv[4]);
1674 if (status && status != MR_NO_MATCH) return(status);
1676 (*action)(q->vcnt, argv, actarg);
1678 /* free saved data */
1679 for (i = 0; i < q->vcnt; i++)
1685 return (MR_SUCCESS);
1689 /* followup_glin: fix the ace_name in argv[8]. argv[7] will contain the
1690 * ace_type: "LIST", "USER", or "NONE". Decode the id in argv[8] into the
1691 * proper name based on the type, and repace that string in the argv.
1692 * Also fixes the modby field by called followup_fix_modby.
1695 followup_glin(q, sq, v, action, actarg, cl)
1696 register struct query *q;
1697 register struct save_queue *sq;
1698 register struct validate *v;
1699 register int (*action)();
1703 char **argv, *malloc(), *realloc(), *type;
1704 int id, i, idx, status;
1707 if (!strcmp(q->shortname, "gsin"))
1710 while (sq_get_data(sq, &argv)) {
1711 mr_trim_args(q->vcnt, argv);
1713 id = atoi(argv[i = q->vcnt - 2]);
1715 status = id_to_name(id, "USER", &argv[i]);
1717 status = id_to_name(-id, "STRING", &argv[i]);
1718 if (status && status != MR_NO_MATCH)
1721 id = atoi(argv[idx]);
1722 type = argv[idx - 1];
1724 if (!strcmp(type, "LIST")) {
1725 status = id_to_name(id, "LIST", &argv[idx]);
1726 } else if (!strcmp(type, "USER")) {
1727 status = id_to_name(id, "USER", &argv[idx]);
1728 } else if (!strcmp(type, "KERBEROS")) {
1729 status = id_to_name(id, "STRING", &argv[idx]);
1730 } else if (!strcmp(type, "NONE")) {
1733 argv[idx] = strsave("NONE");
1737 argv[idx] = strsave("???");
1739 if (status && status != MR_NO_MATCH)
1742 if (!strcmp(q->shortname, "glin") && atoi(argv[6]) == -1) {
1743 argv[6] = realloc(argv[6], strlen(UNIQUE_GID) + 1);
1744 strcpy(argv[6], UNIQUE_GID);
1748 (*action)(q->vcnt, argv, actarg);
1750 /* free saved data */
1751 for (i = 0; i < q->vcnt; i++)
1757 return (MR_SUCCESS);
1761 /* followup_gqot: Fix the entity name, directory name & modby fields
1762 * argv[0] = filsys_id
1764 * argv[2] = entity_id
1765 * argv[3] = ascii(quota)
1768 followup_gqot(q, sq, v, action, actarg, cl)
1770 register struct save_queue *sq;
1772 register int (*action)();
1773 register int actarg;
1777 char **argv, *malloc();
1778 EXEC SQL BEGIN DECLARE SECTION;
1781 EXEC SQL END DECLARE SECTION;
1784 if (!strcmp(q->name, "get_quota") ||
1785 !strcmp(q->name, "get_quota_by_filesys"))
1789 while (sq_get_data(sq, &argv)) {
1791 switch (argv[1][0]) {
1793 status = id_to_name(atoi(argv[2]), "USER", &argv[2]);
1797 status = id_to_name(atoi(argv[2]), "LIST", &argv[2]);
1801 argv[2] = strsave("system:anyuser");
1805 argv[2] = malloc(8);
1806 sprintf(argv[2], "%d", id);
1809 id = atoi(argv[idx]);
1811 argv[idx] = malloc(256);
1815 EXEC SQL REPEATED SELECT name INTO :name FROM filesys
1816 WHERE label = :label;
1818 EXEC SQL REPEATED SELECT dir INTO :name FROM nfsphys
1819 WHERE nfsphys_id = :id;
1821 if (sqlca.sqlerrd[2] != 1) {
1822 sprintf(argv[idx], "#%d", id);
1825 id = atoi(argv[idx+3]);
1827 status = id_to_name(id, "USER", &argv[idx+3]);
1829 status = id_to_name(-id, "STRING", &argv[idx+3]);
1830 if (status && status != MR_NO_MATCH)
1832 (*action)(q->vcnt, argv, actarg);
1833 for (j = 0; j < q->vcnt; j++)
1842 /* followup_aqot: Add allocation to nfsphys after creating quota.
1843 * argv[0] = filsys_id
1844 * argv[1] = type if "add_quota" or "update_quota"
1846 * argv[3 or 2] = ascii(quota)
1849 followup_aqot(q, argv, cl)
1854 EXEC SQL BEGIN DECLARE SECTION;
1855 int quota, id, fs, who, physid;
1856 char *entity, *qtype;
1857 EXEC SQL END DECLARE SECTION;
1859 fs = *(int *)argv[0];
1860 if (!strcmp(q->name, "add_quota") || !strcmp(q->name, "update_quota")) {
1862 id = *(int *)argv[2];
1863 quota = atoi(argv[3]);
1866 id = *(int *)argv[1];
1867 quota = atoi(argv[2]);
1869 who = cl->client_id;
1870 entity = cl->entity;
1872 EXEC SQL REPEATED UPDATE quota
1873 SET modtime = 'now', modby = :who, modwith = :entity
1874 WHERE filsys_id = :fs and type = :qtype and entity_id = :id;
1875 EXEC SQL REPEATED SELECT phys_id INTO :physid FROM filesys
1876 WHERE filsys_id = :fs;
1877 EXEC SQL REPEATED UPDATE nfsphys SET allocated = allocated + :quota
1878 WHERE nfsphys_id = :physid;
1879 if (ingres_errno) return(mr_errcode);
1884 followup_gpce(q, sq, v, action, actarg, cl)
1886 register struct save_queue *sq;
1888 register int (*action)();
1889 register int actarg;
1893 char **argv, *malloc();
1897 while (sq_get_data(sq, &argv)) {
1898 id = atoi(argv[PCAP_QSERVER]);
1899 status = id_to_name(id, "MACHINE", &argv[PCAP_QSERVER]);
1900 if (status) return (status);
1903 status = id_to_name(id, "USER", &argv[i]);
1905 status = id_to_name(-id, "STRING", &argv[i]);
1906 if (status && status != MR_NO_MATCH)
1908 (*action)(q->vcnt, argv, actarg);
1909 for (j = 0; j < q->vcnt; j++)
1921 followup_gzcl(q, sq, v, action, actarg, cl)
1922 register struct query *q;
1923 register struct save_queue *sq;
1924 register struct validate *v;
1925 register int (*action)();
1932 while (sq_get_data(sq, &argv)) {
1933 mr_trim_args(q->vcnt, argv);
1935 id = atoi(argv[i = q->vcnt - 2]);
1937 status = id_to_name(id, "USER", &argv[i]);
1939 status = id_to_name(-id, "STRING", &argv[i]);
1940 if (status && status != MR_NO_MATCH)
1943 for (i = 1; i < 8; i+=2) {
1944 id = atoi(argv[i+1]);
1945 if (!strcmp(argv[i], "LIST")) {
1946 status = id_to_name(id, "LIST", &argv[i+1]);
1947 } else if (!strcmp(argv[i], "USER")) {
1948 status = id_to_name(id, "USER", &argv[i+1]);
1949 } else if (!strcmp(argv[i], "KERBEROS")) {
1950 status = id_to_name(id, "STRING", &argv[i+1]);
1951 } else if (!strcmp(argv[i], "NONE")) {
1954 argv[i+1] = strsave("NONE");
1958 argv[i+1] = strsave("???");
1960 if (status && status != MR_NO_MATCH)
1965 (*action)(q->vcnt, argv, actarg);
1967 /* free saved data */
1968 for (i = 0; i < q->vcnt; i++)
1980 followup_gsha(q, sq, v, action, actarg, cl)
1981 register struct query *q;
1982 register struct save_queue *sq;
1983 register struct validate *v;
1984 register int (*action)();
1991 while (sq_get_data(sq, &argv)) {
1992 mr_trim_args(q->vcnt, argv);
1996 status = id_to_name(id, "USER", &argv[4]);
1998 status = id_to_name(-id, "STRING", &argv[4]);
1999 if (status && status != MR_NO_MATCH)
2003 if (!strcmp(argv[1], "LIST")) {
2004 status = id_to_name(id, "LIST", &argv[2]);
2005 } else if (!strcmp(argv[1], "USER")) {
2006 status = id_to_name(id, "USER", &argv[2]);
2007 } else if (!strcmp(argv[1], "KERBEROS")) {
2008 status = id_to_name(id, "STRING", &argv[2]);
2009 } else if (!strcmp(argv[1], "NONE")) {
2012 argv[2] = strsave("NONE");
2016 argv[2] = strsave("???");
2018 if (status && status != MR_NO_MATCH)
2022 (*action)(q->vcnt, argv, actarg);
2024 /* free saved data */
2025 for (i = 0; i < q->vcnt; i++)
2035 /* Special query routines */
2037 /* set_pobox - this does all of the real work.
2038 * argv = user_id, type, box
2039 * if type is POP, then box should be a machine, and its ID should be put in
2040 * pop_id. If type is SMTP, then box should be a string and its ID should
2041 * be put in box_id. If type is NONE, then box doesn't matter.
2044 int set_pobox(q, argv, cl)
2049 EXEC SQL BEGIN DECLARE SECTION;
2051 char *box, potype[9];
2052 EXEC SQL END DECLARE SECTION;
2056 user = *(int *)argv[0];
2058 EXEC SQL REPEATED SELECT pop_id, potype INTO :id, :potype FROM users
2059 WHERE users_id = :user;
2060 if (ingres_errno) return(mr_errcode);
2061 if (!strcmp(strtrim(potype), "POP"))
2062 set_pop_usage(id, -1);
2064 if (!strcmp(argv[1], "POP")) {
2065 status = name_to_id(box, "MACHINE", &id);
2066 if (status == MR_NO_MATCH)
2070 EXEC SQL REPEATED UPDATE users SET potype = 'POP', pop_id = :id
2071 WHERE users_id = :user;
2072 set_pop_usage(id, 1);
2073 } else if (!strcmp(argv[1], "SMTP")) {
2074 if (index(box, '/') || index(box, '|'))
2075 return(MR_BAD_CHAR);
2076 status = name_to_id(box, "STRING", &id);
2077 if (status == MR_NO_MATCH) {
2078 EXEC SQL REPEATED SELECT value INTO :id FROM numvalues
2079 WHERE name='strings_id';
2081 EXEC SQL REPEATED UPDATE numvalues SET value = :id
2082 WHERE name='strings_id';
2083 EXEC SQL INSERT INTO strings (string_id, string)
2087 EXEC SQL REPEATED UPDATE users SET potype='SMTP', box_id = :id
2088 WHERE users_id = :user;
2089 } else /* argv[1] == "NONE" */ {
2090 EXEC SQL REPEATED UPDATE users SET potype='NONE'
2091 WHERE users_id = :user;
2094 set_pobox_modtime(q, argv, cl);
2095 EXEC SQL REPEATED UPDATE tblstats SET updates = updates+1, modtime='now'
2096 WHERE tblstats.table_name='users';
2097 if (ingres_errno) return(mr_errcode);
2102 /* get_list_info: passed a wildcard list name, returns lots of stuff about
2103 * each list. This is tricky: first build a queue of all requested
2104 * data. Rest of processing consists of fixing gid, ace_name, and modby.
2107 get_list_info(q, aargv, cl, action, actarg)
2108 register struct query *q;
2111 register int (*action)();
2114 char *argv[13], *malloc(), *realloc();
2115 EXEC SQL BEGIN DECLARE SECTION;
2116 char *name, acl_type[9], listname[33], active[5], public[5], hidden[5];
2117 char maillist[5], grouplist[5], gid_str[6], acl_name[256], desc[256];
2118 char modtime[27], modby[256], modwith[9];
2119 int id, rowcount, acl_id, hid, modby_id;
2120 EXEC SQL END DECLARE SECTION;
2121 int returned, status;
2122 struct save_queue *sq, *sq_create();
2124 returned = rowcount = 0;
2126 convert_wildcards(name);
2129 EXEC SQL DECLARE csr102 CURSOR FOR SELECT list_id FROM list
2130 WHERE name LIKE :name ESCAPE '*';
2131 EXEC SQL OPEN csr102;
2134 EXEC SQL FETCH csr102 INTO :id;
2135 if(sqlca.sqlcode!=0) break;
2136 sq_save_data(sq, id);
2139 EXEC SQL CLOSE csr102;
2141 if (ingres_errno) return(mr_errcode);
2143 return(MR_NO_MATCH);
2145 argv[0] = listname; argv[1] = active; argv[2] = public; argv[3] = hidden;
2146 argv[4] = maillist; argv[5] = grouplist; argv[6] = gid_str;
2147 argv[7] = acl_type; argv[9] = desc; argv[10] = modtime; argv[12] = modwith;
2149 while (sq_get_data(sq, &id)) {
2153 EXEC SQL REPEATED SELECT name, CHAR(active), CHAR(publicflg),
2154 CHAR(hidden), hidden, CHAR(maillist), CHAR(grouplist), CHAR(gid),
2155 TRIM(acl_type), acl_id, description, CHAR(modtime), modby, modwith
2156 INTO :listname, :active, :public, :hidden, :hid, :maillist,
2157 :grouplist, :gid_str, :acl_type, :acl_id, :desc,
2158 :modtime, :modby_id, :modwith
2159 FROM list WHERE list_id = :id;
2161 if (ingres_errno) return(mr_errcode);
2163 if (atoi(gid_str) == -1)
2164 argv[6] = UNIQUE_GID;
2166 argv[8] = malloc(0);
2167 if (!strcmp(acl_type, "LIST")) {
2168 status = id_to_name(acl_id, "LIST", &argv[8]);
2169 } else if (!strcmp(acl_type, "USER")) {
2170 status = id_to_name(acl_id, "USER", &argv[8]);
2171 } else if (!strcmp(acl_type, "KERBEROS")) {
2172 status = id_to_name(acl_id, "STRING", &argv[8]);
2173 } else if (!strcmp(acl_type, "NONE")) {
2176 argv[8] = strsave("NONE");
2180 argv[8] = strsave("???");
2182 if (status && status != MR_NO_MATCH) return(status);
2184 argv[11] = malloc(0);
2186 status = id_to_name(modby_id, "USER", &argv[11]);
2188 status = id_to_name(-modby_id, "STRING", &argv[11]);
2189 if (status && status != MR_NO_MATCH) return(status);
2191 mr_trim_args(q->vcnt, argv);
2193 (*action)(q->vcnt, argv, actarg);
2199 if (ingres_errno) return(mr_errcode);
2200 return (MR_SUCCESS);
2204 /* Add_member_to_list: do list flattening as we go! MAXLISTDEPTH is
2205 * how many different ancestors a member is allowed to have.
2208 #define MAXLISTDEPTH 1024
2210 int add_member_to_list(q, argv, cl)
2215 EXEC SQL BEGIN DECLARE SECTION;
2216 int id, lid, mid, error, who, ref;
2217 char *mtype, dtype[9], *entity;
2218 EXEC SQL END DECLARE SECTION;
2219 int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a;
2220 int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d;
2222 char *dtypes[MAXLISTDEPTH];
2223 char *iargv[3], *buf;
2225 lid = *(int *)argv[0];
2227 mid = *(int *)argv[2];
2228 /* if the member is already a direct member of the list, punt */
2229 EXEC SQL REPEATED SELECT list_id INTO :idummy FROM imembers
2230 WHERE list_id = :lid AND member_id = :mid
2231 AND member_type = :mtype AND direct = 1;
2232 if (sqlca.sqlerrd[2] > 0)
2234 if (!strcasecmp(mtype, "STRING")) {
2236 status = id_to_name(mid, "STRING", &buf);
2237 if (status) return(status);
2238 if (index(buf, '/') || index(buf, '|')) {
2240 return(MR_BAD_CHAR);
2248 EXEC SQL DECLARE csr103 CURSOR FOR
2249 SELECT list_id, ref_count FROM imembers
2250 WHERE member_id = :lid AND member_type='LIST';
2251 EXEC SQL OPEN csr103;
2253 EXEC SQL FETCH csr103 INTO :id, :ref;
2254 if(sqlca.sqlcode != 0) break;
2256 ancestors[acount++] = id;
2257 if (acount >= MAXLISTDEPTH) break;
2259 EXEC SQL CLOSE csr103;
2260 if (ingres_errno) return(mr_errcode);
2261 if (acount >= MAXLISTDEPTH) {
2262 return(MR_INTERNAL);
2264 descendants[0] = mid;
2269 if (!strcmp(mtype, "LIST")) {
2270 EXEC SQL DECLARE csr104 CURSOR FOR
2271 SELECT member_id, member_type, ref_count
2273 WHERE list_id = :mid;
2274 EXEC SQL OPEN csr104;
2276 EXEC SQL FETCH csr104 INTO :id, :dtype, :ref;
2277 if(sqlca.sqlcode != 0) break;
2280 dtypes[dcount] = "LIST";
2283 dtypes[dcount] = "USER";
2286 dtypes[dcount] = "STRING";
2289 dtypes[dcount] = "KERBEROS";
2296 descendants[dcount++] = id;
2297 if (dcount >= MAXLISTDEPTH) {
2302 EXEC SQL CLOSE csr104;
2303 if (ingres_errno) return(mr_errcode);
2305 return(MR_INTERNAL);
2307 for (a = 0; a < acount; a++) {
2309 for (d = 0; d < dcount; d++) {
2310 mid = descendants[d];
2312 if (mid == lid && !strcmp(mtype, "LIST")) {
2313 return(MR_LISTLOOP);
2315 EXEC SQL REPEATED SELECT ref_count INTO :idummy FROM imembers
2316 WHERE list_id = :lid AND member_id = :mid
2317 AND member_type = :mtype;
2318 ref = aref[a] * dref[d];
2319 if (sqlca.sqlerrd[2] > 0) {
2320 if (a == 0 && d == 0) {
2321 EXEC SQL UPDATE imembers
2322 SET ref_count = ref_count+:ref, direct=1
2323 WHERE list_id = :lid AND member_id = :mid
2324 AND member_type = :mtype;
2326 EXEC SQL UPDATE imembers
2327 SET ref_count = ref_count+:ref
2328 WHERE list_id = :lid AND member_id = :mid
2329 AND member_type = :mtype;
2332 incremental_clear_before();
2333 if (a == 0 && d == 0) {
2334 EXEC SQL INSERT INTO imembers
2335 (list_id, member_id, direct, member_type, ref_count)
2336 VALUES (:lid, :mid, 1, :mtype, 1);
2338 EXEC SQL INSERT INTO imembers
2339 (list_id, member_id, member_type, ref_count)
2340 VALUES (:lid, :mid, :mtype, 1);
2342 iargv[0] = (char *)lid;
2344 iargv[2] = (char *)mid;
2345 incremental_after("members", 0, iargv);
2349 lid = *(int *)argv[0];
2350 entity = cl->entity;
2351 who = cl->client_id;
2352 EXEC SQL REPEATED UPDATE list
2353 SET modtime='now', modby = :who, modwith = :entity
2354 WHERE list_id = :lid;
2355 if (ingres_errno) return(mr_errcode);
2360 /* Delete_member_from_list: do list flattening as we go!
2363 int delete_member_from_list(q, argv, cl)
2368 EXEC SQL BEGIN DECLARE SECTION;
2369 int id, lid, mid, cnt, error, who, ref;
2370 char *mtype, dtype[9], *entity;
2371 EXEC SQL END DECLARE SECTION;
2372 int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a;
2373 int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d;
2374 char *dtypes[MAXLISTDEPTH];
2377 lid = *(int *)argv[0];
2379 mid = *(int *)argv[2];
2380 /* if the member is not a direct member of the list, punt */
2381 EXEC SQL REPEATED SELECT list_id INTO :idummy FROM imembers
2382 WHERE list_id = :lid AND member_id = :mid
2383 AND member_type = :mtype AND direct = 1;
2384 if (ingres_errno) return(mr_errcode);
2385 if (sqlca.sqlcode == 100)
2386 return(MR_NO_MATCH);
2390 EXEC SQL DECLARE csr105 CURSOR FOR
2391 SELECT list_id, ref_count FROM imembers
2392 WHERE member_id = :lid AND member_type = 'LIST';
2393 EXEC SQL OPEN csr105;
2395 EXEC SQL FETCH csr105 INTO :id, :ref;
2396 if(sqlca.sqlcode!=0) break;
2398 ancestors[acount++] = id;
2399 if (acount >= MAXLISTDEPTH) break;
2401 EXEC SQL CLOSE csr105;
2404 if (acount >= MAXLISTDEPTH)
2405 return(MR_INTERNAL);
2406 descendants[0] = mid;
2411 if (!strcmp(mtype, "LIST")) {
2412 EXEC SQL DECLARE csr106 CURSOR FOR
2413 SELECT member_id, member_type, ref_count FROM imembers
2414 WHERE list_id = :mid;
2415 EXEC SQL OPEN csr106;
2417 EXEC SQL FETCH csr106 INTO :id, :dtype, :ref;
2418 if(sqlca.sqlcode!=0) break;
2421 dtypes[dcount] = "LIST";
2424 dtypes[dcount] = "USER";
2427 dtypes[dcount] = "STRING";
2430 dtypes[dcount] = "KERBEROS";
2437 descendants[dcount++] = id;
2438 if (dcount >= MAXLISTDEPTH) break;
2440 EXEC SQL CLOSE csr106;
2444 return(MR_INTERNAL);
2446 for (a = 0; a < acount; a++) {
2448 for (d = 0; d < dcount; d++) {
2449 mid = descendants[d];
2451 if (mid == lid && !strcmp(mtype, "LIST")) {
2452 return(MR_LISTLOOP);
2454 EXEC SQL REPEATED SELECT ref_count INTO :cnt FROM imembers
2455 WHERE list_id = :lid AND member_id = :mid AND member_type = :mtype;
2456 ref = aref[a] * dref[d];
2458 iargv[0] = (char *)lid;
2460 iargv[2] = (char *)mid;
2461 incremental_before("members", 0, iargv);
2462 EXEC SQL DELETE FROM imembers
2463 WHERE list_id = :lid AND member_id = :mid
2464 AND member_type= :mtype;
2465 incremental_clear_after();
2466 } else if (a == 0 && d == 0) {
2467 EXEC SQL UPDATE imembers
2468 SET ref_count = refcount - :ref, direct = 0
2469 WHERE list_id = :lid AND member_id = :mid
2470 AND member_type = :mtype;
2472 EXEC SQL UPDATE imembers
2473 SET ref_count = refcount - :ref
2474 WHERE list_id = :lid AND member_id = :mid
2475 AND member_type = :mtype;
2479 lid = *(int *)argv[0];
2480 entity = cl->entity;
2481 who = cl->client_id;
2482 EXEC SQL UPDATE list SET modtime = 'now', modby = :who, modwith = :entity
2483 WHERE list_id = :lid;
2484 if (ingres_errno) return(mr_errcode);
2489 /* get_ace_use - given a type and a name, return a type and a name.
2490 * The ace_type is one of "LIST", "USER", "RLIST", or "RUSER" in argv[0],
2491 * and argv[1] will contain the ID of the entity in question. The R*
2492 * types mean to recursively look at every containing list, not just
2493 * when the object in question is a direct member. On return, the
2494 * usage type will be one of LIST, SERVICE, FILESYS, QUOTA, QUERY, or ZEPHYR.
2497 int get_ace_use(q, argv, cl, action, actarg)
2505 EXEC SQL BEGIN DECLARE SECTION;
2507 int aid, listid, id;
2508 EXEC SQL END DECLARE SECTION;
2509 struct save_queue *sq, *sq_create();
2512 aid = *(int *)argv[1];
2513 if (!strcmp(atype, "LIST") || !strcmp(atype, "USER") ||
2514 !strcmp(atype, "KERBEROS")) {
2515 return(get_ace_internal(atype, aid, action, actarg));
2519 if (!strcmp(atype, "RLIST")) {
2520 sq_save_data(sq, aid);
2521 /* get all the list_id's of containing lists */
2522 EXEC SQL DECLARE csr107 CURSOR FOR
2523 SELECT list_id FROM imembers
2524 WHERE member_type='LIST' AND member_id = :aid;
2525 EXEC SQL OPEN csr107;
2527 EXEC SQL FETCH csr107 INTO :listid;
2528 if(sqlca.sqlcode != 0) break;
2529 sq_save_unique_data(sq, listid);
2531 EXEC SQL CLOSE csr107;
2532 /* now process each one */
2533 while (sq_get_data(sq, &id)) {
2534 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2539 if (!strcmp(atype, "RUSER")) {
2540 EXEC SQL DECLARE csr108 CURSOR FOR
2541 SELECT list_id FROM imembers
2542 WHERE member_type='USER' AND member_id = :aid;
2543 EXEC SQL OPEN csr108;
2545 EXEC SQL FETCH csr108 INTO :listid;
2546 if(sqlca.sqlcode != 0) break;
2547 sq_save_data(sq, listid);
2549 EXEC SQL CLOSE csr108;
2550 /* now process each one */
2551 while (sq_get_data(sq, &id)) {
2552 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2555 if (get_ace_internal("USER", aid, action, actarg) == MR_SUCCESS)
2559 if (!strcmp(atype, "RKERBERO")) {
2560 EXEC SQL DECLARE csr109 CURSOR FOR
2561 SELECT list_id FROM imembers
2562 WHERE member_type='KERBEROS' AND member_id = :aid;
2563 EXEC SQL OPEN csr109;
2565 EXEC SQL FETCH csr109 INTO :listid;
2566 if(sqlca.sqlcode != 0) break;
2567 sq_save_data(sq, listid);
2569 EXEC SQL CLOSE csr109;
2570 /* now process each one */
2571 while (sq_get_data(sq, &id)) {
2572 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2575 if (get_ace_internal("KERBEROS", aid, action, actarg) == MR_SUCCESS)
2580 if (ingres_errno) return(mr_errcode);
2581 if (!found) return(MR_NO_MATCH);
2586 /* This looks up a single list or user for ace use. atype must be "USER"
2587 * or "LIST", and aid is the ID of the corresponding object. This is used
2588 * by get_ace_use above.
2591 get_ace_internal(atype, aid, action, actarg)
2592 EXEC SQL BEGIN DECLARE SECTION;
2595 EXEC SQL END DECLARE SECTION;
2601 EXEC SQL BEGIN DECLARE SECTION;
2603 EXEC SQL END DECLARE SECTION;
2606 if (!strcmp(atype, "LIST")) {
2607 rargv[0] = "FILESYS";
2608 EXEC SQL DECLARE csr110 CURSOR FOR
2609 SELECT label FROM filesys
2610 WHERE owners = :aid;
2611 EXEC SQL OPEN csr110;
2613 EXEC SQL FETCH csr110 INTO :name;
2614 if(sqlca.sqlcode != 0) break;
2615 (*action)(2, rargv, actarg);
2618 EXEC SQL CLOSE csr110;
2621 EXEC SQL DECLARE csr111 CURSOR FOR
2622 SELECT capability FROM capacls
2623 WHERE list_id = :aid ;
2624 EXEC SQL OPEN csr111;
2626 EXEC SQL FETCH csr111 INTO :name ;
2627 if(sqlca.sqlcode != 0) break;
2628 (*action)(2, rargv, actarg);
2631 EXEC SQL CLOSE csr111;
2632 } else if (!strcmp(atype, "USER")) {
2633 rargv[0] = "FILESYS";
2634 EXEC SQL DECLARE csr112 CURSOR FOR
2635 SELECT label FROM filesys
2637 EXEC SQL OPEN csr112;
2639 EXEC SQL FETCH csr112 INTO :name ;
2640 if(sqlca.sqlcode != 0) break;
2641 (*action)(2, rargv, actarg);
2644 EXEC SQL CLOSE csr112;
2648 EXEC SQL DECLARE csr113 CURSOR FOR
2649 SELECT name FROM list
2650 WHERE acl_type = :atype AND acl_id = :aid;
2651 EXEC SQL OPEN csr113;
2653 EXEC SQL FETCH csr113 INTO :name;
2654 if(sqlca.sqlcode != 0) break;
2655 (*action)(2, rargv, actarg);
2658 EXEC SQL CLOSE csr113;
2660 rargv[0] = "SERVICE";
2661 EXEC SQL DECLARE csr114 CURSOR FOR
2662 SELECT name FROM servers
2663 WHERE acl_type = :atype AND acl_id = :aid;
2664 EXEC SQL OPEN csr114;
2666 EXEC SQL FETCH csr114 INTO :name;
2667 if(sqlca.sqlcode != 0) break;
2668 (*action)(2, rargv, actarg);
2671 EXEC SQL CLOSE csr114;
2673 rargv[0] = "HOSTACCESS";
2674 EXEC SQL DECLARE csr115 CURSOR FOR
2675 SELECT name FROM machine, hostaccess
2676 WHERE mach_id = hostaccess.mach_id AND hostaccess.acl_type = :atype
2677 AND hostaccess.acl_id = :aid;
2678 EXEC SQL OPEN csr115;
2680 EXEC SQL FETCH csr115 INTO :name;
2681 if(sqlca.sqlcode != 0) break;
2682 (*action)(2, rargv, actarg);
2685 EXEC SQL CLOSE csr115;
2687 rargv[0] = "ZEPHYR";
2688 EXEC SQL DECLARE csr116 CURSOR FOR
2689 SELECT class FROM zephyr
2690 WHERE zephyr.xmt_type = :atype AND zephyr.xmt_id = :aid
2691 OR zephyr.sub_type = :atype AND zephyr.sub_id = :aid
2692 OR zephyr.iws_type = :atype AND zephyr.iws_id = :aid
2693 OR zephyr.iui_type = :atype AND zephyr.iui_id = :aid;
2694 EXEC SQL OPEN csr116;
2696 EXEC SQL FETCH csr116 INTO :name;
2697 if(sqlca.sqlcode != 0) break;
2698 (*action)(2, rargv, actarg);
2701 EXEC SQL CLOSE csr116;
2703 if (!found) return(MR_NO_MATCH);
2708 /* get_lists_of_member - given a type and a name, return the name and flags
2709 * of all of the lists of the given member. The member_type is one of
2710 * "LIST", "USER", "STRING", "RLIST", "RUSER", or "RSTRING" in argv[0],
2711 * and argv[1] will contain the ID of the entity in question. The R*
2712 * types mean to recursively look at every containing list, not just
2713 * when the object in question is a direct member.
2716 int get_lists_of_member(q, argv, cl, action, actarg)
2723 int found = 0, direct = 1;
2725 EXEC SQL BEGIN DECLARE SECTION;
2727 int aid, listid, id;
2728 char name[33], active[5], public[5], hidden[5], maillist[5], grouplist[5];
2729 EXEC SQL END DECLARE SECTION;
2732 aid = *(int *)argv[1];
2733 if (!strcmp(atype, "RLIST")) {
2737 if (!strcmp(atype, "RUSER")) {
2741 if (!strcmp(atype, "RSTRING")) {
2745 if (!strcmp(atype, "RKERBEROS")) {
2754 rargv[4] = maillist;
2755 rargv[5] = grouplist;
2757 EXEC SQL DECLARE csr117a CURSOR FOR
2758 SELECT name, CHAR(active), CHAR(publicflg), CHAR(hidden),
2759 CHAR(maillist), CHAR(grouplist)
2760 FROM list l, imembers m
2761 WHERE l.list_id = m.list_id AND m.direct = 1
2762 AND m.member_type = :atype AND m.member_id = :aid;
2763 EXEC SQL OPEN csr117a;
2765 EXEC SQL FETCH csr117a
2766 INTO :name, :active, :public, :hidden, :maillist, :grouplist;
2767 if(sqlca.sqlcode != 0) break;
2768 (*action)(6, rargv, actarg);
2771 EXEC SQL CLOSE csr117a;
2773 EXEC SQL DECLARE csr117b CURSOR FOR
2774 SELECT name, CHAR(active), CHAR(publicflg), CHAR(hidden),
2775 CHAR(maillist), CHAR(grouplist)
2776 FROM list l, imembers m
2777 WHERE l.list_id = m.list_id
2778 AND m.member_type = :atype AND m.member_id = :aid;
2779 EXEC SQL OPEN csr117b;
2781 EXEC SQL FETCH csr117b
2782 INTO :name, :active, :public, :hidden, :maillist, :grouplist;
2783 if(sqlca.sqlcode != 0) break;
2784 (*action)(6, rargv, actarg);
2787 EXEC SQL CLOSE csr117b;
2790 if (ingres_errno) return(mr_errcode);
2791 if (!found) return(MR_NO_MATCH);
2796 /* qualified_get_lists: passed "TRUE", "FALSE", or "DONTCARE" for each of
2797 * the five flags associated with each list. It will return the name of
2798 * each list that meets the quailifications. It does this by building a
2799 * where clause based on the arguments, then doing a retrieve.
2802 static char *lflags[5] = { "active", "publicflg", "hidden", "maillist", "group" };
2804 int qualified_get_lists(q, argv, cl, action, actarg)
2811 return(qualified_get(q, argv, action, actarg, "l.list_id != 0",
2812 "l", "name", lflags));
2816 /* get_members_of_list - this gets only direct members */
2818 get_members_of_list(q, argv, cl, action, actarg)
2825 return(gmol_internal(q, argv, cl, action, actarg, 1));
2828 /* get_end_members_of_list - this gets direct or indirect members */
2830 get_end_members_of_list(q, argv, cl, action, actarg)
2837 return(gmol_internal(q, argv, cl, action, actarg, 0));
2840 /** gmol_internal - optimized query for retrieval of list members
2841 ** used by both get_members_of_list and get_end_members_of_list
2844 ** argv[0] - list_id
2847 ** - retrieve USER members, then LIST members, then STRING members
2850 gmol_internal(q, argv, cl, action, actarg, flag)
2858 EXEC SQL BEGIN DECLARE SECTION;
2859 int list_id, member_id, direct;
2860 char member_name[129], member_type[9];
2861 EXEC SQL END DECLARE SECTION;
2864 struct save_queue *sq;
2866 /* true/false flag indicates whether to display only direct members. */
2872 list_id = *(int *)argv[0];
2876 EXEC SQL DECLARE csr118 CURSOR FOR
2877 SELECT member_type, member_id FROM imembers
2878 WHERE list_id = :list_id AND direct > :direct;
2879 EXEC SQL OPEN csr118;
2881 EXEC SQL FETCH csr118 INTO :member_type, :member_id;
2882 if (sqlca.sqlcode != 0) break;
2885 sq_save_data(sq, ((int)member_type[0] << 24) | (member_id & 0xffffff));
2887 EXEC SQL CLOSE csr118;
2889 if (members <= 49) {
2890 targv[1] = malloc(0);
2891 while (sq_remove_data(sq, &member_id)) {
2892 switch (member_id >> 24) {
2895 id_to_name(member_id & 0xffffff, "USER", &targv[1]);
2896 (*action)(2, targv, actarg);
2900 id_to_name(member_id & 0xffffff, "LIST", &targv[1]);
2901 (*action)(2, targv, actarg);
2904 targv[0] = "STRING";
2905 id_to_name(member_id & 0xffffff, "STRING", &targv[1]);
2906 (*action)(2, targv, actarg);
2909 targv[0] = "KERBEROS";
2910 id_to_name(member_id & 0xffffff, "STRING", &targv[1]);
2911 (*action)(2, targv, actarg);
2915 return(MR_INTERNAL);
2924 targv[1] = member_name;
2926 EXEC SQL DECLARE csr119 CURSOR FOR
2927 SELECT users.login FROM users, imembers
2928 WHERE imembers.list_id = :list_id AND imembers.member_type = 'USER'
2929 AND imembers.member_id = users.users_id AND imembers.direct > :direct
2931 EXEC SQL OPEN csr119;
2933 EXEC SQL FETCH csr119 INTO :member_name;
2934 if(sqlca.sqlcode != 0) break;
2935 (*action)(2, targv, actarg);
2937 EXEC SQL CLOSE csr119;
2938 if (ingres_errno) return(mr_errcode);
2941 EXEC SQL DECLARE csr120 CURSOR FOR
2942 SELECT list.name FROM list, imembers
2943 WHERE imembers.list_id = :list_id AND imembers.member_type='LIST'
2944 AND imembers.member_id = list.list_id AND imembers.direct > :direct
2946 EXEC SQL OPEN csr120;
2948 EXEC SQL FETCH csr120 INTO :member_name;
2949 if(sqlca.sqlcode != 0) break;
2950 (*action)(2, targv, actarg);
2952 EXEC SQL CLOSE csr120;
2953 if (ingres_errno) return(mr_errcode);
2955 targv[0] = "STRING";
2956 EXEC SQL DECLARE csr121 CURSOR FOR
2957 SELECT strings.string FROM strings, imembers
2958 WHERE imembers.list_id = :list_id AND imembers.member_type='STRING'
2959 AND imembers.member_id = strings.string_id
2960 AND imembers.direct > :direct
2962 EXEC SQL OPEN csr121;
2964 EXEC SQL FETCH csr121 INTO :member_name;
2965 if(sqlca.sqlcode != 0) break;
2966 (*action)(2, targv, actarg);
2968 EXEC SQL CLOSE csr121;
2969 if (ingres_errno) return(mr_errcode);
2971 targv[0] = "KERBEROS";
2972 EXEC SQL DECLARE csr122 CURSOR FOR
2973 SELECT strings.string FROM strings, imembers
2974 WHERE imembers.list_id = :list_id AND imembers.member_type='KERBEROS'
2975 AND imembers.member_id = strings.string_id
2976 AND imembers.direct > :direct
2978 EXEC SQL OPEN csr122;
2980 EXEC SQL FETCH csr122 INTO :member_name;
2981 if(sqlca.sqlcode != 0) break;
2982 (*action)(2, targv, actarg);
2984 EXEC SQL CLOSE csr122;
2985 if (ingres_errno) return(mr_errcode);
2991 /* count_members_of_list: this is a simple query, but it cannot be done
2992 * through the dispatch table.
2995 int count_members_of_list(q, argv, cl, action, actarg)
3002 EXEC SQL BEGIN DECLARE SECTION;
3004 EXEC SQL END DECLARE SECTION;
3005 char *rargv[1], countbuf[5];
3007 list = *(int *)argv[0];
3008 rargv[0] = countbuf;
3009 EXEC SQL REPEATED SELECT count (*) INTO :ct FROM imembers
3010 WHERE list_id = :list AND direct=1;
3011 if (ingres_errno) return(mr_errcode);
3012 sprintf(countbuf, "%d", ct);
3013 (*action)(1, rargv, actarg);
3018 /* qualified_get_server: passed "TRUE", "FALSE", or "DONTCARE" for each of
3019 * the three flags associated with each service. It will return the name of
3020 * each service that meets the quailifications. It does this by building a
3021 * where clause based on the arguments, then doing a retrieve.
3024 static char *sflags[3] = { "enable", "inprogress", "harderror" };
3026 int qualified_get_server(q, argv, cl, action, actarg)
3033 return(qualified_get(q, argv, action, actarg, "s.name != ''",
3034 "s", "name", sflags));
3038 /* generic qualified get routine, used by qualified_get_lists,
3039 * qualified_get_server, and qualified_get_serverhost.
3041 * start - a simple where clause, must not be empty
3042 * range - the name of the range variable
3043 * field - the field to return
3044 * flags - an array of strings, names of the flag variables
3047 int qualified_get(q, argv, action, actarg, start, range, field, flags)
3057 char name[33], qual[256];
3059 char *rargv[1], buf[32];
3061 strcpy(qual, start);
3062 for (i = 0; i < q->argc; i++) {
3063 if (!strcmp(argv[i], "TRUE")) {
3064 sprintf(buf, " and %s.%s != 0", range, flags[i]);
3065 (void) strcat(qual, buf);
3066 } else if (!strcmp(argv[i], "FALSE")) {
3067 sprintf(buf, " and %s.%s = 0", range, flags[i]);
3068 (void) strcat(qual, buf);
3072 rargv[0] = SQLDA->sqlvar[0].sqldata;
3073 sprintf(stmt_buf,"SELECT %s.%s FROM %s %s WHERE %s",q->rtable,field,q->rtable,q->rvar,qual);
3074 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3076 return(MR_INTERNAL);
3077 EXEC SQL DECLARE csr123 CURSOR FOR stmt;
3078 EXEC SQL OPEN csr123;
3080 EXEC SQL FETCH csr123 USING DESCRIPTOR :SQLDA;
3081 if(sqlca.sqlcode != 0) break;
3083 (*action)(1, rargv, actarg);
3085 EXEC SQL CLOSE csr123;
3086 if (ingres_errno) return(mr_errcode);
3088 return(MR_NO_MATCH);
3093 /* qualified_get_serverhost: passed "TRUE", "FALSE", or "DONTCARE" for each of
3094 * the five flags associated with each serverhost. It will return the name of
3095 * each service and host that meets the quailifications. It does this by
3096 * building a where clause based on the arguments, then doing a retrieve.
3099 static char *shflags[6] = { "service", "enable", "override", "success",
3100 "inprogress", "hosterror" };
3102 int qualified_get_serverhost(q, argv, cl, action, actarg)
3109 EXEC SQL BEGIN DECLARE SECTION;
3110 char sname[33], mname[33], qual[256];
3111 EXEC SQL END DECLARE SECTION;
3112 char *rargv[2], buf[32];
3115 /** the uppercase() function is INGRES-specific */
3116 sprintf(qual, "machine.mach_id = serverhosts.mach_id AND \
3117 serverhosts.service = uppercase('%s')",
3119 for (i = 1; i < q->argc; i++) {
3120 if (!strcmp(argv[i], "TRUE")) {
3121 sprintf(buf, " AND serverhosts.%s != 0", shflags[i]);
3123 } else if (!strcmp(argv[i], "FALSE")) {
3124 sprintf(buf, " AND serverhosts.%s = 0", shflags[i]);
3131 EXEC SQL DECLARE csr124 CURSOR FOR
3132 SELECT serverhosts.service, machine.name FROM serverhosts, machine
3134 EXEC SQL OPEN csr124;
3136 EXEC SQL FETCH csr124 INTO :sname, :mname;
3137 if(sqlca.sqlcode != 0) break;
3139 (*action)(2, rargv, actarg);
3141 EXEC SQL CLOSE csr124;
3143 if (ingres_errno) return(mr_errcode);
3145 return(MR_NO_MATCH);
3150 /* register_user - change user's login name and allocate a pobox, group,
3151 * filesystem, and quota for them. The user's status must start out as 0,
3152 * and is left as 2. Arguments are: user's UID, new login name, and user's
3153 * type for filesystem allocation (MR_FS_STUDENT, MR_FS_FACULTY,
3154 * MR_FS_STAFF, MR_FS_MISC).
3157 register_user(q, argv, cl)
3162 EXEC SQL BEGIN DECLARE SECTION;
3163 char *login, dir[65], *entity, directory[129], machname[33];
3164 int who, rowcount, mid, uid, users_id, flag, utype, nid, list_id, quota;
3165 int size, alloc, pid, ostatus, nstatus, gidval, fsidval, npidval;
3166 static int m_id = 0, def_quota = 0;
3167 EXEC SQL END DECLARE SECTION;
3168 char buffer[256], *aargv[3];
3170 entity = cl->entity;
3171 who = cl->client_id;
3173 uid = atoi(argv[0]);
3175 utype = atoi(argv[2]);
3178 EXEC SQL REPEATED SELECT users_id, status INTO :users_id, :ostatus
3180 WHERE uid = :uid AND (status=0 OR status=5 OR status=6);
3182 if (sqlca.sqlerrd[2] == 0)
3183 return(MR_NO_MATCH);
3184 if (sqlca.sqlerrd[2] > 1)
3185 return(MR_NOT_UNIQUE);
3187 /* check new login name */
3188 EXEC SQL REPEATED SELECT login INTO :cdummy FROM users
3189 WHERE login = LEFT(:login,SIZE(login)) AND users_id != :users_id;
3190 if (ingres_errno) return(mr_errcode);
3191 if (sqlca.sqlerrd[2] > 0) return(MR_IN_USE);
3192 EXEC SQL REPEATED SELECT name INTO :cdummy FROM list
3193 WHERE name = LEFT(:login,SIZE(name));
3194 if (ingres_errno) return(mr_errcode);
3195 if (sqlca.sqlerrd[2] > 0) return(MR_IN_USE);
3196 EXEC SQL REPEATED SELECT label INTO :cdummy FROM filesys
3197 WHERE label = LEFT(:login,SIZE(label));
3198 if (ingres_errno) return(mr_errcode);
3199 if (sqlca.sqlerrd[2] > 0) return(MR_IN_USE);
3200 com_err(whoami, 0, "login name OK");
3202 /* choose place for pobox, put in mid */
3203 EXEC SQL DECLARE csr130 CURSOR FOR
3204 SELECT sh.mach_id, m.name FROM serverhosts sh, machine m
3205 WHERE sh.service='POP' AND sh.mach_id=m.mach_id
3206 AND sh.value2 - sh.value1 =
3207 (SELECT MAX(value2 - value1) FROM serverhosts
3208 WHERE service = 'POP');
3209 EXEC SQL OPEN csr130;
3210 EXEC SQL FETCH csr130 INTO :mid, :machname;
3211 if (sqlca.sqlerrd[2] == 0) {
3212 EXEC SQL CLOSE csr130;
3213 if (ingres_errno) return(mr_errcode);
3214 return(MR_NO_POBOX);
3216 EXEC SQL CLOSE csr130;
3217 if (ingres_errno) return(mr_errcode);
3220 /* change login name, set pobox */
3221 sprintf(buffer, "users.users_id = %d", users_id);
3222 incremental_before("users", buffer, 0);
3224 if (ostatus == 5 || ostatus == 6)
3226 EXEC SQL REPEATED UPDATE users SET login = :login, status = :nstatus,
3227 modtime='now', modby = :who, modwith = :entity, potype='POP',
3228 pop_id = :mid, pmodtime='now', pmodby = :who, pmodwith = :entity
3229 WHERE users_id = :users_id;
3231 if (ingres_errno) return(mr_errcode);
3232 if (sqlca.sqlerrd[2] != 1)
3233 return(MR_INTERNAL);
3234 set_pop_usage(mid, 1);
3235 com_err(whoami, 0, "set login name to %s and pobox to %s", login,
3237 incremental_after("users", buffer, 0);
3239 /* create group list */
3240 if (set_next_object_id("gid", "list", 1))
3242 if (set_next_object_id("list_id", "list", 0))
3244 EXEC SQL REPEATED SELECT value INTO :list_id FROM numvalues
3245 WHERE name='list_id';
3246 if (ingres_errno) return(mr_errcode);
3247 if (sqlca.sqlerrd[2] != 1)
3248 return(MR_INTERNAL);
3249 incremental_clear_before();
3250 EXEC SQL SELECT value INTO :gidval FROM numvalues WHERE name = 'gid';
3251 EXEC SQL REPEATED INSERT INTO list
3252 (name, list_id, active, publicflg, hidden, maillist, grouplist,
3253 gid, description, acl_type, acl_id,
3254 modtime, modby, modwith)
3255 VALUES (:login, :list_id, 1, 0, 0, 0, 1,
3256 :gidval, 'User Group', 'USER', :users_id,
3257 'now', :who, :entity);
3258 if (ingres_errno) return(mr_errcode);
3259 if (sqlca.sqlerrd[2] != 1)
3260 return(MR_INTERNAL);
3261 sprintf(buffer, "list_id = %d", list_id);
3262 incremental_after("list", buffer, 0);
3263 aargv[0] = (char *) list_id;
3265 aargv[2] = (char *) users_id;
3266 incremental_clear_before();
3267 EXEC SQL REPEATED INSERT INTO imembers
3268 (list_id, member_type, member_id, ref_count, direct)
3269 VALUES (:list_id, 'USER', :users_id, 1, 1);
3270 if (ingres_errno) return(mr_errcode);
3271 if (sqlca.sqlerrd[2] != 1)
3272 return(MR_INTERNAL);
3273 incremental_after("members", 0, aargv);
3276 /* Cell Name (I know, it shouldn't be hard coded...) */
3277 strcpy(machname, "ATHENA.MIT.EDU");
3278 EXEC SQL SELECT mach_id INTO :m_id FROM machine
3279 WHERE name = :machname;
3282 /* create filesystem */
3283 if (set_next_object_id("filsys_id", "filesys", 0))
3285 incremental_clear_before();
3286 if (islower(login[0]) && islower(login[1])) {
3287 sprintf(directory, "/afs/athena.mit.edu/user/%c/%c/%s",
3288 login[0], login[1], login);
3290 sprintf(directory, "/afs/athena.mit.edu/user/other/%s", login);
3293 EXEC SQL SELECT value INTO :fsidval FROM numvalues
3294 WHERE numvalues.name='filsys_id';
3295 EXEC SQL REPEATED INSERT INTO filesys
3296 (filsys_id, phys_id, label, type, mach_id, name,
3297 mount, access, comments, owner, owners, createflg,
3298 lockertype, modtime, modby, modwith)
3300 (:fsidval, 0, :login, 'AFS', :m_id, :directory,
3301 '/mit/'+:login, 'w', 'User Locker', :users_id, :list_id, 1,
3302 'HOMEDIR', 'now', :who, :entity);
3304 if (ingres_errno) return(mr_errcode);
3305 if (sqlca.sqlerrd[2] != 1)
3306 return(MR_INTERNAL);
3307 sprintf(buffer,"fs.filsys_id = %d",fsidval);
3308 incremental_after("filesys", buffer, 0);
3311 if (def_quota == 0) {
3312 EXEC SQL REPEATED SELECT value INTO :quota FROM numvalues
3313 WHERE name='def_quota';
3314 if (ingres_errno) return(mr_errcode);
3315 if (sqlca.sqlerrd[2] != 1)
3316 return(MR_NO_QUOTA);
3318 incremental_clear_before();
3319 EXEC SQL REPEATED INSERT INTO quota
3320 (entity_id, filsys_id, type, quota, phys_id, modtime, modby, modwith)
3322 (0, :fsidval, 'ANY', :def_quota, 0, 'now', :who, :entity);
3323 if (ingres_errno) return(mr_errcode);
3324 if (sqlca.sqlerrd[2] != 1)
3325 return(MR_INTERNAL);
3329 sprintf(buffer, "q.entity_id = 0 and q.filsys_id = %d and q.type = 'ANY'", fsidval);
3330 incremental_after("quota", buffer, aargv);
3331 com_err(whoami, 0, "quota of %d assigned", def_quota);
3332 if (ingres_errno) return(mr_errcode);
3334 cache_entry(login, "USER", users_id);
3336 EXEC SQL REPEATED UPDATE tblstats SET updates=updates+1, modtime='now'
3337 WHERE table_name='users';
3338 EXEC SQL REPEATED UPDATE tblstats SET appends=appends+1, modtime='now'
3339 WHERE table_name='list' OR table_name='filesys' OR table_name='quota';
3340 if (ingres_errno) return(mr_errcode);
3346 /** set_pop_usage - incr/decr usage count for pop server in serverhosts talbe
3350 ** delta (will be +/- 1)
3353 ** - incr/decr value field in serverhosts table for pop/mach_id
3357 static int set_pop_usage(id, cnt)
3358 EXEC SQL BEGIN DECLARE SECTION;
3361 EXEC SQL END DECLARE SECTION;
3363 EXEC SQL REPEATED UPDATE serverhosts SET value1 = value1 + :cnt
3364 WHERE serverhosts.service = 'POP' AND serverhosts.mach_id = :id;
3366 if (ingres_errno) return(mr_errcode);
3372 /* Validation Routines */
3374 validate_row(q, argv, v)
3375 register struct query *q;
3377 register struct validate *v;
3379 EXEC SQL BEGIN DECLARE SECTION;
3383 EXEC SQL END DECLARE SECTION;
3385 /* build where clause */
3386 build_qual(v->qual, v->argc, argv, qual);
3388 if (log_flags & LOG_VALID)
3389 /* tell the logfile what we're doing */
3390 com_err(whoami, 0, "validating row: %s", qual);
3392 /* look for the record */
3393 sprintf(stmt_buf,"SELECT COUNT (*) FROM %s WHERE %s",q->rtable,qual);
3394 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3396 return(MR_INTERNAL);
3397 EXEC SQL DECLARE csr126 CURSOR FOR stmt;
3398 EXEC SQL OPEN csr126;
3399 EXEC SQL FETCH csr126 USING DESCRIPTOR :SQLDA;
3400 EXEC SQL CLOSE csr126;
3401 rowcount = *(int *)SQLDA->sqlvar[0].sqldata;
3403 if (ingres_errno) return(mr_errcode);
3404 if (rowcount == 0) return(MR_NO_MATCH);
3405 if (rowcount > 1) return(MR_NOT_UNIQUE);
3409 validate_fields(q, argv, vo, n)
3411 register char *argv[];
3412 register struct valobj *vo;
3415 register int status;
3420 if (log_flags & LOG_VALID)
3421 com_err(whoami, 0, "validating %s in %s: %s",
3422 vo->namefield, vo->table, argv[vo->index]);
3423 status = validate_name(argv, vo);
3427 if (log_flags & LOG_VALID)
3428 com_err(whoami, 0, "validating %s in %s: %s",
3429 vo->idfield, vo->table, argv[vo->index]);
3430 status = validate_id(q, argv, vo);
3434 if (log_flags & LOG_VALID)
3435 com_err(whoami, 0, "validating date: %s", argv[vo->index]);
3436 status = validate_date(argv, vo);
3440 if (log_flags & LOG_VALID)
3441 com_err(whoami, 0, "validating %s type: %s",
3442 vo->table, argv[vo->index]);
3443 status = validate_type(argv, vo);
3447 if (log_flags & LOG_VALID)
3448 com_err(whoami, 0, "validating typed data (%s): %s",
3449 argv[vo->index - 1], argv[vo->index]);
3450 status = validate_typedata(q, argv, vo);
3454 if (log_flags & LOG_VALID)
3455 com_err(whoami, 0, "validating rename %s in %s",
3456 argv[vo->index], vo->table);
3457 status = validate_rename(argv, vo);
3461 if (log_flags & LOG_VALID)
3462 com_err(whoami, 0, "validating chars: %s", argv[vo->index]);
3463 status = validate_chars(argv[vo->index]);
3471 status = lock_table(vo);
3475 status = convert_wildcards(argv[vo->index]);
3479 status = convert_wildcards_uppercase(argv[vo->index]);
3484 if (status != MR_EXISTS) return(status);
3488 if (ingres_errno) return(mr_errcode);
3493 /* validate_chars: verify that there are no illegal characters in
3494 * the string. Legal characters are printing chars other than
3495 * ", *, ?, \, [ and ].
3497 static int illegalchars[] = {
3498 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
3499 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
3500 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
3501 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
3502 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* : - O */
3503 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* P - _ */
3504 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
3505 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
3506 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3507 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3508 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3509 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3510 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3511 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3512 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3513 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3520 if (illegalchars[*s++])
3521 return(MR_BAD_CHAR);
3526 validate_id(q, argv, vo)
3529 register struct valobj *vo;
3531 EXEC SQL BEGIN DECLARE SECTION;
3532 char *name, *tbl, *namefield, *idfield;
3534 EXEC SQL END DECLARE SECTION;
3538 name = argv[vo->index];
3540 namefield = vo->namefield;
3541 idfield = vo->idfield;
3543 if ((!strcmp(tbl, "users") && !strcmp(namefield, "login")) ||
3544 !strcmp(tbl, "machine") ||
3545 !strcmp(tbl, "filesys") ||
3546 !strcmp(tbl, "list") ||
3547 !strcmp(tbl, "cluster") ||
3548 !strcmp(tbl, "strings")) {
3549 if (!strcmp(tbl, "machine"))
3550 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3551 status = name_to_id(name, tbl, &id);
3553 *(int *)argv[vo->index] = id;
3555 } else if (status == MR_NO_MATCH && !strcmp(tbl, "strings") &&
3556 (q->type == APPEND || q->type == UPDATE)) {
3557 EXEC SQL SELECT value INTO :id FROM numvalues
3558 WHERE name = 'strings_id';
3560 EXEC SQL UPDATE numvalues SET value = :id WHERE name = 'string_id';
3561 EXEC SQL INSERT INTO strings (string_id, string) VALUES (:id, :name);
3562 cache_entry(name, "STRING", id);
3563 *(int *)argv[vo->index] = id;
3565 } else if (status == MR_NO_MATCH || status == MR_NOT_UNIQUE)
3571 if (!strcmp(namefield, "uid")) {
3572 sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s = %s",idfield,tbl,namefield,name);
3574 sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s = '%s'",idfield,tbl,namefield,name);
3576 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3578 return(MR_INTERNAL);
3579 EXEC SQL DECLARE csr127 CURSOR FOR stmt;
3580 EXEC SQL OPEN csr127;
3582 EXEC SQL FETCH csr127 USING DESCRIPTOR :SQLDA;
3583 if(sqlca.sqlcode == 0) {
3585 EXEC SQL FETCH csr127 USING DESCRIPTOR :SQLDA;
3586 if(sqlca.sqlcode == 0) rowcount++;
3588 EXEC SQL CLOSE csr127;
3592 if (rowcount != 1) return(vo->error);
3593 bcopy(SQLDA->sqlvar[0].sqldata,argv[vo->index],sizeof(int));
3597 validate_name(argv, vo)
3599 register struct valobj *vo;
3601 EXEC SQL BEGIN DECLARE SECTION;
3602 char *name, *tbl, *namefield;
3604 EXEC SQL END DECLARE SECTION;
3607 name = argv[vo->index];
3609 namefield = vo->namefield;
3610 if (!strcmp(tbl, "servers") && !strcmp(namefield, "name")) {
3611 for (c = name; *c; c++)
3615 sprintf(stmt_buf,"SELECT DISTINCT COUNT(*) FROM %s WHERE %s.%s = '%s'",
3616 tbl,tbl,namefield,name);
3617 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3619 return(MR_INTERNAL);
3620 EXEC SQL DECLARE csr128 CURSOR FOR stmt;
3621 EXEC SQL OPEN csr128;
3622 EXEC SQL FETCH csr128 USING DESCRIPTOR :SQLDA;
3623 rowcount = *(int *)SQLDA->sqlvar[0].sqldata;
3624 EXEC SQL CLOSE csr128;
3626 if (ingres_errno) return(mr_errcode);
3627 return ((rowcount == 1) ? MR_EXISTS : vo->error);
3630 validate_date(argv, vo)
3634 EXEC SQL BEGIN DECLARE SECTION;
3638 EXEC SQL END DECLARE SECTION;
3640 idate = argv[vo->index];
3641 EXEC SQL SELECT interval('years',date(:idate)-date('today')) INTO :dd;
3643 if (sqlca.sqlcode != 0 || dd > 5.0) return(MR_DATE);
3648 validate_rename(argv, vo)
3652 EXEC SQL BEGIN DECLARE SECTION;
3653 char *name, *tbl, *namefield, *idfield;
3655 EXEC SQL END DECLARE SECTION;
3659 c = name = argv[vo->index];
3661 if (illegalchars[*c++])
3662 return(MR_BAD_CHAR);
3664 /* minor kludge to upcasify machine names */
3665 if (!strcmp(tbl, "machine"))
3666 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3667 namefield = vo->namefield;
3668 idfield = vo->idfield;
3671 if (!strcmp(argv[vo->index], argv[vo->index - 1]))
3673 sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s = LEFT('%s',SIZE(%s))",
3674 namefield,tbl,namefield,name,namefield);
3675 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3677 return(MR_INTERNAL);
3678 EXEC SQL DECLARE csr129 CURSOR FOR stmt;
3679 EXEC SQL OPEN csr129;
3680 EXEC SQL FETCH csr129 USING DESCRIPTOR :SQLDA;
3681 if(sqlca.sqlcode == 0) id=1; else id=0;
3682 EXEC SQL CLOSE csr129;
3684 if (ingres_errno) return(mr_errcode);
3690 status = name_to_id(name, tbl, &id);
3691 if (status == MR_NO_MATCH || id == *(int *)argv[vo->index - 1])
3698 validate_type(argv, vo)
3700 register struct valobj *vo;
3702 EXEC SQL BEGIN DECLARE SECTION;
3705 EXEC SQL END DECLARE SECTION;
3708 typename = vo->table;
3709 c = val = argv[vo->index];
3711 if (illegalchars[*c++])
3712 return(MR_BAD_CHAR);
3715 /* uppercase type fields */
3716 for (c = val; *c; c++) if (islower(*c)) *c = toupper(*c);
3718 EXEC SQL SELECT trans INTO :cdummy FROM alias
3719 WHERE name = :typename AND type='TYPE' AND trans = :val;
3720 if (ingres_errno) return(mr_errcode);
3721 return (sqlca.sqlerrd[2] ? MR_EXISTS : vo->error);
3724 /* validate member or type-specific data field */
3726 validate_typedata(q, argv, vo)
3727 register struct query *q;
3728 register char *argv[];
3729 register struct valobj *vo;
3731 EXEC SQL BEGIN DECLARE SECTION;
3734 char data_type[129];
3736 EXEC SQL END DECLARE SECTION;
3741 /* get named object */
3742 name = argv[vo->index];
3744 /* get field type string (known to be at index-1) */
3745 field_type = argv[vo->index-1];
3747 /* get corresponding data type associated with field type name */
3748 EXEC SQL SELECT trans INTO :data_type FROM alias
3749 WHERE name = :field_type AND type='TYPEDATA';
3750 if (ingres_errno) return(mr_errcode);
3751 if (sqlca.sqlerrd[2] != 1) return(MR_TYPE);
3753 /* now retrieve the record id corresponding to the named object */
3754 if (index(data_type, ' '))
3755 *index(data_type, ' ') = 0;
3756 if (!strcmp(data_type, "user")) {
3758 status = name_to_id(name, data_type, &id);
3759 if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
3761 if (status) return(status);
3762 } else if (!strcmp(data_type, "list")) {
3764 status = name_to_id(name, data_type, &id);
3765 if (status && status == MR_NOT_UNIQUE)
3767 if (status == MR_NO_MATCH) {
3768 /* if idfield is non-zero, then if argv[0] matches the string
3769 * that we're trying to resolve, we should get the value of
3770 * numvalues.[idfield] for the id.
3772 if (vo->idfield && !strcmp(argv[0], argv[vo->index])) {
3773 set_next_object_id(q->validate->object_id, q->rtable, 0);
3775 EXEC SQL REPEATED SELECT value INTO :id FROM numvalues
3777 if (sqlca.sqlerrd[2] != 1) return(MR_LIST);
3780 } else if (status) return(status);
3781 } else if (!strcmp(data_type, "machine")) {
3783 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3784 status = name_to_id(name, data_type, &id);
3785 if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
3787 if (status) return(status);
3788 } else if (!strcmp(data_type, "string")) {
3790 status = name_to_id(name, data_type, &id);
3791 if (status && status == MR_NOT_UNIQUE)
3793 if (status == MR_NO_MATCH) {
3794 if (q->type != APPEND && q->type != UPDATE) return(MR_STRING);
3795 EXEC SQL SELECT value INTO :id FROM numvalues WHERE name = 'strings_id';
3797 EXEC SQL UPDATE numvalues SET value = :id WHERE name = 'strings_id';
3798 EXEC SQL INSERT INTO strings (string_id, string) VALUES (:id, :name);
3799 cache_entry(name, "STRING", id);
3800 } else if (status) return(status);
3801 } else if (!strcmp(data_type, "none")) {
3807 /* now set value in argv */
3808 *(int *)argv[vo->index] = id;
3814 /* Lock the table named by the validation object */
3819 sprintf(stmt_buf,"UPDATE %s SET modtime='now' WHERE %s.%s = 0",
3820 vo->table,vo->table,vo->idfield);
3821 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
3822 if (ingres_errno) return(mr_errcode);
3823 if (sqlca.sqlerrd[2] != 1)
3830 /* Check the database at startup time. For now this just resets the
3831 * inprogress flags that the DCM uses.
3834 sanity_check_database()
3839 /* Dynamic SQL support routines */
3840 MR_SQLDA_T *mr_alloc_SQLDA()
3843 short *null_indicators;
3846 if((it=(MR_SQLDA_T *)malloc(sizeof(MR_SQLDA_T)))==NULL) {
3847 com_err(whoami, MR_NO_MEM, "setting up SQLDA");
3851 if((null_indicators=(short *)calloc(QMAXARGS,sizeof(short)))==NULL) {
3852 com_err(whoami, MR_NO_MEM, "setting up SQLDA null indicators");
3856 for(j=0; j<QMAXARGS; j++) {
3857 if((it->sqlvar[j].sqldata=malloc(sizeof(short)+QMAXARGSIZE))==NULL) {
3858 com_err(whoami, MR_NO_MEM, "setting up SQLDA variables");
3861 it->sqlvar[j].sqllen=QMAXARGSIZE;
3862 it->sqlvar[j].sqlind=null_indicators+j;
3863 null_indicators[j]=0;
3870 /* Use this after FETCH USING DESCRIPTOR one or more
3871 * result columns may contain NULLs. This routine is
3872 * not currently needed, since db/schema creates all
3873 * columns with a NOT NULL WITH DEFAULT clause.
3875 * This is currently dead flesh, since no Moira columns
3876 * allow null values; all use default values.
3878 mr_fix_nulls_in_SQLDA(da)
3881 register IISQLVAR *var;
3885 for(j=0, var=da->sqlvar; j<da->sqld; j++, var++) {
3886 switch(var->sqltype) {
3887 case -IISQ_CHA_TYPE:
3891 case -IISQ_INT_TYPE:
3893 intp=(int *)var->sqldata;
3901 /* prefetch_value():
3902 * This routine fetches an appropriate value from the numvalues table.
3903 * It is a little hack to get around the fact that SQL doesn't let you
3904 * do something like INSERT INTO table (foo) VALUES (other_table.bar).
3906 * It is called from the query table as (*v->pre_rtn)(q,Argv,cl) or
3907 * from within a setup_...() routine with the appropriate arguments.
3909 * Correct functioning of this routine may depend on the assumption
3910 * that this query is an APPEND.
3913 prefetch_value(q,argv,cl)
3918 EXEC SQL BEGIN DECLARE SECTION;
3919 char *name = q->validate->object_id;
3921 EXEC SQL END DECLARE SECTION;
3922 int status, limit, argc;
3924 /* set next object id, limiting it if necessary */
3925 if(!strcmp(name, "uid") || !strcmp(name, "gid"))
3926 limit = 1; /* So far as I know, this isn't needed. Just CMA. */
3929 if((status = set_next_object_id(name, q->rtable, limit)) != MR_SUCCESS)
3932 /* fetch object id */
3933 EXEC SQL SELECT value INTO :value FROM numvalues WHERE name=:name;
3934 if(ingres_errno) return(mr_errcode);
3935 if(sqlca.sqlerrd[2] != 1) return(MR_INTERNAL);
3937 argc = q->argc + q->vcnt; /* end of Argv for APPENDs */
3938 sprintf(argv[argc],"%d",value); /** Could save this step by changing tlist from %s to %d **/
3943 /* prefetch_filesys():
3944 * Fetches the phys_id from filesys based on the filsys_id in argv[0].
3945 * Appends the filsys_id and the phys_id to the argv so they can be
3946 * referenced in an INSERT into a table other than filesys. Also
3947 * see comments at prefetch_value().
3949 * Assumes the existence of a row where filsys_id = argv[0], since a
3950 * filesys label has already been resolved to a filsys_id.
3952 prefetch_filesys(q,argv,cl)
3957 EXEC SQL BEGIN DECLARE SECTION;
3959 EXEC SQL END DECLARE SECTION;
3962 fid = *(int *)argv[0];
3963 EXEC SQL SELECT phys_id INTO :phid FROM filesys WHERE filsys_id = :fid;
3964 if(ingres_errno) return(mr_errcode);
3966 argc=q->argc+q->vcnt;
3967 sprintf(argv[argc++],"%d",fid);
3968 sprintf(argv[argc],"%d",phid);
3973 /* Convert normal Unix-style wildcards to SQL voodoo */
3974 convert_wildcards(arg)
3977 static char buffer[QMAXARGSIZE];
3978 register char *s, *d;
3980 for(d=buffer,s=arg;*s;s++) {
3982 case '*': *d++='%'; *d++='%'; break;
3983 case '?': *d++='_'; break;
3986 case ']': *d++='*'; *d++ = *s; break;
3987 case '%': *d++='*'; *d++='%'; *d++='%'; break;
3988 default: *d++ = *s; break;
3993 /* Copy back into argv */
3999 /* This version includes uppercase conversion, for things like gmac.
4000 * This is necessary because "LIKE" doesn't work with "uppercase()".
4001 * Including it in a wildcard routine saves making two passes over
4002 * the argument string.
4004 convert_wildcards_uppercase(arg)
4007 static char buffer[QMAXARGSIZE];
4008 register char *s, *d;
4010 for(d=buffer,s=arg;*s;s++) {
4012 case '*': *d++='%'; *d++='%'; break;
4013 case '?': *d++='_'; break;
4016 case ']': *d++='*'; *d++ = *s; break;
4017 case '%': *d++='*'; *d++='%'; *d++='%'; break;
4018 default: *d++=toupper(*s); break; /* This is the only diff. */
4023 /* Copy back into argv */
4030 /* Looks like it's time to build an abstraction barrier, Yogi */
4032 EXEC SQL BEGIN DECLARE SECTION;
4034 EXEC SQL END DECLARE SECTION;
4038 EXEC SQL PREPARE stmt FROM :stmt;
4039 EXEC SQL DESCRIBE stmt INTO :SQLDA;
4040 if(SQLDA->sqld==0) /* Not a SELECT */
4041 return(MR_INTERNAL);
4042 EXEC SQL DECLARE csr CURSOR FOR stmt;
4044 EXEC SQL FETCH csr USING DESCRIPTOR :SQLDA;
4045 if(sqlca.sqlcode==0)
4047 else if((sqlca.sqlcode<0) && mr_errcode)
4056 /* eof:qsupport.dc */