7 * Copyright (C) 1987 by the Massachusetts Institute of Technology
8 * For copying and distribution information, please see the file
14 static char *rcsid_qsupport_dc = "$Header$";
17 #include <mit-copyright.h>
19 #include "mr_server.h"
24 EXEC SQL INCLUDE sqlca;
25 EXEC SQL INCLUDE sqlda;
28 extern char *whoami, *strsave();
29 extern int ingres_errno, mr_errcode;
31 EXEC SQL BEGIN DECLARE SECTION;
33 extern char *cdummy, *stmt_buf;
34 EXEC SQL END DECLARE SECTION;
36 /* Specialized Access Routines */
38 /* access_user - verify that client name equals specified login name
40 * - since field validation routines are called first, a users_id is
41 * now in argv[0] instead of the login name.
44 EXEC SQL WHENEVER SQLERROR CALL ingerr;
46 access_user(q, argv, cl)
51 if (cl->users_id != *(int *)argv[0])
59 /* access_login - verify that client name equals specified login name
61 * argv[0...n] contain search info. q->
64 access_login(q, argv, cl)
69 EXEC SQL BEGIN DECLARE SECTION;
72 EXEC SQL END DECLARE SECTION;
74 build_qual(q->qual, q->argc, argv, qual);
75 EXEC SQL SELECT users_id INTO :id FROM users WHERE :qual;
77 if (sqlca.sqlerrd[2] != 1 || id != cl->users_id)
85 /* access_list - check access for most list operations
87 * Inputs: argv[0] - list_id
89 * argv[2] - member ID (only for queries "amtl" and "dmfl")
90 * argv[7] - group IID (only for query "ulis")
93 * - check that client is a member of the access control list
94 * - OR, if the query is add_member_to_list or delete_member_from_list
95 * and the list is public, allow access if client = member
98 access_list(q, argv, cl)
103 EXEC SQL BEGIN DECLARE SECTION;
104 int list_id, acl_id, flags, gid;
106 EXEC SQL END DECLARE SECTION;
108 int client_id, status;
110 list_id = *(int *)argv[0];
111 EXEC SQL SELECT acl_id, acl_type, gid, public
112 INTO :acl_id, :acl_type, :gid, :flags
114 WHERE list_id = :list_id;
116 if (sqlca.sqlerrd[2] != 1)
119 /* parse client structure */
120 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
123 /* if amtl or dmfl and list is public allow client to add or delete self */
124 if (((!strcmp("amtl", q->shortname) && flags) ||
125 (!strcmp("dmfl", q->shortname))) &&
126 (!strcmp("USER", argv[1]))) {
127 if (*(int *)argv[2] == client_id) return(MR_SUCCESS);
128 /* if update_list, don't allow them to change the GID */
129 } else if (!strcmp("ulis", q->shortname)) {
130 if ((!strcmp(argv[7], UNIQUE_GID) && (gid != -1)) ||
131 (strcmp(argv[7], UNIQUE_GID) && (gid != atoi(argv[7]))))
135 /* check for client in access control list */
136 status = find_member(acl_type, acl_id, client_type, client_id, 0);
137 if (!status) return(MR_PERM);
143 /* access_visible_list - allow access to list only if it is not hidden,
144 * or if the client is on the ACL
146 * Inputs: argv[0] - list_id
147 * cl - client identifier
150 access_visible_list(q, argv, cl)
155 EXEC SQL BEGIN DECLARE SECTION;
156 int list_id, acl_id, flags ;
158 EXEC SQL END DECLARE SECTION;
160 int client_id, status;
162 list_id = *(int *)argv[0];
163 EXEC SQL SELECT hidden, acl_id, acl_type
164 INTO :flags, :acl_id, :acl_type
166 WHERE list_id = :list_id;
167 if (sqlca.sqlerrd[2] != 1)
172 /* parse client structure */
173 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
176 /* check for client in access control list */
177 status = find_member(acl_type, acl_id, client_type, client_id, 0);
185 /* access_vis_list_by_name - allow access to list only if it is not hidden,
186 * or if the client is on the ACL
188 * Inputs: argv[0] - list name
189 * cl - client identifier
192 access_vis_list_by_name(q, argv, cl)
197 EXEC SQL BEGIN DECLARE SECTION;
198 int acl_id, flags, rowcount;
199 char acl_type[9], *listname;
200 EXEC SQL END DECLARE SECTION;
202 int client_id, status;
205 EXEC SQL SELECT hidden, acl_id, acl_type INTO :flags, :acl_id, :acl_type
206 FROM list WHERE name = :listname;
208 rowcount=sqlca.sqlerrd[2];
216 /* parse client structure */
217 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
220 /* check for client in access control list */
221 status = find_member(acl_type, acl_id, client_type, client_id, 0);
229 /* access_member - allow user to access member of type "USER" and name matches
230 * username, or to access member of type "LIST" and list is one that user is
231 * on the acl of, or the list is visible.
234 access_member(q, argv, cl)
239 if (!strcmp(argv[0], "LIST") || !strcmp(argv[0], "RLIST"))
240 return(access_visible_list(q, &argv[1], cl));
242 if (!strcmp(argv[0], "USER") || !strcmp(argv[0], "RUSER")) {
243 if (cl->users_id == *(int *)argv[1])
251 /* access_qgli - special access routine for Qualified_get_lists. Allows
252 * access iff argv[0] == "TRUE" and argv[2] == "FALSE".
255 access_qgli(q, argv, cl)
260 if (!strcmp(argv[0], "TRUE") && !strcmp(argv[2], "FALSE"))
266 /* access_service - allow access if user is on ACL of service. Don't
267 * allow access if a wildcard is used.
270 access_service(q, argv, cl)
275 EXEC SQL BEGIN DECLARE SECTION;
277 char *name, acl_type[9];
278 EXEC SQL END DECLARE SECTION;
279 int client_id, status;
280 char *client_type, *c;
283 for(c=name;*c;c++) if(islower(*c)) *c = toupper(*c); /* uppercasify */
284 EXEC SQL SELECT acl_id, acl_type INTO :acl_id, :acl_type FROM servers
286 if (sqlca.sqlerrd[2] > 1)
289 /* parse client structure */
290 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
293 /* check for client in access control list */
294 status = find_member(acl_type, acl_id, client_type, client_id, 0);
295 if (!status) return(MR_PERM);
301 /* access_filesys - verify that client is owner or on owners list of filesystem
305 access_filesys(q, argv, cl)
310 EXEC SQL BEGIN DECLARE SECTION;
311 int users_id, list_id;
313 EXEC SQL END DECLARE SECTION;
314 int status, client_id;
318 EXEC SQL SELECT owner, owners INTO :users_id, :list_id FROM filesys
321 if (sqlca.sqlerrd[2] != 1)
323 if (users_id == cl->users_id)
325 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
327 status = find_member("LIST", list_id, client_type, client_id, 0);
338 /* Setup routine for add_user
340 * Inputs: argv[0] - login
345 * - if argv[1] == UNIQUE_UID then set argv[1] = next(uid)
346 * - if argv[0] == UNIQUE_LOGIN then set argv[0] = "#<uid>"
349 setup_ausr(q, argv, cl)
351 register char *argv[];
355 EXEC SQL BEGIN DECLARE SECTION;
357 EXEC SQL END DECLARE SECTION;
359 if (!strcmp(q->shortname, "uusr") || !strcmp(q->shortname, "uuac"))
363 if (!strcmp(argv[row], UNIQUE_UID) || atoi(argv[row]) == -1) {
364 if (set_next_object_id("uid", "users", 1))
365 return(MR_INGRES_ERR);
366 EXEC SQL SELECT value INTO :nuid FROM numvalues WHERE name = 'uid';
367 if (sqlca.sqlerrd[2] != 1)
369 sprintf(argv[row], "%d", nuid);
372 if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[row]) == -1) {
373 sprintf(argv[0], "#%s", argv[row]);
380 /* setup_dusr - verify that the user is no longer being referenced
381 * and may safely be deleted.
384 int setup_dusr(q, argv)
388 EXEC SQL BEGIN DECLARE SECTION;
390 EXEC SQL END DECLARE SECTION;
392 id = *(int *)argv[0];
394 /*? Can this get wildcarded users? What happens then?! */
395 /*? How does the REPEATED keyword work? */
396 /* For now, only allow users to be deleted if their status is 0 */
397 EXEC SQL REPEATED SELECT status INTO :flag FROM users
399 if (flag != 0 && flag != 4)
402 EXEC SQL REPEATED DELETE FROM quota WHERE entity_id = :id AND type = 'USER';
403 EXEC SQL REPEATED DELETE FROM krbmap WHERE users_id = :id;
404 EXEC SQL REPEATED SELECT member_id INTO :idummy FROM imembers
405 WHERE member_id = :id AND member_type = 'USER';
406 if (sqlca.sqlerrd[2] > 0)
408 EXEC SQL REPEATED SELECT label INTO :cdummy FROM filesys WHERE owner = :id;
409 if (sqlca.sqlerrd[2]> 0)
411 EXEC SQL REPEATED SELECT name INTO :cdummy FROM list
412 WHERE acl_id = :id AND acl_type = 'USER';
413 if (sqlca.sqlerrd[2] > 0)
415 EXEC SQL REPEATED SELECT name INTO :cdummy FROM servers
416 WHERE acl_id = :id AND acl_type = 'USER';
417 if (sqlca.sqlerrd[2] > 0)
419 EXEC SQL REPEATED SELECT acl_id INTO :idummy FROM hostaccess
420 WHERE acl_d = :id AND acl_type = 'USER';
421 if (sqlca.sqlerrd[2] > 0)
429 /* setup_spop: verify that there is already a valid POP machine_id in the
430 * pop_id field. Also take care of keeping track of the post office usage.
432 int setup_spop(q, argv)
436 EXEC SQL BEGIN DECLARE SECTION;
439 EXEC SQL END DECLARE SECTION;
441 id = *(int *)argv[0];
442 EXEC SQL REPEATED SELECT potype, pop_id INTO :type, :mid FROM users
443 WHERE users_id = :id;
444 if(sqlca.sqlerrd[2] = 0)
446 EXEC SQL REPEATED SELECT mach_id INTO :mid FROM machine
447 WHERE mach_id = :mid;
448 if (sqlca.sqlerrd[2] = 0)
450 if (strcmp(strtrim(type), "POP"))
451 set_pop_usage(mid, 1);
456 /* setup_dpob: Take care of keeping track of the post office usage.
458 int setup_dpob(q, argv)
462 EXEC SQL BEGIN DECLARE SECTION;
465 EXEC SQL END DECLARE SECTION;
467 user = *(int *)argv[0];
468 EXEC SQL REPEATED SELECT potype, pop_id INTO :type, :id FROM users
469 WHERE users_id = :user;
470 if (ingres_errno) return(mr_errcode);
472 if (!strcmp(strtrim(type), "POP"))
473 set_pop_usage(id, -1);
478 /* setup_dmac - verify that the machine is no longer being referenced
479 * and may safely be deleted.
482 int setup_dmac(q, argv)
486 EXEC SQL BEGIN DECLARE SECTION;
488 EXEC SQL END DECLARE SECTION;
490 id = *(int *)argv[0];
491 EXEC SQL REPEATED SELECT login INTO :cdummy FROM users
492 WHERE potype='POP' AND pop_id = :id;
493 if (sqlca.sqlerrd[2] > 0)
495 EXEC SQL REPEATED SELECT mach_id INTO :idummy FROM serverhosts
497 if (sqlca.sqlerrd[2] > 0)
499 EXEC SQL REPEATED SELECT mach_id INTO :idummy FROM nfsphys
501 if (sqlca.sqlerrd[2] > 0)
503 EXEC SQL REPEATED SELECT mach_id INTO :idummy FROM hostaccess
505 if (sqlca.sqlerrd[2] > 0)
507 EXEC SQL REPEATED SELECT mach_id INTO :idummy FROM printcap
509 if (sqlca.sqlerrd[2] > 0)
511 EXEC SQL REPEATED SELECT quotaserver INTO :idummy FROM printcap
512 WHERE quotaserver = :id;
513 if (sqlca.sqlerrd[2] > 0)
515 EXEC SQL REPEATED SELECT mach_id INTO :idummy FROM palladium
517 if (sqlca.sqlerrd[2] > 0)
520 EXEC SQL REPEATED DELETE FROM mcmap WHERE mach_id = :id;
521 if (ingres_errno) return(mr_errcode);
526 /* setup_dclu - verify that the cluster is no longer being referenced
527 * and may safely be deleted.
530 int setup_dclu(q, argv)
534 EXEC SQL BEGIN DECLARE SECTION;
536 EXEC SQL END DECLARE SECTION;
538 id = *(int *)argv[0];
539 EXEC SQL REPEATED SELECT mach_id INTO :idummy FROM mcmap
541 if (sqlca.sqlerrd[2] > 0)
543 EXEC SQL REPEATED SELECT clu_id INTO :idummy FROM svc
545 if (sqlca.sqlerrd[2] > 0)
553 /* setup_alis - if argv[5] is non-zero and argv[6] is UNIQUE_ID, then allocate
554 * a new gid and put it in argv[6]. Otherwise if argv[6] is UNIQUE_ID but
555 * argv[5] is not, then remember that UNIQUE_ID is being stored by putting
556 * a -1 there. Remember that this is also used for ulis, with the indexes
560 int setup_alis(q, argv)
564 EXEC SQL BEGIN DECLARE SECTION;
566 EXEC SQL END DECLARE SECTION;
570 if (!strcmp(q->shortname, "alis"))
572 else if (!strcmp(q->shortname, "ulis"))
575 if (!strcmp(argv[idx], UNIQUE_GID) || atoi(argv[idx]) == -1) {
576 if (atoi(argv[idx - 1])) {
577 if (set_next_object_id("gid", "list", 1))
578 return(MR_INGRES_ERR);
579 EXEC SQL REPEATED SELECT value INTO :ngid FROM numvalues
581 if (ingres_errno) return(mr_errcode);
582 sprintf(argv[idx], "%d", ngid);
584 strcpy(argv[idx], "-1");
592 /* setup_dlist - verify that the list is no longer being referenced
593 * and may safely be deleted.
596 int setup_dlis(q, argv)
600 EXEC SQL BEGIN DECLARE SECTION;
602 EXEC SQL END DECLARE SECTION;
604 id = *(int *)argv[0];
605 EXEC SQL REPEATED SELECT member_id INTO :idummy FROM imembers
606 WHERE member_id = :id AND member_type='LIST';
607 if (sqlca.sqlerrd[2] > 0)
609 EXEC SQL REPEATED SELECT member_id INTO :idummy FROM imembers
611 if (sqlca.sqlerrd[2] > 0)
613 EXEC SQL REPEATED SELECT label INTO :cdummy FROM filesys
615 if (sqlca.sqlerrd[2] > 0)
617 EXEC SQL REPEATED SELECT tag INTO :cdummy FROM capacls
619 if (sqlca.sqlerrd[2] > 0)
621 EXEC SQL REPEATED SELECT name INTO :cdummy FROM list
622 WHERE acl_id = :id AND acl_type='LIST' AND list_id = :id;
623 if (sqlca.sqlerrd[2] > 0)
625 EXEC SQL REPEATED SELECT name INTO :cdummy FROM servers
626 WHERE acl_id = :id AND acl_type='LIST';
627 if (sqlca.sqlerrd[2] > 0)
629 EXEC SQL REPEATED SELECT entity_id INTO :idummy FROM quota
630 WHERE entity_id = :id AND type='GROUP';
631 if (sqlca.sqlerrd[2] > 0)
633 EXEC SQL REPEATED SELECT acl_id INTO :idummy FROM hostaccess
634 WHERE acl_id = :id AND acl_type='LIST';
635 if (sqlca.sqlerrd[2] > 0)
637 EXEC SQL REPEATED SELECT class INTO :cdummy FROM zephyr z
638 WHERE zephyr.xmt_type = 'LIST' AND z.xmt_id = :id
639 OR z.sub_type = 'LIST' AND z.sub_id = :id
640 OR z.iws_type = 'LIST' AND z.iws_id = :id
641 OR z.iui_type = 'LIST' AND z.iui_id = :id;
642 if (sqlca.sqlerrd[2] > 0)
650 /* setup_dsin - verify that the service is no longer being referenced
651 * and may safely be deleted.
654 int setup_dsin(q, argv)
658 EXEC SQL BEGIN DECLARE SECTION;
660 EXEC SQL END DECLARE SECTION;
664 for(c=name;*c;c++) if(islower(*c)) *c = toupper(*c);
665 EXEC SQL REPEATED SELECT service INTO :cdummy FROM serverhosts
666 WHERE service = :name;
667 if (sqlca.sqlerrd[2] > 0)
669 EXEC SQL REPEATED SELECT inprogress INTO :idummy FROM servers
671 if (sqlca.sqlerrd[2] > 0)
679 /* setup_dshi - verify that the service-host is no longer being referenced
680 * and may safely be deleted.
683 int setup_dshi(q, argv)
687 EXEC SQL BEGIN DECLARE SECTION;
690 EXEC SQL END DECLARE SECTION;
693 for(c=name;*c;c++) if(islower(*c)) *c = toupper(*c); /* to uppercase */
694 id = *(int *)argv[1];
695 EXEC SQL REPEATED SELECT inprogress INTO :idummy FROM serverhosts
696 WHERE service = :name AND mach_id = :id;
697 if (sqlca.sqlerrd[2] > 0)
706 ** setup_add_filesys - verify existance of referenced file systems
718 ** * extract directory prefix from name
719 ** * verify mach_id/dir in nfsphys
720 ** * verify access in {r, w, R, W}
722 ** Side effect: sets variable var_phys_id to the ID of the physical
723 ** filesystem (nfsphys_id for NFS, 0 for RVD)
726 ** MR_NFS - specified directory not exported
727 ** MR_FILESYS_ACCESS - invalid filesys access
731 EXEC SQL BEGIN DECLARE SECTION;
732 static int var_phys_id;
733 EXEC SQL END DECLARE SECTION;
741 EXEC SQL BEGIN DECLARE SECTION;
743 char ftype[32], *access;
744 EXEC SQL END DECLARE SECTION;
747 mach_id = *(int *)argv[2];
752 sprintf(ftype, "fs_access_%s", type);
753 EXEC SQL SELECT trans INTO :cdummy FROM alias
754 WHERE name = :ftype AND type = 'TYPE' and trans = :access;
755 if (ingres_errno) return(mr_errcode);
756 if (sqlca.sqlerrd[2] == 0) return(MR_FILESYS_ACCESS);
758 if (!strcmp(type, "NFS"))
759 return (check_nfs(mach_id, name, access));
765 /* Verify the arguments, depending on the FStype. Also, if this is an
766 * NFS filesystem, then update any quotas for that filesystem to reflect
770 setup_ufil(q, argv, cl)
777 EXEC SQL BEGIN DECLARE SECTION;
779 char *entity, ftype[32], *access;
781 EXEC SQL END DECLARE SECTION;
784 mach_id = *(int *)argv[3];
787 fid = *(int *)argv[0];
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;
794 if (ingres_errno) return(mr_errcode);
795 if (sqlca.sqlerrd[2] == 0) return(MR_FILESYS_ACCESS);
797 if (!strcmp(type, "NFS")) {
798 status = check_nfs(mach_id, name, access);
799 EXEC SQL UPDATE quota SET phys_id = :var_phys_id
800 WHERE filsys_id = :fid;
801 if (ingres_errno) return(mr_errcode);
803 } else if (!strcmp(type, "AFS")) {
805 EXEC SQL REPEATED DELETE FROM quota
806 WHERE type = 'ANY' AND filsys_id = :fid;
807 EXEC SQL SELECT SUM (quota) INTO :total FROM quota
808 WHERE filsys_id = :fid AND phys_id != 0;
809 if (ingres_errno) return(mr_errcode);
812 * append quota (quota = total, filsys_id = fid,
813 * phys_id = 0, entity_id = 0, type = "ANY",
814 * modtime = "now", modby = who, modwith = entity)
816 EXEC SQL INSERT INTO quota (quota, filsys_id, phys_id, entity_id,
817 type, modtime, modby, modwith)
818 VALUES (:total, :fid, 0, 0,
819 'ANY', 'now', :who, :entity) ;
820 if (ingres_errno) return(mr_errcode);
823 EXEC SQL UPDATE quota SET phys_id = 0 WHERE filsys_id = :fid;
824 if (ingres_errno) return(mr_errcode);
830 /* Find the NFS physical partition that the named directory is on.
831 * This is done by comparing the dir against the mount point of the
832 * partition. To make sure we get the correct match when there is
833 * more than one, we sort the query in reverse order by dir name.
836 check_nfs(mach_id, name, access)
837 EXEC SQL BEGIN DECLARE SECTION;
839 EXEC SQL END DECLARE SECTION;
843 EXEC SQL BEGIN DECLARE SECTION;
845 EXEC SQL END DECLARE SECTION;
852 EXEC SQL DECLARE csr101 CURSOR FOR
853 SELECT nfsphys_id, TRIM (dir) FROM nfsphys
854 WHERE mach_id = :mach_id
856 EXEC SQL OPEN csr101;
858 EXEC SQL FETCH csr101 INTO :var_phys_id, :dir;
859 if(sqlca.sqlcode != 0) break;
863 if (*cp1++ != *cp2) break;
871 EXEC SQL CLOSE csr101;
878 /* setup_dfil: free any quota records and fsgroup info associated with
879 * a filesystem when it is deleted. Also adjust the allocation numbers.
882 setup_dfil(q, argv, cl)
887 EXEC SQL BEGIN DECLARE SECTION;
889 EXEC SQL END DECLARE SECTION;
891 id = *(int *)argv[0];
892 EXEC SQL REPEATED SELECT SUM (quota) INTO :total FROM quota
893 WHERE filsys_id = :id;
894 EXEC SQL REPEATED UPDATE nfsphys SET allocated = allocated - :total
895 WHERE nfsphys_id = filesys.phys_id AND filesys.filsys_id = :id;
896 /** Is SQL smart enough to do the PRODUCT above? */
897 /** Or should we code it using another SELECT? */
899 EXEC SQL REPEATED DELETE FROM quota WHERE filsys_id = :id;
900 EXEC SQL REPEATED DELETE FROM fsgroup WHERE filsys_id = :id;
901 EXEC SQL REPEATED DELETE FROM fsgroup WHERE group_id = :id;
902 if (ingres_errno) return(mr_errcode);
907 /* setup_dnfp: check to see that the nfs physical partition does not have
908 * any filesystems assigned to it before allowing it to be deleted.
911 setup_dnfp(q, argv, cl)
916 EXEC SQL BEGIN DECLARE SECTION;
919 EXEC SQL END DECLARE SECTION;
921 id = *(int *)argv[0];
923 EXEC SQL REPEATED SELECT label INTO :cdummy FROM filesys fs, nfsphys np
924 WHERE fs.mach_id = :id AND fs.phys_id = np.nfsphys_id
925 AND np.mach_id = :id AND np.dir = :dir;
926 if (sqlca.sqlerrd[2] > 0)
934 /* setup_dqot: Remove allocation from nfsphys before deleting quota.
935 * argv[0] = filsys_id
936 * argv[1] = type if "update_quota" or "delete_quota"
937 * argv[2 or 1] = users_id or list_id
940 setup_dqot(q, argv, cl)
945 EXEC SQL BEGIN DECLARE SECTION;
948 EXEC SQL END DECLARE SECTION;
950 fs = *(int *)argv[0];
951 if (!strcmp(q->name, "update_quota") || !strcmp(q->name, "delete_quota")) {
953 id = *(int *)argv[2];
956 id = *(int *)argv[1];
959 EXEC SQL REPEATED SELECT quota INTO :quota FROM quota
960 WHERE type = :qtype AND entity_id = :id AND filsys_id = :fs;
961 EXEC SQL REPEATED UPDATE nfsphys
962 SET allocated = nfsphys.allocated - :quota
963 WHERE nfsphys_id = filesys.physid AND filesys.filsys_id = :fs;
965 if (ingres_errno) return(mr_errcode);
970 /* setup_sshi: don't exclusive lock the machine table during
971 * set_server_host_internal.
974 setup_sshi(q, argv, cl)
980 EXEC SQL set lockmode session where readlock = system;
985 /* setup add_kerberos_user_mapping: add the string to the string
986 * table if necessary.
989 setup_akum(q, argv, cl)
994 EXEC SQL BEGIN DECLARE SECTION;
997 EXEC SQL END DECLARE SECTION;
1000 if (name_to_id(name, "STRING", &id) != MR_SUCCESS) {
1001 if (q->type != APPEND) return(MR_STRING);
1002 EXEC SQL SELECT value INTO :id FROM numvalues
1003 WHERE name = 'strings_id';
1005 EXEC SQL UPDATE numvalues SET value = :id
1006 WHERE name = 'strings_id';
1007 EXEC SQL INSERT INTO strings (string_id, string) VALUES (:id, :name);
1008 cache_entry(name, "STRING", id);
1010 if (ingres_errno) return(mr_errcode);
1011 *(int *)argv[1] = id;
1017 /* FOLLOWUP ROUTINES */
1019 /* generic set_modtime routine. This takes the table name from the query,
1020 * and will update the modtime, modby, and modwho fields in the entry in
1021 * the table whose name field matches argv[0].
1024 set_modtime(q, argv, cl)
1029 char *name, *entity, *table;
1032 entity = cl->entity;
1033 who = cl->client_id;
1037 sprintf(stmt_buf,"UPDATE %s SET modtime = 'now', modby = %d, \
1038 modwith = '%s' WHERE %s.name = '%s'",table,who,entity,table,name);
1039 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
1044 /* generic set_modtime_by_id routine. This takes the table name from
1045 * the query, and the id name from the validate record,
1046 * and will update the modtime, modby, and modwho fields in the entry in
1047 * the table whose id matches argv[0].
1050 set_modtime_by_id(q, argv, cl)
1055 char *entity, *table, *id_name;
1058 entity = cl->entity;
1059 who = cl->client_id;
1061 id_name = q->validate->object_id;
1063 id = *(int *)argv[0];
1064 sprintf(stmt_buf,"UPDATE %s SET modtime = 'now', modby = %d, \
1065 modwith = '%s' WHERE %s.%s = %d",table,who,entity,table,id_name,id);
1066 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
1071 /* Sets the finger modtime on a user record. The users_id will be in argv[0].
1074 set_finger_modtime(q, argv, cl)
1079 EXEC SQL BEGIN DECLARE SECTION;
1082 EXEC SQL END DECLARE SECTION;
1084 entity = cl->entity;
1085 who = cl->client_id;
1086 users_id = *(int *)argv[0];
1088 EXEC SQL UPDATE users SET fmodtime='now', fmodby = :who, fmodwith = :entity
1089 WHERE users.users_id = :users_id;
1095 /* Sets the pobox modtime on a user record. The users_id will be in argv[0].
1098 set_pobox_modtime(q, argv, cl)
1103 EXEC SQL BEGIN DECLARE SECTION;
1106 EXEC SQL END DECLARE SECTION;
1108 entity = cl->entity;
1109 who = cl->client_id;
1110 users_id = *(int *)argv[0];
1112 EXEC SQL UPDATE users SET pmodtime='now', pmodby = :who, pmodwith = entity
1113 WHERE users.users_id = users_id;
1119 /* Like set_modtime, but uppercases the name first.
1122 set_uppercase_modtime(q, argv, cl)
1127 char *name, *entity, *table, *c;
1130 entity = cl->entity;
1131 who = cl->client_id;
1134 for(c=name;*c;c++) if(islower(*c)) *c = toupper(*c); /** INGRES has an uppercase() functiuons, but it's not portable. */
1136 sprintf(stmt_buf,"UPDATE %s SET modtime = 'now', modby = %d, \
1137 modwith = '%s' WHERE %s.name = '%s'",table,who,entity,table,name);
1138 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
1144 /* Sets the modtime on the machine whose mach_id is in argv[0]. This routine
1145 * is necessary for add_machine_to_cluster becuase the table that query
1146 * operates on is "mcm", not "machine".
1149 set_mach_modtime_by_id(q, argv, cl)
1154 EXEC SQL BEGIN DECLARE SECTION;
1157 EXEC SQL END DECLARE SECTION;
1159 entity = cl->entity;
1160 who = cl->client_id;
1161 id = *(int *)argv[0];
1162 EXEC SQL UPDATE machine SET modtime='now', modby = :who, modwith = :entity
1163 WHERE machine.mach_id = :id;
1169 /* Sets the modtime on the cluster whose mach_id is in argv[0]. This routine
1170 * is necessary for add_cluster_data and delete_cluster_data becuase the
1171 * table that query operates on is "svc", not "cluster".
1174 set_cluster_modtime_by_id(q, argv, cl)
1179 EXEC SQL BEGIN DECLARE SECTION;
1182 EXEC SQL END DECLARE SECTION;
1184 entity = cl->entity;
1185 who = cl->client_id;
1187 id = *(int *)argv[0];
1188 EXEC SQL UPDATE cluster SET modtime='now', modby = :who, modwith = :entity
1189 WHERE cluster.clu_id = :id;
1194 /* sets the modtime on the serverhost where the service name is in argv[0]
1195 * and the mach_id is in argv[1].
1198 set_serverhost_modtime(q, argv, cl)
1203 EXEC SQL BEGIN DECLARE SECTION;
1204 char *entity, *serv;
1206 EXEC SQL END DECLARE SECTION;
1208 entity = cl->entity;
1209 who = cl->client_id;
1212 id = *(int *)argv[1];
1213 EXEC SQL UPDATE serverhosts
1214 SET modtime = 'now', modby = :who, modwith = :entity
1215 WHERE service = :serv AND mach_id = :id;
1220 /* sets the modtime on the nfsphys where the mach_id is in argv[0] and the
1221 * directory name is in argv[1].
1224 set_nfsphys_modtime(q, argv, cl)
1229 EXEC SQL BEGIN DECLARE SECTION;
1232 EXEC SQL END DECLARE SECTION;
1234 entity = cl->entity;
1235 who = cl->client_id;
1237 id = *(int *)argv[0];
1239 EXEC SQL UPDATE nfsphys SET modtime = 'now', modby = :who, modwith = :entity
1240 WHERE dir = :dir AND mach_id = :id;
1245 /* sets the modtime on a filesystem, where argv[0] contains the filesys
1249 set_filesys_modtime(q, argv, cl)
1254 EXEC SQL BEGIN DECLARE SECTION;
1255 char *label, *entity;
1257 EXEC SQL END DECLARE SECTION;
1259 entity = cl->entity;
1260 who = cl->client_id;
1263 if (!strcmp(q->shortname, "ufil"))
1266 EXEC SQL UPDATE filesys SET modtime = 'now', modby = :who,
1267 modwith = :entity, phys_id = :var_phys_id
1268 WHERE label = :label;
1273 /* sets the modtime on a zephyr class, where argv[0] contains the class
1277 set_zephyr_modtime(q, argv, cl)
1282 EXEC SQL BEGIN DECLARE SECTION;
1283 char *class, *entity;
1285 EXEC SQL END DECLARE SECTION;
1287 entity = cl->entity;
1288 who = cl->client_id;
1292 EXEC SQL UPDATE zephyr SET modtime = 'now', modby = :who, modwith = :entity
1293 WHERE class = :class;
1299 /* fixes the modby field. This will be the second to last thing in the
1300 * argv, the argv length is determined from the query structure. It is
1301 * passed as a pointer to an integer. This will either turn it into a
1302 * username, or # + the users_id.
1304 followup_fix_modby(q, sq, v, action, actarg, cl)
1306 register struct save_queue *sq;
1308 register int (*action)();
1309 register int actarg;
1313 char **argv, *malloc();
1317 while (sq_get_data(sq, &argv)) {
1320 status = id_to_name(id, "USER", &argv[i]);
1322 status = id_to_name(-id, "STRING", &argv[i]);
1323 if (status && status != MR_NO_MATCH)
1325 (*action)(q->vcnt, argv, actarg);
1326 for (j = 0; j < q->vcnt; j++)
1335 /* After retrieving a user account, fix the modby field and signature.
1336 * The modby field is the second to last thing in the
1337 * argv, the argv length is determined from the query structure. It is
1338 * passed as a pointer to an integer. This will either turn it into a
1339 * username, or # + the users_id. Only "gua*" queries have a signature,
1340 * these are ones with U_END return values. "gub*" queries also use this
1341 * routine but don't have a signature.
1343 followup_guax(q, sq, v, action, actarg, cl)
1345 register struct save_queue *sq;
1347 register int (*action)();
1348 register int actarg;
1352 char **argv, *malloc();
1354 char sigbuf[256], *rawsig, *kname;
1360 while (sq_get_data(sq, &argv)) {
1363 status = id_to_name(id, "USER", &argv[i]);
1365 status = id_to_name(-id, "STRING", &argv[i]);
1366 if (status && status != MR_NO_MATCH)
1369 if (q->vcnt == U_END) {
1370 com_err(whoami, 0, "compressing signature");
1371 rawsig = argv[U_SIGNATURE];
1372 bcopy(&rawsig[0], &id, sizeof(int));
1374 status = id_to_name(id, "STRING", &kname);
1375 bcopy(&rawsig[4], &si.timestamp, sizeof(int));
1376 si.timestamp = ntohl(si.timestamp);
1377 si.SigInfoVersion = 0; /* XXXXX this isn't used */
1378 kname_parse(si.pname, si.pinst, si.prealm, kname);
1379 si.rawsig = (unsigned char *)&rawsig[8];
1380 GDSS_Recompose(&si, sigbuf);
1381 argv[U_SIGNATURE] = strsave(sigbuf);
1384 (*action)(q->vcnt, argv, actarg);
1385 for (j = 0; j < q->vcnt; j++)
1395 ** followup_ausr - add finger and pobox entries, set_user_modtime
1398 ** argv[0] - login (add_user)
1399 ** argv[3] - last name
1400 ** argv[4] - first name
1401 ** argv[5] - middle name
1405 followup_ausr(q, argv, cl)
1410 EXEC SQL BEGIN DECLARE SECTION;
1411 int who, status, sigwho, id;
1412 char *login, *entity, *src, *dst, *name;
1414 EXEC SQL END DECLARE SECTION;
1416 char databuf[32], *kname_unparse();
1417 EXEC SQL BEGIN DECLARE SECTION;
1419 EXEC SQL END DECLARE SECTION;
1423 /* build fullname */
1424 if (strlen(argv[4]) && strlen(argv[5]))
1425 sprintf(fullname, "%s %s %s", argv[4], argv[5], argv[3]);
1426 else if (strlen(argv[4]))
1427 sprintf(fullname, "%s %s", argv[4], argv[3]);
1429 sprintf(fullname, "%s", argv[3]);
1432 sprintf(databuf, "%s:%s", argv[U_NAME], argv[U_MITID]);
1433 /* skip bytes for timestamp & kname */
1434 si.rawsig = (unsigned char *)&rawsig[8];
1435 status = GDSS_Verify(databuf, strlen(databuf), argv[U_SIGNATURE], &si);
1437 name = kname_unparse(si.pname, si.pinst, si.prealm);
1438 status = name_to_id(name, "STRING", &sigwho);
1439 if (status == MR_NO_MATCH) {
1440 EXEC SQL REPEATED SELECT value INTO :sigwho FROM numvalues
1441 WHERE name = 'strings_id';
1443 EXEC SQL REPEATED UPDATE numvalues SET value = :sigwho
1444 WHERE name = 'strings_id';
1445 EXEC SQL INSERT INTO strings (string_id, string)
1446 VALUES (:sigwho, :name);
1449 sigwho = htonl(sigwho);
1450 bcopy(&sigwho, &rawsig[0], sizeof(int));
1451 si.timestamp = htonl(si.timestamp);
1452 bcopy(&si.timestamp, &rawsig[4], sizeof(int));
1458 who = cl->client_id;
1459 entity = cl->entity;
1461 /* create finger entry, pobox & set modtime on user */
1463 EXEC SQL REPEATED UPDATE users
1464 SET modtime='now', modby=:who, modwith = :entity,
1465 fullname = :fullname, mit_affil = mit_year,
1466 signature = :rawsig,
1467 fmodtime='now', fmodby = :who, fmodwith = :entity,
1468 potype='NONE', pmodtime='now', pmodby = :who, pmodwith = :entity
1469 WHERE login = :login;
1471 EXEC SQL REPEATED UPDATE users
1472 SET modtime='now', modby=:who, modwith = :entity,
1473 fullname = :fullname, mit_affil = mit_year,
1474 fmodtime='now', fmodby = :who, fmodwith = :entity,
1475 potype='NONE', pmodtime='now', pmodby = :who, pmodwith = :entity
1476 WHERE login = :login;
1483 /* followup_gpob: fixes argv[2] based on the IDs currently there and the
1484 * type in argv[1]. Then completes the upcall to the user.
1486 * argv[2] is of the form "123:234" where the first integer is the machine
1487 * ID if it is a pop box, and the second is the string ID if it is an SMTP
1488 * box. argv[1] should be "POP", "SMTP", or "NONE". Boxes of type NONE
1492 followup_gpob(q, sq, v, action, actarg, cl)
1493 register struct query *q;
1494 register struct save_queue *sq;
1495 register struct validate *v;
1496 register int (*action)();
1500 char **argv, *index();
1502 int mid, sid, status;
1505 while (sq_get_data(sq, &argv)) {
1506 mr_trim_args(2, argv);
1508 p = index(argv[2], ':');
1510 mid = atoi(argv[2]);
1513 if (!strcmp(ptype, "POP")) {
1514 status = id_to_name(mid, "MACHINE", &argv[2]);
1515 if (status == MR_NO_MATCH)
1517 } else if (!strcmp(ptype, "SMTP")) {
1518 status = id_to_name(sid, "STRING", &argv[2]);
1519 if (status == MR_NO_MATCH)
1521 } else /* ptype == "NONE" */ {
1524 if (status) return(status);
1526 if (!strcmp(q->shortname, "gpob")) {
1527 sid = atoi(argv[4]);
1529 status = id_to_name(sid, "USER", &argv[4]);
1531 status = id_to_name(-sid, "STRING", &argv[4]);
1533 if (status && status != MR_NO_MATCH) return(status);
1535 (*action)(q->vcnt, argv, actarg);
1537 /* free saved data */
1545 return (MR_SUCCESS);
1549 /* followup_glin: fix the ace_name in argv[8]. argv[7] will contain the
1550 * ace_type: "LIST", "USER", or "NONE". Decode the id in argv[8] into the
1551 * proper name based on the type, and repace that string in the argv.
1552 * Also fixes the modby field by called followup_fix_modby.
1555 followup_glin(q, sq, v, action, actarg, cl)
1556 register struct query *q;
1557 register struct save_queue *sq;
1558 register struct validate *v;
1559 register int (*action)();
1563 char **argv, *malloc(), *realloc(), *type;
1564 int id, i, idx, status;
1567 if (!strcmp(q->shortname, "gsin"))
1570 while (sq_get_data(sq, &argv)) {
1571 mr_trim_args(q->vcnt, argv);
1573 id = atoi(argv[i = q->vcnt - 2]);
1575 status = id_to_name(id, "USER", &argv[i]);
1577 status = id_to_name(-id, "STRING", &argv[i]);
1578 if (status && status != MR_NO_MATCH)
1581 id = atoi(argv[idx]);
1582 type = argv[idx - 1];
1584 if (!strcmp(type, "LIST")) {
1585 status = id_to_name(id, "LIST", &argv[idx]);
1586 } else if (!strcmp(type, "USER")) {
1587 status = id_to_name(id, "USER", &argv[idx]);
1588 } else if (!strcmp(type, "KERBEROS")) {
1589 status = id_to_name(id, "STRING", &argv[idx]);
1590 } else if (!strcmp(type, "NONE")) {
1593 argv[idx] = strsave("NONE");
1597 argv[idx] = strsave("???");
1599 if (status && status != MR_NO_MATCH)
1602 if (!strcmp(q->shortname, "glin") && atoi(argv[6]) == -1) {
1603 argv[6] = realloc(argv[6], strlen(UNIQUE_GID) + 1);
1604 strcpy(argv[6], UNIQUE_GID);
1608 (*action)(q->vcnt, argv, actarg);
1610 /* free saved data */
1611 for (i = 0; i < q->vcnt; i++)
1617 return (MR_SUCCESS);
1621 /* followup_gqot: Fix the entity name, directory name & modby fields
1622 * argv[0] = filsys_id
1624 * argv[2] = entity_id
1625 * argv[3] = ascii(quota)
1628 followup_gqot(q, sq, v, action, actarg, cl)
1630 register struct save_queue *sq;
1632 register int (*action)();
1633 register int actarg;
1637 char **argv, *malloc();
1638 EXEC SQL BEGIN DECLARE SECTION;
1641 EXEC SQL END DECLARE SECTION;
1644 if (!strcmp(q->name, "get_quota") ||
1645 !strcmp(q->name, "get_quota_by_filesys"))
1649 while (sq_get_data(sq, &argv)) {
1651 switch (argv[1][0]) {
1653 status = id_to_name(atoi(argv[2]), "USER", &argv[2]);
1657 status = id_to_name(atoi(argv[2]), "LIST", &argv[2]);
1661 argv[2] = strsave("system:anyuser");
1665 argv[2] = malloc(8);
1666 sprintf(argv[2], "%d", id);
1669 id = atoi(argv[idx]);
1671 argv[idx] = malloc(256);
1675 EXEC SQL REPEATED SELECT name INTO :name FROM filesys
1676 WHERE label = :label;
1678 EXEC SQL REPEATED SELECT dir INTO :name FROM nfsphys
1679 WHERE nfsphys_id = :id;
1681 if (sqlca.sqlerrd[2] != 1) {
1682 sprintf(argv[idx], "#%d", id);
1685 id = atoi(argv[idx+3]);
1687 status = id_to_name(id, "USER", &argv[idx+3]);
1689 status = id_to_name(-id, "STRING", &argv[idx+3]);
1690 if (status && status != MR_NO_MATCH)
1692 (*action)(q->vcnt, argv, actarg);
1693 for (j = 0; j < q->vcnt; j++)
1702 /* followup_aqot: Add allocation to nfsphys after creating quota.
1703 * argv[0] = filsys_id
1704 * argv[1] = type if "add_quota" or "update_quota"
1706 * argv[3 or 2] = ascii(quota)
1709 followup_aqot(q, argv, cl)
1714 EXEC SQL BEGIN DECLARE SECTION;
1715 int quota, id, fs, who;
1716 char *entity, *qtype;
1717 EXEC SQL END DECLARE SECTION;
1719 fs = *(int *)argv[0];
1720 if (!strcmp(q->name, "add_quota") || !strcmp(q->name, "update_quota")) {
1722 id = *(int *)argv[2];
1723 quota = atoi(argv[3]);
1726 id = *(int *)argv[1];
1727 quota = atoi(argv[2]);
1729 who = cl->client_id;
1730 entity = cl->entity;
1732 EXEC SQL REPEATED UPDATE quota
1733 SET modtime = 'now', modby = :who, modwith = :entity
1734 WHERE filsys_id = :fs and type = :qtype and entity_id = :id;
1735 EXEC SQL REPEATED UPDATE nfsphys
1736 SET allocated = allocated + :quota
1737 WHERE nfsphys_id = filesys.phys_id AND filesys.filsys_id = :fs;
1738 if (ingres_errno) return(mr_errcode);
1743 followup_gpce(q, sq, v, action, actarg, cl)
1745 register struct save_queue *sq;
1747 register int (*action)();
1748 register int actarg;
1752 char **argv, *malloc();
1756 while (sq_get_data(sq, &argv)) {
1757 id = atoi(argv[PCAP_QSERVER]);
1758 status = id_to_name(id, "MACHINE", &argv[PCAP_QSERVER]);
1759 if (status) return (status);
1762 status = id_to_name(id, "USER", &argv[i]);
1764 status = id_to_name(-id, "STRING", &argv[i]);
1765 if (status && status != MR_NO_MATCH)
1767 (*action)(q->vcnt, argv, actarg);
1768 for (j = 0; j < q->vcnt; j++)
1780 followup_gzcl(q, sq, v, action, actarg, cl)
1781 register struct query *q;
1782 register struct save_queue *sq;
1783 register struct validate *v;
1784 register int (*action)();
1791 while (sq_get_data(sq, &argv)) {
1792 mr_trim_args(q->vcnt, argv);
1794 id = atoi(argv[i = q->vcnt - 2]);
1796 status = id_to_name(id, "USER", &argv[i]);
1798 status = id_to_name(-id, "STRING", &argv[i]);
1799 if (status && status != MR_NO_MATCH)
1802 for (i = 1; i < 8; i+=2) {
1803 id = atoi(argv[i+1]);
1804 if (!strcmp(argv[i], "LIST")) {
1805 status = id_to_name(id, "LIST", &argv[i+1]);
1806 } else if (!strcmp(argv[i], "USER")) {
1807 status = id_to_name(id, "USER", &argv[i+1]);
1808 } else if (!strcmp(argv[i], "KERBEROS")) {
1809 status = id_to_name(id, "STRING", &argv[i+1]);
1810 } else if (!strcmp(argv[i], "NONE")) {
1813 argv[i+1] = strsave("NONE");
1817 argv[i+1] = strsave("???");
1819 if (status && status != MR_NO_MATCH)
1824 (*action)(q->vcnt, argv, actarg);
1826 /* free saved data */
1827 for (i = 0; i < q->vcnt; i++)
1839 followup_gsha(q, sq, v, action, actarg, cl)
1840 register struct query *q;
1841 register struct save_queue *sq;
1842 register struct validate *v;
1843 register int (*action)();
1850 while (sq_get_data(sq, &argv)) {
1851 mr_trim_args(q->vcnt, argv);
1855 status = id_to_name(id, "USER", &argv[4]);
1857 status = id_to_name(-id, "STRING", &argv[4]);
1858 if (status && status != MR_NO_MATCH)
1862 if (!strcmp(argv[1], "LIST")) {
1863 status = id_to_name(id, "LIST", &argv[2]);
1864 } else if (!strcmp(argv[1], "USER")) {
1865 status = id_to_name(id, "USER", &argv[2]);
1866 } else if (!strcmp(argv[1], "KERBEROS")) {
1867 status = id_to_name(id, "STRING", &argv[2]);
1868 } else if (!strcmp(argv[1], "NONE")) {
1871 argv[2] = strsave("NONE");
1875 argv[2] = strsave("???");
1877 if (status && status != MR_NO_MATCH)
1881 (*action)(q->vcnt, argv, actarg);
1883 /* free saved data */
1884 for (i = 0; i < q->vcnt; i++)
1894 /* Special query routines */
1896 /* set_pobox - this does all of the real work.
1897 * argv = user_id, type, box
1898 * if type is POP, then box should be a machine, and its ID should be put in
1899 * pop_id. If type is SMTP, then box should be a string and its ID should
1900 * be put in box_id. If type is NONE, then box doesn't matter.
1903 int set_pobox(q, argv, cl)
1908 EXEC SQL BEGIN DECLARE SECTION;
1910 char *box, potype[9];
1911 EXEC SQL END DECLARE SECTION;
1915 user = *(int *)argv[0];
1917 EXEC SQL REPEATED SELECT pop_id, potype INTO :id, :potype FROM users
1918 WHERE users_id = :user;
1919 if (ingres_errno) return(mr_errcode);
1920 if (!strcmp(strtrim(potype), "POP"))
1921 set_pop_usage(id, -1);
1923 if (!strcmp(argv[1], "POP")) {
1924 status = name_to_id(box, "MACHINE", &id);
1925 if (status == MR_NO_MATCH)
1929 EXEC SQL REPEATED UPDATE users SET potype = 'POP', pop_id = :id
1930 WHERE users_id = :user;
1931 set_pop_usage(id, 1);
1932 } else if (!strcmp(argv[1], "SMTP")) {
1933 if (index(box, '/') || index(box, '|'))
1934 return(MR_BAD_CHAR);
1935 status = name_to_id(box, "STRING", &id);
1936 if (status == MR_NO_MATCH) {
1937 EXEC SQL REPEATED SELECT value INTO :id FROM numvalues
1938 WHERE name='strings_id';
1940 EXEC SQL REPEATED UPDATE numvalues SET value = :id
1941 WHERE name='strings_id';
1942 EXEC SQL INSERT INTO strings (string_id, string)
1946 EXEC SQL REPEATED UPDATE users SET potype='SMTP', box_id = :id
1947 WHERE users_id = :user;
1948 } else /* argv[1] == "NONE" */ {
1949 EXEC SQL REPEATED UPDATE users SET potype='NONE'
1950 WHERE users_id = :user;
1953 set_pobox_modtime(q, argv, cl);
1954 EXEC SQL REPEATED UPDATE tblstats SET updates = updates+1, modtime='now'
1955 WHERE tblstats.table_name='users';
1956 if (ingres_errno) return(mr_errcode);
1961 /* get_list_info: passed a wildcard list name, returns lots of stuff about
1962 * each list. This is tricky: first build a queue of all requested
1963 * data. Rest of processing consists of fixing gid, ace_name, and modby.
1966 get_list_info(q, aargv, cl, action, actarg)
1967 register struct query *q;
1970 register int (*action)();
1973 char *argv[13], *malloc(), *realloc();
1974 EXEC SQL BEGIN DECLARE SECTION;
1975 char *name, acl_type[9], listname[33], active[5], public[5], hidden[5];
1976 char maillist[5], grouplist[5], gid_str[6], acl_name[256], desc[256];
1977 char modtime[27], modby[256], modwith[9];
1978 int id, rowcount, acl_id, hid, modby_id;
1979 EXEC SQL END DECLARE SECTION;
1980 int returned, status;
1981 struct save_queue *sq, *sq_create();
1983 returned = rowcount = 0;
1987 EXEC SQL DECLARE csr102 CURSOR FOR SELECT list_id FROM list
1989 EXEC SQL OPEN csr102;
1992 EXEC SQL FETCH csr102 INTO :id;
1993 if(sqlca.sqlcode!=0) break;
1994 sq_save_data(sq, id);
1997 EXEC SQL CLOSE csr102;
1999 if (ingres_errno) return(mr_errcode);
2001 return(MR_NO_MATCH);
2003 argv[0] = listname; argv[1] = active; argv[2] = public; argv[3] = hidden;
2004 argv[4] = maillist; argv[5] = grouplist; argv[6] = gid_str;
2005 argv[7] = acl_type; argv[9] = desc; argv[10] = modtime; argv[12] = modwith;
2007 while (sq_get_data(sq, &id)) {
2012 * repeat retrieve (listname = l.#name, active = text(l.#active),
2013 * public = text(l.#public), hidden = text(l.#hidden),
2014 * hid = l.#hidden, maillist = text(l.#maillist),
2015 * group = text(l.#group), gid = text(l.#gid),
2016 * acl_type = trim(l.#acl_type), acl_id = l.#acl_id,
2017 * desc = l.#desc, modtime = l.#modtime, modby_id = l.#modby,
2018 * modwith =l.#modwith)
2019 * where l.list_id = :id
2021 EXEC SQL REPEATED SELECT name, text(active), text(public),
2022 text(hidden), hidden, text(maillist), text(grouplist), text(gid),
2023 trim(acl_type), acl_id, desc, modtime, modby, modwith
2024 INTO :listname, :active, :public, :hidden, :hid, :maillist,
2025 :grouplist, :gid_str, :acl_type, :acl_id, :desc,
2026 :modtime, :modby_id, :modwith
2027 FROM list WHERE list_id = :id;
2029 if (ingres_errno) return(mr_errcode);
2031 if (atoi(gid_str) == -1)
2032 argv[6] = UNIQUE_GID;
2034 argv[8] = malloc(0);
2035 if (!strcmp(acl_type, "LIST")) {
2036 status = id_to_name(acl_id, "LIST", &argv[8]);
2037 } else if (!strcmp(acl_type, "USER")) {
2038 status = id_to_name(acl_id, "USER", &argv[8]);
2039 } else if (!strcmp(acl_type, "KERBEROS")) {
2040 status = id_to_name(acl_id, "STRING", &argv[8]);
2041 } else if (!strcmp(acl_type, "NONE")) {
2044 argv[8] = strsave("NONE");
2048 argv[8] = strsave("???");
2050 if (status && status != MR_NO_MATCH) return(status);
2052 argv[11] = malloc(0);
2054 status = id_to_name(modby_id, "USER", &argv[11]);
2056 status = id_to_name(-modby_id, "STRING", &argv[11]);
2057 if (status && status != MR_NO_MATCH) return(status);
2059 mr_trim_args(q->vcnt, argv);
2061 (*action)(q->vcnt, argv, actarg);
2067 if (ingres_errno) return(mr_errcode);
2068 return (MR_SUCCESS);
2072 /* Add_member_to_list: do list flattening as we go! MAXLISTDEPTH is
2073 * how many different ancestors a member is allowed to have.
2076 #define MAXLISTDEPTH 1024
2078 int add_member_to_list(q, argv, cl)
2083 EXEC SQL BEGIN DECLARE SECTION;
2084 int id, lid, mid, error, who, ref;
2085 char *mtype, dtype[9], *entity;
2086 EXEC SQL END DECLARE SECTION;
2087 int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a;
2088 int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d;
2090 char *dtypes[MAXLISTDEPTH];
2091 char *iargv[3], *buf;
2093 lid = *(int *)argv[0];
2095 mid = *(int *)argv[2];
2096 /* if the member is already a direct member of the list, punt */
2098 * repeat retrieve (exists = any(m.list_id where m.list_id=@lid and
2099 * m.member_id = :mid and m.member_type = :mtype
2100 * and m.direct = 1))
2102 EXEC SQL REPEATED SELECT list_id INTO :idummy FROM imembers
2103 WHERE list_id = :lid AND member_id = :mid
2104 AND member_type = :mtype AND direct = 1;
2105 if (sqlca.sqlerrd[2] > 0)
2107 if (!strcasecmp(mtype, "STRING")) {
2109 status = id_to_name(mid, "STRING", &buf);
2110 if (status) return(status);
2111 if (index(buf, '/') || index(buf, '|')) {
2113 return(MR_BAD_CHAR);
2121 EXEC SQL DECLARE csr103 CURSOR FOR
2122 SELECT list_id, ref_count FROM imembers
2123 WHERE member_id = :lid AND member_type='LIST';
2124 EXEC SQL OPEN csr103;
2126 EXEC SQL FETCH csr103 INTO :id, :ref;
2127 if(sqlca.sqlcode != 0) break;
2129 ancestors[acount++] = id;
2130 if (acount >= MAXLISTDEPTH) break;
2132 EXEC SQL CLOSE csr103;
2133 if (ingres_errno) return(mr_errcode);
2134 if (acount >= MAXLISTDEPTH) {
2135 return(MR_INTERNAL);
2137 descendants[0] = mid;
2142 if (!strcmp(mtype, "LIST")) {
2143 EXEC SQL DECLARE csr104 CURSOR FOR
2144 SELECT member_id, member_type, ref_count
2146 WHERE list_id = :mid;
2147 EXEC SQL OPEN csr104;
2149 EXEC SQL FETCH csr104 INTO :id, :dtype, :ref;
2150 if(sqlca.sqlcode != 0) break;
2153 dtypes[dcount] = "LIST";
2156 dtypes[dcount] = "USER";
2159 dtypes[dcount] = "STRING";
2162 dtypes[dcount] = "KERBEROS";
2169 descendants[dcount++] = id;
2170 if (dcount >= MAXLISTDEPTH) {
2175 EXEC SQL CLOSE csr104;
2176 if (ingres_errno) return(mr_errcode);
2178 return(MR_INTERNAL);
2180 for (a = 0; a < acount; a++) {
2182 for (d = 0; d < dcount; d++) {
2183 mid = descendants[d];
2185 if (mid == lid && !strcmp(mtype, "LIST")) {
2186 return(MR_LISTLOOP);
2189 * repeat retrieve (exists = any(m.ref_count where m.list_id = :lid
2190 * and m.member_id = :mid
2191 * and m.member_type = :mtype))
2193 EXEC SQL REPEATED SELECT ref_count INTO :idummy FROM imembers
2194 WHERE list_id = :lid AND member_id = :mid
2195 AND m.member_type = :mtype;
2196 ref = aref[a] * dref[d];
2197 if (sqlca.sqlerrd[2] > 0) {
2198 if (a == 0 && d == 0) {
2199 EXEC SQL UPDATE imembers
2200 SET ref_count = ref_count+ref, direct=1
2201 WHERE list_id = :lid AND member_id = :mid
2202 AND member_type = :mtype;
2204 EXEC SQL UPDATE imembers
2205 SET ref_count = ref_count+ref
2206 WHERE list_id = :lid AND member_id = :mid
2207 AND member_type = :mtype;
2210 incremental_clear_before();
2211 if (a == 0 && d == 0) {
2212 EXEC SQL INSERT INTO imembers
2213 (list_id, member_id, direct, member_type, ref_count)
2214 VALUES (:lid, :mid, 1, :mtype, 1);
2216 EXEC SQL INSERT INTO imembers
2217 (list_id, member_id, member_type, ref_count)
2218 VALUES (:lid, :mid, :mtype, 1);
2220 iargv[0] = (char *)lid;
2222 iargv[2] = (char *)mid;
2223 incremental_after("members", 0, iargv);
2227 lid = *(int *)argv[0];
2228 entity = cl->entity;
2229 who = cl->client_id;
2230 EXEC SQL REPEATED UPDATE list
2231 SET modtime='now', modby = :who, modwith = :entity
2232 WHERE list_id = :lid;
2233 if (ingres_errno) return(mr_errcode);
2238 /* Delete_member_from_list: do list flattening as we go!
2241 int delete_member_from_list(q, argv, cl)
2246 EXEC SQL BEGIN DECLARE SECTION;
2247 int id, lid, mid, cnt, error, who, ref;
2248 char *mtype, dtype[9], *entity;
2249 EXEC SQL END DECLARE SECTION;
2250 int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a;
2251 int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d;
2252 char *dtypes[MAXLISTDEPTH];
2255 lid = *(int *)argv[0];
2257 mid = *(int *)argv[2];
2258 /* if the member is not a direct member of the list, punt */
2260 * repeat retrieve (exists = any(m.list_id where m.list_id=@lid and
2261 * m.member_id = :mid and m.member_type = :mtype
2262 * and m.direct = 1))
2264 EXEC SQL REPEATED SELECT list_id INTO :idummy FROM imembers
2265 WHERE list_id = :lid AND member_id = :mid
2266 AND member_type = :mtype AND direct = 1;
2267 if (ingres_errno) return(mr_errcode);
2268 if (sqlca.sqlcode == 100)
2269 return(MR_NO_MATCH);
2273 EXEC SQL DECLARE csr105 CURSOR FOR
2274 SELECT list_id, ref_count FROM imembers
2275 WHERE member_id = :lid AND member_type = 'LIST';
2276 EXEC SQL OPEN csr105;
2278 EXEC SQL FETCH csr105 INTO :id, :ref;
2279 if(sqlca.sqlcode!=0) break;
2281 ancestors[acount++] = id;
2282 if (acount >= MAXLISTDEPTH) break;
2284 EXEC SQL CLOSE csr105;
2287 if (acount >= MAXLISTDEPTH)
2288 return(MR_INTERNAL);
2289 descendants[0] = mid;
2294 if (!strcmp(mtype, "LIST")) {
2295 EXEC SQL DECLARE csr106 CURSOR FOR
2296 SELECT member_id, member_type, ref_count FROM imembers
2297 WHERE list_id = :mid;
2298 EXEC SQL OPEN csr106;
2300 EXEC SQL FETCH csr106 INTO :id, :dtype, :ref;
2301 if(sqlca.sqlcode!=0) break;
2304 dtypes[dcount] = "LIST";
2307 dtypes[dcount] = "USER";
2310 dtypes[dcount] = "STRING";
2313 dtypes[dcount] = "KERBEROS";
2320 descendants[dcount++] = id;
2321 if (dcount >= MAXLISTDEPTH) break;
2323 EXEC SQL CLOSE csr106;
2327 return(MR_INTERNAL);
2329 for (a = 0; a < acount; a++) {
2331 for (d = 0; d < dcount; d++) {
2332 mid = descendants[d];
2334 if (mid == lid && !strcmp(mtype, "LIST")) {
2335 return(MR_LISTLOOP);
2337 EXEC SQL REPEATED SELECT ref_count INTO :cnt FROM imembers
2338 WHERE list_id = :lid AND member_id = :mid AND member_type = :mtype;
2339 ref = aref[a] * dref[d];
2341 iargv[0] = (char *)lid;
2343 iargv[2] = (char *)mid;
2344 incremental_before("members", 0, iargv);
2345 EXEC SQL DELETE FROM imembers
2346 WHERE list_id = :lid AND member_id = :mid
2347 AND member_type= :mtype;
2348 incremental_clear_after();
2349 } else if (a == 0 && d == 0) {
2350 EXEC SQL UPDATE imembers
2351 SET ref_count = refcount - :ref, direct = 0
2352 WHERE list_id = :lid AND member_id = :mid
2353 AND member_type = :mtype;
2355 EXEC SQL UPDATE imembers
2356 SET ref_count=refcount-:ref
2357 WHERE list_id = :lid AND member_id = :mid
2358 AND member_type = :mtype;
2362 lid = *(int *)argv[0];
2363 entity = cl->entity;
2364 who = cl->client_id;
2365 EXEC SQL UPDATE list SET modtime = 'now', modby = :who, modwith = :entity
2366 WHERE list_id = :lid;
2367 if (ingres_errno) return(mr_errcode);
2372 /* get_ace_use - given a type and a name, return a type and a name.
2373 * The ace_type is one of "LIST", "USER", "RLIST", or "RUSER" in argv[0],
2374 * and argv[1] will contain the ID of the entity in question. The R*
2375 * types mean to recursively look at every containing list, not just
2376 * when the object in question is a direct member. On return, the
2377 * usage type will be one of LIST, SERVICE, FILESYS, QUOTA, QUERY, or ZEPHYR.
2380 int get_ace_use(q, argv, cl, action, actarg)
2388 EXEC SQL BEGIN DECLARE SECTION;
2390 int aid, listid, id;
2391 EXEC SQL END DECLARE SECTION;
2392 struct save_queue *sq, *sq_create();
2395 aid = *(int *)argv[1];
2396 if (!strcmp(atype, "LIST") || !strcmp(atype, "USER") ||
2397 !strcmp(atype, "KERBEROS")) {
2398 return(get_ace_internal(atype, aid, action, actarg));
2402 if (!strcmp(atype, "RLIST")) {
2403 sq_save_data(sq, aid);
2404 /* get all the list_id's of containing lists */
2405 EXEC SQL DECLARE csr107 CURSOR FOR
2406 SELECT list_id FROM imembers
2407 WHERE member_type='LIST' AND member_id = :aid;
2408 EXEC SQL OPEN csr107;
2410 EXEC SQL FETCH csr107 INTO :listid;
2411 if(sqlca.sqlcode != 0) break;
2412 sq_save_unique_data(sq, listid);
2414 EXEC SQL CLOSE csr107;
2415 /* now process each one */
2416 while (sq_get_data(sq, &id)) {
2417 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2422 if (!strcmp(atype, "RUSER")) {
2423 EXEC SQL DECLARE csr108 CURSOR FOR
2424 SELECT list_id FROM imembers
2425 WHERE member_type='USER' AND member_id = :aid;
2426 EXEC SQL OPEN csr108;
2428 EXEC SQL FETCH csr108 INTO :listid;
2429 if(sqlca.sqlcode != 0) break;
2430 sq_save_data(sq, listid);
2432 EXEC SQL CLOSE csr108;
2433 /* now process each one */
2434 while (sq_get_data(sq, &id)) {
2435 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2438 if (get_ace_internal("USER", aid, action, actarg) == MR_SUCCESS)
2442 if (!strcmp(atype, "RKERBERO")) {
2443 EXEC SQL DECLARE csr109 CURSOR FOR
2444 SELECT list_id FROM imembers
2445 WHERE member_type='KERBEROS' AND member_id = :aid;
2446 EXEC SQL OPEN csr109;
2448 EXEC SQL FETCH csr109 INTO :listid;
2449 if(sqlca.sqlcode != 0) break;
2450 sq_save_data(sq, listid);
2452 EXEC SQL CLOSE csr109;
2453 /* now process each one */
2454 while (sq_get_data(sq, &id)) {
2455 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2458 if (get_ace_internal("KERBEROS", aid, action, actarg) == MR_SUCCESS)
2463 if (ingres_errno) return(mr_errcode);
2464 if (!found) return(MR_NO_MATCH);
2469 /* This looks up a single list or user for ace use. atype must be "USER"
2470 * or "LIST", and aid is the ID of the corresponding object. This is used
2471 * by get_ace_use above.
2474 get_ace_internal(atype, aid, action, actarg)
2475 EXEC SQL BEGIN DECLARE SECTION;
2478 EXEC SQL END DECLARE SECTION;
2484 EXEC SQL BEGIN DECLARE SECTION;
2486 EXEC SQL END DECLARE SECTION;
2489 if (!strcmp(atype, "LIST")) {
2490 rargv[0] = "FILESYS";
2491 EXEC SQL DECLARE csr110 CURSOR FOR
2492 SELECT label FROM filesys
2493 WHERE owners = :aid;
2494 EXEC SQL OPEN csr110;
2496 EXEC SQL FETCH csr110 INTO :name;
2497 if(sqlca.sqlcode != 0) break;
2498 (*action)(2, rargv, actarg);
2501 EXEC SQL CLOSE csr110;
2504 EXEC SQL DECLARE csr111 CURSOR FOR
2505 SELECT capability FROM capacls
2506 WHERE list_id = :aid ;
2507 EXEC SQL OPEN csr111;
2509 EXEC SQL FETCH csr111 INTO :name ;
2510 if(sqlca.sqlcode != 0) break;
2511 (*action)(2, rargv, actarg);
2514 EXEC SQL CLOSE csr111;
2515 } else if (!strcmp(atype, "USER")) {
2516 rargv[0] = "FILESYS";
2517 EXEC SQL DECLARE csr112 CURSOR FOR
2518 SELECT label FROM filesys
2520 EXEC SQL OPEN csr112;
2522 EXEC SQL FETCH csr112 INTO :name ;
2523 if(sqlca.sqlcode != 0) break;
2524 (*action)(2, rargv, actarg);
2527 EXEC SQL CLOSE csr112;
2531 EXEC SQL DECLARE csr113 CURSOR FOR
2532 SELECT name FROM list
2533 WHERE acl_type = :atype AND acl_id = :aid;
2534 EXEC SQL OPEN csr113;
2536 EXEC SQL FETCH csr113 INTO :name;
2537 if(sqlca.sqlcode != 0) break;
2538 (*action)(2, rargv, actarg);
2541 EXEC SQL CLOSE csr113;
2543 rargv[0] = "SERVICE";
2544 EXEC SQL DECLARE csr114 CURSOR FOR
2545 SELECT name FROM servers
2546 WHERE acl_type = :atype AND acl_id = :aid;
2547 EXEC SQL OPEN csr114;
2549 EXEC SQL FETCH csr114 INTO :name;
2550 if(sqlca.sqlcode != 0) break;
2551 (*action)(2, rargv, actarg);
2554 EXEC SQL CLOSE csr114;
2556 rargv[0] = "HOSTACCESS";
2557 EXEC SQL DECLARE csr115 CURSOR FOR
2558 SELECT name FROM machine, hostaccess
2559 WHERE mach_id = hostaccess.mach_id AND hostaccess.acl_type = :atype
2560 AND hostaccess.acl_id = :aid;
2561 EXEC SQL OPEN csr115;
2563 EXEC SQL FETCH csr115 INTO :name;
2564 if(sqlca.sqlcode != 0) break;
2565 (*action)(2, rargv, actarg);
2568 EXEC SQL CLOSE csr115;
2570 rargv[0] = "ZEPHYR";
2571 EXEC SQL DECLARE csr116 CURSOR FOR
2572 SELECT class FROM zephyr
2573 WHERE zephyr.xmt_type = :atype AND zephyr.xmt_id = :aid
2574 OR zephyr.sub_type = :atype AND zephyr.sub_id = :aid
2575 OR zephyr.iws_type = :atype AND zephyr.iws_id = :aid
2576 OR zephyr.iui_type = :atype AND zephyr.iui_id = :aid;
2577 EXEC SQL OPEN csr116;
2579 EXEC SQL FETCH csr116 INTO :name;
2580 if(sqlca.sqlcode != 0) break;
2581 (*action)(2, rargv, actarg);
2584 EXEC SQL CLOSE csr116;
2586 if (!found) return(MR_NO_MATCH);
2591 /* get_lists_of_member - given a type and a name, return the name and flags
2592 * of all of the lists of the given member. The member_type is one of
2593 * "LIST", "USER", "STRING", "RLIST", "RUSER", or "RSTRING" in argv[0],
2594 * and argv[1] will contain the ID of the entity in question. The R*
2595 * types mean to recursively look at every containing list, not just
2596 * when the object in question is a direct member.
2599 int get_lists_of_member(q, argv, cl, action, actarg)
2606 int found = 0, direct = 1;
2608 EXEC SQL BEGIN DECLARE SECTION;
2610 int aid, listid, id;
2611 char name[33], active[5], public[5], hidden[5], maillist[5], grouplist[5];
2612 EXEC SQL END DECLARE SECTION;
2615 aid = *(int *)argv[1];
2616 if (!strcmp(atype, "RLIST")) {
2620 if (!strcmp(atype, "RUSER")) {
2624 if (!strcmp(atype, "RSTRING")) {
2628 if (!strcmp(atype, "RKERBEROS")) {
2637 rargv[4] = maillist;
2638 rargv[5] = grouplist;
2641 * repeat retrieve (name = list.#name, active = text(list.#active),
2642 * public = text(list.#public), hidden = text(list.#hidden),
2643 * maillist = text(list.#maillist), group = text(list.#group))
2644 * where list.list_id = m.list_id and m.direct = 1 and
2645 * m.member_type = :atype and m.member_id = :aid
2647 EXEC SQL DECLARE csr117a CURSOR FOR
2648 SELECT name, text(active), text(public), text(hidden),
2649 text(maillist), text(grouplist)
2650 FROM list l, imembers m
2651 WHERE l.list_id = m.list_id AND m.direct = 1
2652 AND m.member_type = :atype AND m.member_id = :aid;
2653 EXEC SQL OPEN csr117a;
2655 EXEC SQL FETCH csr117a
2656 INTO :name, :active, :public, :hidden, :maillist, :grouplist;
2657 if(sqlca.sqlcode != 0) break;
2658 (*action)(6, rargv, actarg);
2661 EXEC SQL CLOSE csr117a;
2663 EXEC SQL DECLARE csr117b CURSOR FOR
2664 SELECT name, text(active), text(public), text(hidden),
2665 text(maillist), text(grouplist)
2666 FROM list l, imembers m
2667 WHERE l.list_id = m.list_id
2668 AND m.member_type = :atype AND m.member_id = :aid;
2669 EXEC SQL OPEN csr117b;
2671 EXEC SQL FETCH csr117b
2672 INTO :name, :active, :public, :hidden, :maillist, :grouplist;
2673 if(sqlca.sqlcode != 0) break;
2674 (*action)(6, rargv, actarg);
2677 EXEC SQL CLOSE csr117b;
2680 if (ingres_errno) return(mr_errcode);
2681 if (!found) return(MR_NO_MATCH);
2686 /* qualified_get_lists: passed "TRUE", "FALSE", or "DONTCARE" for each of
2687 * the five flags associated with each list. It will return the name of
2688 * each list that meets the quailifications. It does this by building a
2689 * where clause based on the arguments, then doing a retrieve.
2692 static char *lflags[5] = { "active", "public", "hidden", "maillist", "group" };
2694 int qualified_get_lists(q, argv, cl, action, actarg)
2701 return(qualified_get(q, argv, action, actarg, "l.list_id != 0",
2702 "l", "name", lflags));
2706 /** get_members_of_list - optimized query for retrieval of list members
2709 ** argv[0] - list_id
2712 ** - retrieve USER members, then LIST members, then STRING members
2715 get_members_of_list(q, argv, cl, action, actarg)
2722 EXEC SQL BEGIN DECLARE SECTION;
2723 int list_id, member_id;
2724 char member_name[129], member_type[9];
2725 EXEC SQL END DECLARE SECTION;
2728 struct save_queue *sq;
2730 list_id = *(int *)argv[0];
2734 EXEC SQL DECLARE csr118 CURSOR FOR
2735 SELECT member_type, member_id FROM imembers
2736 WHERE list_id = :list_id AND direct=1;
2737 EXEC SQL OPEN csr118;
2739 EXEC SQL FETCH csr118 INTO :member_type, :member_id;
2740 if (sqlca.sqlcode != 0) break;
2743 sq_save_data(sq, ((int)member_type[0] << 24) | (member_id & 0xffffff));
2745 EXEC SQL CLOSE csr118;
2747 if (members <= 49) {
2748 targv[1] = malloc(0);
2749 while (sq_remove_data(sq, &member_id)) {
2750 switch (member_id >> 24) {
2753 id_to_name(member_id & 0xffffff, "USER", &targv[1]);
2754 (*action)(2, targv, actarg);
2758 id_to_name(member_id & 0xffffff, "LIST", &targv[1]);
2759 (*action)(2, targv, actarg);
2762 targv[0] = "STRING";
2763 id_to_name(member_id & 0xffffff, "STRING", &targv[1]);
2764 (*action)(2, targv, actarg);
2767 targv[0] = "KERBEROS";
2768 id_to_name(member_id & 0xffffff, "STRING", &targv[1]);
2769 (*action)(2, targv, actarg);
2773 return(MR_INTERNAL);
2782 targv[1] = member_name;
2784 EXEC SQL DECLARE csr119 CURSOR FOR
2785 SELECT users.login FROM users, imembers
2786 WHERE imembers.list_id = :list_id AND imembers.member_type = 'USER'
2787 AND imembers.member_id = users.users_id AND imembers.direct=1
2789 EXEC SQL OPEN csr119;
2791 EXEC SQL FETCH csr119 INTO :member_name;
2792 if(sqlca.sqlcode != 0) break;
2793 (*action)(2, targv, actarg);
2795 EXEC SQL CLOSE csr119;
2796 if (ingres_errno) return(mr_errcode);
2799 EXEC SQL DECLARE csr120 CURSOR FOR
2800 SELECT list.name FROM list, imembers
2801 WHERE imembers.list_id = :list_id AND imembers.member_type='LIST'
2802 AND imembers.member_id = list.list_id AND imembers.direct=1
2804 EXEC SQL OPEN csr120;
2806 EXEC SQL FETCH csr120 INTO :member_name;
2807 if(sqlca.sqlcode != 0) break;
2808 (*action)(2, targv, actarg);
2810 EXEC SQL CLOSE csr120;
2811 if (ingres_errno) return(mr_errcode);
2813 targv[0] = "STRING";
2814 EXEC SQL DECLARE csr121 CURSOR FOR
2815 SELECT strings.string FROM strings, imembers
2816 WHERE imembers.list_id = :list_id AND imembers.member_type='STRING'
2817 AND imembers.member_id = strings.string_id AND imembers.direct=1
2819 EXEC SQL OPEN csr121;
2821 EXEC SQL FETCH csr121 INTO :member_name;
2822 if(sqlca.sqlcode != 0) break;
2823 (*action)(2, targv, actarg);
2825 EXEC SQL CLOSE csr121;
2826 if (ingres_errno) return(mr_errcode);
2828 targv[0] = "KERBEROS";
2829 EXEC SQL DECLARE csr122 CURSOR FOR
2830 SELECT strings.string FROM strings, imembers
2831 WHERE imembers.list_id = :list_id AND imembers.member_type='KERBEROS'
2832 AND imembers.member_id = strings.string_id AND imembers.direct=1
2834 EXEC SQL OPEN csr122;
2836 EXEC SQL FETCH csr122 INTO :member_name;
2837 if(sqlca.sqlcode != 0) break;
2838 (*action)(2, targv, actarg);
2840 EXEC SQL CLOSE csr122;
2841 if (ingres_errno) return(mr_errcode);
2847 /* count_members_of_list: this is a simple query, but it cannot be done
2848 * through the dispatch table.
2851 int count_members_of_list(q, argv, cl, action, actarg)
2858 EXEC SQL BEGIN DECLARE SECTION;
2860 EXEC SQL END DECLARE SECTION;
2861 char *rargv[1], countbuf[5];
2863 list = *(int *)argv[0];
2864 rargv[0] = countbuf;
2865 EXEC SQL REPEATED SELECT count (*) INTO :ct FROM imembers
2866 WHERE list_id = :list AND direct=1;
2867 if (ingres_errno) return(mr_errcode);
2868 sprintf(countbuf, "%d", ct);
2869 (*action)(1, rargv, actarg);
2874 /* qualified_get_server: passed "TRUE", "FALSE", or "DONTCARE" for each of
2875 * the three flags associated with each service. It will return the name of
2876 * each service that meets the quailifications. It does this by building a
2877 * where clause based on the arguments, then doing a retrieve.
2880 static char *sflags[3] = { "enable", "inprogress", "harderror" };
2882 int qualified_get_server(q, argv, cl, action, actarg)
2889 return(qualified_get(q, argv, action, actarg, "s.name != ''",
2890 "s", "name", sflags));
2894 /* generic qualified get routine, used by qualified_get_lists,
2895 * qualified_get_server, and qualified_get_serverhost.
2897 * start - a simple where clause, must not be empty
2898 * range - the name of the range variable
2899 * field - the field to return
2900 * flags - an array of strings, names of the flag variables
2903 int qualified_get(q, argv, action, actarg, start, range, field, flags)
2913 char name[33], qual[256];
2915 char *rargv[1], buf[32];
2917 strcpy(qual, start);
2918 for (i = 0; i < q->argc; i++) {
2919 if (!strcmp(argv[i], "TRUE")) {
2920 sprintf(buf, " and %s.%s != 0", range, flags[i]);
2921 (void) strcat(qual, buf);
2922 } else if (!strcmp(argv[i], "FALSE")) {
2923 sprintf(buf, " and %s.%s = 0", range, flags[i]);
2924 (void) strcat(qual, buf);
2928 rargv[0] = SQLDA->sqlvar[0].sqldata;
2929 sprintf(stmt_buf,"SELECT %s.%s FROM %s WHERE %s",q->rtable,field,q->rtable,qual);
2930 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
2931 if((mr_errcode=mr_check_SQLDA(SQLDA)) != MR_SUCCESS)
2933 EXEC SQL DECLARE csr123 CURSOR FOR stmt;
2934 EXEC SQL OPEN csr123;
2936 EXEC SQL FETCH csr123 USING DESCRIPTOR :SQLDA;
2937 if(sqlca.sqlcode != 0) break;
2938 mr_fix_nulls_in_SQLDA(SQLDA);
2940 (*action)(1, rargv, actarg);
2942 EXEC SQL CLOSE csr123;
2943 if (ingres_errno) return(mr_errcode);
2945 return(MR_NO_MATCH);
2950 /* qualified_get_serverhost: passed "TRUE", "FALSE", or "DONTCARE" for each of
2951 * the five flags associated with each serverhost. It will return the name of
2952 * each service and host that meets the quailifications. It does this by
2953 * building a where clause based on the arguments, then doing a retrieve.
2956 static char *shflags[6] = { "service", "enable", "override", "success",
2957 "inprogress", "hosterror" };
2959 int qualified_get_serverhost(q, argv, cl, action, actarg)
2966 EXEC SQL BEGIN DECLARE SECTION;
2967 char sname[33], mname[33], qual[256];
2968 EXEC SQL END DECLARE SECTION;
2969 char *rargv[2], buf[32];
2972 /** the uppercase() function is INGRES-specific */
2973 sprintf(qual, "machine.mach_id = serverhosts.mach_id AND \
2974 serverhosts.service = uppercase('%s')",
2976 for (i = 1; i < q->argc; i++) {
2977 if (!strcmp(argv[i], "TRUE")) {
2978 sprintf(buf, " AND serverhosts.%s != 0", shflags[i]);
2980 } else if (!strcmp(argv[i], "FALSE")) {
2981 sprintf(buf, " AND serverhosts.%s = 0", shflags[i]);
2988 EXEC SQL DECLARE csr124 CURSOR FOR
2989 SELECT serverhosts.service, machine.name FROM serverhosts, machine
2991 EXEC SQL OPEN csr124;
2993 EXEC SQL FETCH csr124 INTO :sname, :mname;
2994 if(sqlca.sqlcode != 0) break;
2996 (*action)(2, rargv, actarg);
2998 EXEC SQL CLOSE csr124;
3000 if (ingres_errno) return(mr_errcode);
3002 return(MR_NO_MATCH);
3007 /* register_user - change user's login name and allocate a pobox, group,
3008 * filesystem, and quota for them. The user's status must start out as 0,
3009 * and is left as 2. Arguments are: user's UID, new login name, and user's
3010 * type for filesystem allocation (MR_FS_STUDENT, MR_FS_FACULTY,
3011 * MR_FS_STAFF, MR_FS_MISC).
3014 register_user(q, argv, cl)
3019 EXEC SQL BEGIN DECLARE SECTION;
3020 char *login, dir[65], *entity, *directory, machname[33];
3021 int who, rowcount, mid, uid, users_id, flag, utype, nid, list_id, quota;
3022 int size, alloc, pid, m_id, ostatus, nstatus, gidval, fsidval;
3023 EXEC SQL END DECLARE SECTION;
3024 char buffer[256], *aargv[3];
3027 entity = cl->entity;
3028 who = cl->client_id;
3030 uid = atoi(argv[0]);
3032 utype = atoi(argv[2]);
3035 EXEC SQL REPEATED SELECT users_id, status INTO :users_id, :ostatus
3037 WHERE uid = :uid AND (status=0 OR status=5 OR status=6);
3039 if (sqlca.sqlerrd[2] == 0)
3040 return(MR_NO_MATCH);
3041 if (sqlca.sqlerrd[2] > 1)
3042 return(MR_NOT_UNIQUE);
3044 /* check new login name */
3045 EXEC SQL REPEATED SELECT login INTO :cdummy FROM users
3046 WHERE login = :login AND users_id != :users_id;
3047 if (ingres_errno) return(mr_errcode);
3048 if (sqlca.sqlerrd[2] > 0) return(MR_IN_USE);
3049 EXEC SQL REPEATED SELECT name INTO :cdummy FROM list
3050 WHERE name = :login;
3051 if (ingres_errno) return(mr_errcode);
3052 if (sqlca.sqlerrd[2] > 0) return(MR_IN_USE);
3053 EXEC SQL REPEATED SELECT label INTO :cdummy FROM filesys
3054 WHERE label = :login;
3055 if (ingres_errno) return(mr_errcode);
3056 if (sqlca.sqlerrd[2] > 0) return(MR_IN_USE);
3057 com_err(whoami, 0, "login name OK");
3059 /* choose place for pobox, put in mid */
3060 EXEC SQL REPEATED SELECT sh.mach_id, m.name
3061 INTO :mid, :machname FROM serverhosts sh, machine m
3062 WHERE sh.service='POP' AND sh.value2 - sh.value1 =
3063 (SELECT MAX(value2 - value1) FROM serverhosts
3064 WHERE service = 'POP');
3065 if (ingres_errno) return(mr_errcode);
3066 if (sqlca.sqlerrd[2] == 0)
3067 return(MR_NO_POBOX);
3069 /* change login name, set pobox */
3070 sprintf(buffer, "users.users_id = %d", users_id);
3071 incremental_before("users", buffer, 0);
3073 if (ostatus == 5 || ostatus == 6)
3075 EXEC SQL REPEATED UPDATE users SET login = :login, status = :nstatus,
3076 modtime='now', modby = :who, modwith = :entity, potype='POP',
3077 pop_id = :mid, pmodtime='now', pmodby = :who, pmodwith = :entity
3078 WHERE users_id = :users_id;
3080 if (ingres_errno) return(mr_errcode);
3081 if (sqlca.sqlerrd[2] != 1)
3082 return(MR_INTERNAL);
3083 set_pop_usage(mid, 1);
3084 com_err(whoami, 0, "set login name to %s and pobox to %s", login,
3086 incremental_after("users", buffer, 0);
3088 /* create group list */
3089 if (set_next_object_id("gid", "list", 1))
3091 if (set_next_object_id("list_id", "list", 0))
3093 EXEC SQL REPEATED SELECT value INTO :list_id FROM numvalues
3094 WHERE name='list_id';
3095 if (ingres_errno) return(mr_errcode);
3096 if (sqlca.sqlerrd[2] != 1)
3097 return(MR_INTERNAL);
3098 incremental_clear_before();
3099 EXEC SQL SELECT value INTO :gidval FROM numvalues WHERE name = 'gid';
3100 EXEC SQL REPEATED INSERT INTO list
3101 (name, list_id, active, public, hidden, maillist, grouplist,
3102 gid, desc, acl_type, acl_id,
3103 modtime, modby, modwith)
3104 VALUES (:login, :list_id, 1, 0, 0, 0, 1,
3105 :gidval, 'User Group', 'USER', :users_id,
3106 'now', :who, :entity);
3107 if (ingres_errno) return(mr_errcode);
3108 if (sqlca.sqlerrd[2] != 1)
3109 return(MR_INTERNAL);
3110 sprintf(buffer, "l.list_id = %d", list_id);
3111 incremental_after("list", buffer, 0);
3112 aargv[0] = (char *) list_id;
3114 aargv[2] = (char *) users_id;
3115 incremental_clear_before();
3116 EXEC SQL REPEATED INSERT INTO imembers
3117 (list_id, member_type, member_id, ref_count, direct)
3118 VALUES (:list_id, 'USER', :users_id, 1, 1);
3119 if (ingres_errno) return(mr_errcode);
3120 if (sqlca.sqlerrd[2] != 1)
3121 return(MR_INTERNAL);
3122 incremental_after("members", 0, aargv);
3124 /* decide where to put filesystem */
3127 EXEC SQL DECLARE csr125 CURSOR FOR
3128 SELECT mach_id, trim(nfsphys.dir), nfsphys_id, status, size, allocated
3130 EXEC SQL OPEN csr125;
3132 EXEC SQL FETCH csr125 INTO :mid, :dir, :nid, :flag, :size, :alloc;
3133 if(sqlca.sqlcode != 0) break;
3134 if ((flag & utype) && (size != 0) && (size - alloc > maxsize)) {
3135 maxsize = size - alloc;
3138 directory = strsave(dir);
3143 EXEC SQL CLOSE csr125;
3144 if (ingres_errno) return(mr_errcode);
3146 return(MR_NO_FILESYS);
3148 /* create filesystem */
3149 if (set_next_object_id("filsys_id", "filesys", 0))
3151 incremental_clear_before();
3152 EXEC SQL SELECT value INTO :fsidval FROM numvalues
3153 WHERE numvalues.name='filsys_id';
3154 EXEC SQL REPEATED INSERT INTO filesys
3155 (filsys_id, phys_id, label, type, mach_id, name,
3156 mount, access, comments, owner, owners, createflg,
3157 lockertype, modtime, modby, modwith)
3159 (:fsidval, :pid, :login, 'NFS', :m_id, :directory+'/'+:login,
3160 '/mit/'+:login, 'w', 'User Locker', :users_id, :list_id, 1,
3161 'HOMEDIR', 'now', :who, :entity) ;
3162 if (ingres_errno) return(mr_errcode);
3163 if (sqlca.sqlerrd[2] != 1)
3164 return(MR_INTERNAL);
3165 incremental_after("filesys",
3166 "fs.filsys_id = numvalues.value and numvalues.name = 'filsys_id'",
3168 com_err(whoami, 0, "filesys on mach %d in %s/%s", m_id,
3172 EXEC SQL REPEATED SELECT value INTO :quota FROM numvalues
3173 WHERE name='def_quota';
3174 if (ingres_errno) return(mr_errcode);
3175 if (sqlca.sqlerrd[2] != 1)
3176 return(MR_NO_QUOTA);
3177 incremental_clear_before();
3178 EXEC SQL SELECT value INTO :fsidval FROM numvalues
3179 WHERE numvalues.name = 'filsys_id';
3180 EXEC SQL REPEATED INSERT INTO quota
3181 (entity_id, filsys_id, type, quota, phys_id, modtime, modby, modwith)
3183 (:users_id, :fsidval, 'USER', :quota, :pid, 'now', :who, :entity);
3184 if (ingres_errno) return(mr_errcode);
3185 if (sqlca.sqlerrd[2] != 1)
3186 return(MR_INTERNAL);
3187 EXEC SQL REPEATED UPDATE nfsphys SET allocated=allocated + :quota
3188 WHERE nfsphys_id = filesys.phys_id
3189 AND filesys.filsys_id = numvalues.value
3190 AND numvalues.name = 'filsys_id';
3191 if (ingres_errno) return(mr_errcode);
3192 if (sqlca.sqlerrd[2] != 1)
3193 return(MR_INTERNAL);
3197 sprintf(buffer, "q.entity_id = %d and q.filsys_id = numvalues.value and q.type = 'USER' and numvalues.name = 'filsys_id'", users_id);
3198 incremental_after("quota", buffer, aargv);
3199 com_err(whoami, 0, "quota of %d assigned", quota);
3200 if (ingres_errno) return(mr_errcode);
3202 cache_entry(login, "USER", users_id);
3204 EXEC SQL REPEATED UPDATE tblstats SET updates=updates+1, modtime='now'
3205 WHERE table_name='users';
3206 EXEC SQL REPEATED UPDATE tblstats SET appends=appends+1, modtime='now'
3207 WHERE table_name='list' OR table_name='filesys' OR table_name='quota';
3208 if (ingres_errno) return(mr_errcode);
3214 /** set_pop_usage - incr/decr usage count for pop server in serverhosts talbe
3218 ** delta (will be +/- 1)
3221 ** - incr/decr value field in serverhosts table for pop/mach_id
3225 static int set_pop_usage(id, cnt)
3226 EXEC SQL BEGIN DECLARE SECTION;
3229 EXEC SQL END DECLARE SECTION;
3231 EXEC SQL REPEATED UPDATE serverhosts SET value1 = value1 + :cnt
3232 WHERE serverhosts.service = 'POP' AND serverhosts.mach_id = :id;
3234 if (ingres_errno) return(mr_errcode);
3240 /* Validation Routines */
3242 validate_row(q, argv, v)
3243 register struct query *q;
3245 register struct validate *v;
3247 EXEC SQL BEGIN DECLARE SECTION;
3251 EXEC SQL END DECLARE SECTION;
3253 /* build where clause */
3254 build_qual(v->qual, v->argc, argv, qual);
3257 /** I'm pretty sure we don't need this now */
3258 /* setup ingres variables */
3262 if (log_flags & LOG_VALID)
3263 /* tell the logfile what we're doing */
3264 com_err(whoami, 0, "validating row: %s", qual);
3266 /* look for the record */
3268 * range of rvar is table
3269 * retrieve (rowcount = count(rvar.name where qual))
3271 sprintf(stmt_buf,"SELECT COUNT (*) FROM %s %s WHERE %s",q->rtable,q->rvar,qual);
3272 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3273 EXEC SQL DECLARE csr126 CURSOR FOR stmt;
3274 EXEC SQL OPEN csr126;
3275 EXEC SQL FETCH csr126 USING DESCRIPTOR :SQLDA;
3276 EXEC SQL CLOSE csr126;
3277 rowcount=*(int *)SQLDA->[0].sqldata;
3279 if (ingres_errno) return(mr_errcode);
3280 if (rowcount == 0) return(MR_NO_MATCH);
3281 if (rowcount > 1) return(MR_NOT_UNIQUE);
3285 validate_fields(q, argv, vo, n)
3287 register char *argv[];
3288 register struct valobj *vo;
3291 register int status;
3296 if (log_flags & LOG_VALID)
3297 com_err(whoami, 0, "validating %s in %s: %s",
3298 vo->namefield, vo->table, argv[vo->index]);
3299 status = validate_name(argv, vo);
3303 if (log_flags & LOG_VALID)
3304 com_err(whoami, 0, "validating %s in %s: %s",
3305 vo->idfield, vo->table, argv[vo->index]);
3306 status = validate_id(q, argv, vo);
3310 if (log_flags & LOG_VALID)
3311 com_err(whoami, 0, "validating date: %s", argv[vo->index]);
3312 status = validate_date(argv, vo);
3316 if (log_flags & LOG_VALID)
3317 com_err(whoami, 0, "validating %s type: %s",
3318 vo->table, argv[vo->index]);
3319 status = validate_type(argv, vo);
3323 if (log_flags & LOG_VALID)
3324 com_err(whoami, 0, "validating typed data (%s): %s",
3325 argv[vo->index - 1], argv[vo->index]);
3326 status = validate_typedata(q, argv, vo);
3330 if (log_flags & LOG_VALID)
3331 com_err(whoami, 0, "validating rename %s in %s",
3332 argv[vo->index], vo->table);
3333 status = validate_rename(argv, vo);
3337 if (log_flags & LOG_VALID)
3338 com_err(whoami, 0, "validating chars: %s", argv[vo->index]);
3339 status = validate_chars(argv[vo->index]);
3347 status = lock_table(vo);
3351 if (status != MR_EXISTS) return(status);
3355 if (ingres_errno) return(mr_errcode);
3360 /* validate_chars: verify that there are no illegal characters in
3361 * the string. Legal characters are printing chars other than
3362 * ", *, ?, \, [ and ].
3364 static int illegalchars[] = {
3365 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
3366 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
3367 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
3368 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
3369 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* : - O */
3370 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* P - _ */
3371 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
3372 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
3373 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3374 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3375 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3376 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3377 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3378 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3379 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3380 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3387 if (illegalchars[*s++])
3388 return(MR_BAD_CHAR);
3393 validate_id(q, argv, vo)
3396 register struct valobj *vo;
3398 EXEC SQL BEGIN DECLARE SECTION;
3399 char *name, *tbl, *namefield, *idfield;
3401 EXEC SQL END DECLARE SECTION;
3405 name = argv[vo->index];
3407 namefield = vo->namefield;
3408 idfield = vo->idfield;
3410 if ((!strcmp(tbl, "users") && !strcmp(namefield, "login")) ||
3411 !strcmp(tbl, "machine") ||
3412 !strcmp(tbl, "filesys") ||
3413 !strcmp(tbl, "list") ||
3414 !strcmp(tbl, "cluster") ||
3415 !strcmp(tbl, "strings")) {
3416 if (!strcmp(tbl, "machine"))
3417 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3418 status = name_to_id(name, tbl, &id);
3420 *(int *)argv[vo->index] = id;
3422 } else if (status == MR_NO_MATCH && !strcmp(tbl, "strings") &&
3423 (q->type == APPEND || q->type == UPDATE)) {
3424 EXEC SQL SELECT value INTO :id FROM numvalues
3425 WHERE name = 'strings_id';
3427 EXEC SQL UPDATE numvalues SET value = :id WHERE name = 'string_id';
3428 EXEC SQL INSERT INTO strings (string_id, string) VALUES (:id, :name);
3429 cache_entry(name, "STRING", id);
3430 *(int *)argv[vo->index] = id;
3432 } else if (status == MR_NO_MATCH || status == MR_NOT_UNIQUE)
3438 if (!strcmp(namefield, "uid")) {
3440 * retrieve (id = table.idfield) where table.namefield = int4(name)
3442 sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s.%s = %s",idfield,tbl,tbl,namefield,name);
3443 if (ingres_errno) return(mr_errcode);
3446 * retrieve (id = table.idfield) where table.namefield = name
3448 sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s.%s = '%s'",idfield,tbl,tbl,namefield,name);
3449 if (ingres_errno) return(mr_errcode);
3451 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3452 EXEC SQL DECLARE csr127 CURSOR FOR stmt;
3453 EXEC SQL OPEN csr127;
3455 EXEC SQL FETCH csr127 USING DESCRIPTOR :SQLDA;
3456 if(sqlca.sqlcode == 0) {
3458 EXEC SQL FETCH csr127 USING DESCRIPTOR :SQLDA;
3459 if(sqlca.sqlcode == 0) rowcount++
3461 EXEC SQL CLOSE csr127;
3463 if (rowcount != 1) return(vo->error);
3464 *argv[vo->index] = *SQLDA->sqlvar[0]->sqldata;
3468 validate_name(argv, vo)
3470 register struct valobj *vo;
3472 EXEC SQL BEGIN DECLARE SECTION;
3473 char *name, *tbl, *namefield;
3475 EXEC SQL END DECLARE SECTION;
3478 name = argv[vo->index];
3480 namefield = vo->namefield;
3481 if (!strcmp(tbl, "servers") && !strcmp(namefield, "name")) {
3482 for (c = name; *c; c++)
3487 * retrieve (rowcount = countu(table.namefield
3488 * where table.namefield = name))
3490 sprintf(stmt_buf,"SELECT COUNT (DISTINCT *) FROM %s WHERE %s.%s = '%s'",
3491 tbl,tbl,namefield,name);
3492 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3493 EXEC SQL DECLARE csr128 CURSOR FOR stmt;
3494 EXEC SQL OPEN csr128;
3495 EXEC SQL FETCH csr128 USING DESCRIPTOR :SQLDA;
3496 rowcount=*(int *)SQLDA->sqlvar[0]->sqldata;
3497 EXEC SQL CLOSE csr128;
3499 if (ingres_errno) return(mr_errcode);
3500 return ((rowcount == 1) ? MR_EXISTS : vo->error);
3503 validate_date(argv, vo)
3507 EXEC SQL BEGIN DECLARE SECTION;
3511 EXEC SQL END DECLARE SECTION;
3513 idate = argv[vo->index];
3515 * retrieve (dd = interval("years", date(idate) - date("today")))
3517 EXEC SQL SELECT interval('years',date(:idate)-date('today')) INTO :dd;
3519 if (sqlca.sqlcode != 0 || dd > 5.0) return(MR_DATE);
3524 validate_rename(argv, vo)
3528 EXEC SQL BEGIN DECLARE SECTION;
3529 char *name, *tbl, *namefield, *idfield;
3531 EXEC SQL END DECLARE SECTION;
3535 c = name = argv[vo->index];
3537 if (illegalchars[*c++])
3538 return(MR_BAD_CHAR);
3540 /* minor kludge to upcasify machine names */
3541 if (!strcmp(tbl, "machine"))
3542 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3543 namefield = vo->namefield;
3544 idfield = vo->idfield;
3547 if (!strcmp(argv[vo->index], argv[vo->index - 1]))
3550 * retrieve (id = any(table.namefield where table.namefield = name))
3552 sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s.%s = '%s'",
3553 namefield,tbl,tbl,namefield,name);
3554 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3555 EXEC SQL DECLARE csr129 CURSOR FOR stmt;
3556 EXEC SQL OPEN csr129;
3557 EXEC SQL FETCH csr129 USING DESCRIPTOR :SQLDA;
3558 if(sqlca.sqlcode == 0) id=1; else id=0;
3559 EXEC SQL CLOSE csr129;
3561 if (ingres_errno) return(mr_errcode);
3567 status = name_to_id(name, tbl, &id);
3568 if (status == MR_NO_MATCH || id == *(int *)argv[vo->index - 1])
3575 validate_type(argv, vo)
3577 register struct valobj *vo;
3579 EXEC SQL BEGIN DECLARE SECTION;
3582 EXEC SQL END DECLARE SECTION;
3585 typename = vo->table;
3586 c = value = argv[vo->index];
3588 if (illegalchars[*c])
3589 return(MR_BAD_CHAR);
3592 /* uppercase type fields */
3593 for (c = value; *c; c++) if (islower(*c)) *c = toupper(*c);
3595 EXEC SQL SELECT trans INTO :cdummy FROM alias
3596 WHERE name = :typename AND type='TYPE' AND trans = :value;
3597 if (ingres_errno) return(mr_errcode);
3598 return (sqlca.sqlerrd[2] ? MR_EXISTS : vo->error);
3601 /* validate member or type-specific data field */
3603 validate_typedata(q, argv, vo)
3604 register struct query *q;
3605 register char *argv[];
3606 register struct valobj *vo;
3608 EXEC SQL BEGIN DECLARE SECTION;
3611 char data_type[129];
3613 EXEC SQL END DECLARE SECTION;
3618 /* get named object */
3619 name = argv[vo->index];
3621 /* get field type string (known to be at index-1) */
3622 field_type = argv[vo->index-1];
3624 /* get corresponding data type associated with field type name */
3625 EXEC SQL SELECT trans INTO :data_type FROM alias
3626 WHERE name = :field_type AND type='TYPEDATA';
3627 if (ingres_errno) return(mr_errcode);
3628 if (sqlca.sqlerrd[2] != 1) return(MR_TYPE);
3630 /* now retrieve the record id corresponding to the named object */
3631 if (index(data_type, ' '))
3632 *index(data_type, ' ') = 0;
3633 if (!strcmp(data_type, "user")) {
3635 status = name_to_id(name, data_type, &id);
3636 if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
3638 if (status) return(status);
3639 } else if (!strcmp(data_type, "list")) {
3641 status = name_to_id(name, data_type, &id);
3642 if (status && status == MR_NOT_UNIQUE)
3644 if (status == MR_NO_MATCH) {
3645 /* if idfield is non-zero, then if argv[0] matches the string
3646 * that we're trying to resolve, we should get the value of
3647 * numvalues.[idfield] for the id.
3649 if (vo->idfield && !strcmp(argv[0], argv[vo->index])) {
3650 set_next_object_id(q->validate->object_id, q->rtable, 0);
3652 EXEC SQL REPEATED SELECT value INTO :id FROM numvalues
3654 if (sqlca.sqlerrd[2] != 1) return(MR_LIST);
3657 } else if (status) return(status);
3658 } else if (!strcmp(data_type, "machine")) {
3660 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3661 status = name_to_id(name, data_type, &id);
3662 if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
3664 if (status) return(status);
3665 } else if (!strcmp(data_type, "string")) {
3667 status = name_to_id(name, data_type, &id);
3668 if (status && status == MR_NOT_UNIQUE)
3670 if (status == MR_NO_MATCH) {
3671 if (q->type != APPEND && q->type != UPDATE) return(MR_STRING);
3672 EXEC SQL SELECT value INTO :id FROM numvalues WHERE name = 'strings_id';
3674 EXEC SQL UPDATE numvalues SET value = :id WHERE name = 'strings_id';
3675 EXEC SQL INSERT INTO strings (string_id, string) VALUES (:id, :name);
3676 cache_entry(name, "STRING", id);
3677 } else if (status) return(status);
3678 } else if (!strcmp(data_type, "none")) {
3684 /* now set value in argv */
3685 *(int *)argv[vo->index] = id;
3691 /* Lock the table named by the validation object */
3696 sprintf(stmt_buf,"UPDATE %s SET modtime='now' WHERE %s.%s = 0",
3697 vo->table,vo->table,vo->idfield);
3698 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
3699 if (ingres_errno) return(mr_errcode);
3700 if (sqlca.sqlerrd[2] != 1)
3707 /* Check the database at startup time. For now this just resets the
3708 * inprogress flags that the DCM uses.
3711 sanity_check_database()
3716 /* Dynamic SQL support routines */
3717 MR_SQLDA_T *mr_alloc_SQLDA()
3720 short *null_indicators;
3723 if((it=(MR_SQLDA_T *)malloc(sizeof(MR_SQLDA_T)))==NULL) {
3724 com_err(whoami, MR_NO_MEM, "setting up SQLDA");
3728 if((null_indicators=(short *)calloc(QMAXARGS,sizeof(short)))==NULL) {
3729 com_err(whoami, MR_NO_MEM, "setting up SQLDA null indicators");
3733 for(j=0; j<QMAXARGS; j++) {
3734 if((it->sqlvar[j].sqldata=malloc(sizeof(short)+QMAXARGSIZE))==NULL) {
3735 com_err(whoami, MR_NO_MEM, "setting up SQLDA variables");
3738 it->sqlvar[j].sqllen=QMAXARGSIZE;
3739 it->sqlvar[j].sqlind=null_indicators+j;
3740 null_indicators[j]=0;
3747 /* Use mr_check_SQLDA before OPEN CURSOR or EXECUTE */
3751 if(da->sqld > da->sqln) {
3752 com_err(whoami, MR_INTERNAL,
3753 "Internal arg count error preparing for dynamic query");
3754 return(MR_INTERNAL);
3760 mr_fix_nulls_in_SQLDA(da)
3763 register IISQLVAR *var;
3767 for(j=0, var=da->sqlvar; j<da->sqld; j++, var++) {
3768 switch(var->sqltype) {
3769 case -IISQ_CHA_TYPE:
3773 case -IISQ_INT_TYPE:
3775 intp=(int *)var->sqldata;
3779 } /** I believe that these two are the only types Moira encounters */