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 extern MR_SQLDA_T *SQLDA;
32 EXEC SQL BEGIN DECLARE SECTION;
34 extern char *cdummy, *stmt_buf;
35 EXEC SQL END DECLARE SECTION;
37 /* Specialized Access Routines */
39 /* access_user - verify that client name equals specified login name
41 * - since field validation routines are called first, a users_id is
42 * now in argv[0] instead of the login name.
45 access_user(q, argv, cl)
50 if (cl->users_id != *(int *)argv[0])
58 /* access_login - verify that client name equals specified login name
60 * argv[0...n] contain search info. q->
63 access_login(q, argv, cl)
68 EXEC SQL BEGIN DECLARE SECTION;
71 EXEC SQL END DECLARE SECTION;
73 build_qual(q->qual, q->argc, argv, qual);
74 EXEC SQL SELECT users_id INTO :id FROM users WHERE :qual;
76 if (sqlca.sqlerrd[2] != 1 || id != cl->users_id)
84 /* access_list - check access for most list operations
86 * Inputs: argv[0] - list_id
88 * argv[2] - member ID (only for queries "amtl" and "dmfl")
89 * argv[7] - group IID (only for query "ulis")
92 * - check that client is a member of the access control list
93 * - OR, if the query is add_member_to_list or delete_member_from_list
94 * and the list is public, allow access if client = member
97 access_list(q, argv, cl)
102 EXEC SQL BEGIN DECLARE SECTION;
103 int list_id, acl_id, flags, gid;
105 EXEC SQL END DECLARE SECTION;
107 int client_id, status;
109 list_id = *(int *)argv[0];
110 EXEC SQL SELECT acl_id, acl_type, gid, public
111 INTO :acl_id, :acl_type, :gid, :flags
113 WHERE list_id = :list_id;
115 if (sqlca.sqlerrd[2] != 1)
118 /* parse client structure */
119 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
122 /* if amtl or dmfl and list is public allow client to add or delete self */
123 if (((!strcmp("amtl", q->shortname) && flags) ||
124 (!strcmp("dmfl", q->shortname))) &&
125 (!strcmp("USER", argv[1]))) {
126 if (*(int *)argv[2] == client_id) return(MR_SUCCESS);
127 /* if update_list, don't allow them to change the GID */
128 } else if (!strcmp("ulis", q->shortname)) {
129 if ((!strcmp(argv[7], UNIQUE_GID) && (gid != -1)) ||
130 (strcmp(argv[7], UNIQUE_GID) && (gid != atoi(argv[7]))))
134 /* check for client in access control list */
135 status = find_member(acl_type, acl_id, client_type, client_id, 0);
136 if (!status) return(MR_PERM);
142 /* access_visible_list - allow access to list only if it is not hidden,
143 * or if the client is on the ACL
145 * Inputs: argv[0] - list_id
146 * cl - client identifier
149 access_visible_list(q, argv, cl)
154 EXEC SQL BEGIN DECLARE SECTION;
155 int list_id, acl_id, flags ;
157 EXEC SQL END DECLARE SECTION;
159 int client_id, status;
161 list_id = *(int *)argv[0];
162 EXEC SQL SELECT hidden, acl_id, acl_type
163 INTO :flags, :acl_id, :acl_type
165 WHERE list_id = :list_id;
166 if (sqlca.sqlerrd[2] != 1)
171 /* parse client structure */
172 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
175 /* check for client in access control list */
176 status = find_member(acl_type, acl_id, client_type, client_id, 0);
184 /* access_vis_list_by_name - allow access to list only if it is not hidden,
185 * or if the client is on the ACL
187 * Inputs: argv[0] - list name
188 * cl - client identifier
191 access_vis_list_by_name(q, argv, cl)
196 EXEC SQL BEGIN DECLARE SECTION;
197 int acl_id, flags, rowcount;
198 char acl_type[9], *listname;
199 EXEC SQL END DECLARE SECTION;
201 int client_id, status;
204 EXEC SQL SELECT hidden, acl_id, acl_type INTO :flags, :acl_id, :acl_type
205 FROM list WHERE name = :listname;
207 rowcount=sqlca.sqlerrd[2];
215 /* parse client structure */
216 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
219 /* check for client in access control list */
220 status = find_member(acl_type, acl_id, client_type, client_id, 0);
228 /* access_member - allow user to access member of type "USER" and name matches
229 * username, or to access member of type "LIST" and list is one that user is
230 * on the acl of, or the list is visible.
233 access_member(q, argv, cl)
238 if (!strcmp(argv[0], "LIST") || !strcmp(argv[0], "RLIST"))
239 return(access_visible_list(q, &argv[1], cl));
241 if (!strcmp(argv[0], "USER") || !strcmp(argv[0], "RUSER")) {
242 if (cl->users_id == *(int *)argv[1])
250 /* access_qgli - special access routine for Qualified_get_lists. Allows
251 * access iff argv[0] == "TRUE" and argv[2] == "FALSE".
254 access_qgli(q, argv, cl)
259 if (!strcmp(argv[0], "TRUE") && !strcmp(argv[2], "FALSE"))
265 /* access_service - allow access if user is on ACL of service. Don't
266 * allow access if a wildcard is used.
269 access_service(q, argv, cl)
274 EXEC SQL BEGIN DECLARE SECTION;
276 char *name, acl_type[9];
277 EXEC SQL END DECLARE SECTION;
278 int client_id, status;
279 char *client_type, *c;
282 for(c=name;*c;c++) if(islower(*c)) *c = toupper(*c); /* uppercasify */
283 EXEC SQL SELECT acl_id, acl_type INTO :acl_id, :acl_type FROM servers
285 if (sqlca.sqlerrd[2] > 1)
288 /* parse client structure */
289 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
292 /* check for client in access control list */
293 status = find_member(acl_type, acl_id, client_type, client_id, 0);
294 if (!status) return(MR_PERM);
300 /* access_filesys - verify that client is owner or on owners list of filesystem
304 access_filesys(q, argv, cl)
309 EXEC SQL BEGIN DECLARE SECTION;
310 int users_id, list_id;
312 EXEC SQL END DECLARE SECTION;
313 int status, client_id;
317 EXEC SQL SELECT owner, owners INTO :users_id, :list_id FROM filesys
320 if (sqlca.sqlerrd[2] != 1)
322 if (users_id == cl->users_id)
324 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
326 status = find_member("LIST", list_id, client_type, client_id, 0);
337 /* Setup routine for add_user
339 * Inputs: argv[0] - login
344 * - if argv[1] == UNIQUE_UID then set argv[1] = next(uid)
345 * - if argv[0] == UNIQUE_LOGIN then set argv[0] = "#<uid>"
348 setup_ausr(q, argv, cl)
350 register char *argv[];
354 EXEC SQL BEGIN DECLARE SECTION;
356 EXEC SQL END DECLARE SECTION;
358 if (!strcmp(q->shortname, "uusr") || !strcmp(q->shortname, "uuac"))
362 if (!strcmp(argv[row], UNIQUE_UID) || atoi(argv[row]) == -1) {
363 if (set_next_object_id("uid", "users", 1))
364 return(MR_INGRES_ERR);
365 EXEC SQL SELECT value INTO :nuid FROM numvalues WHERE name = 'uid';
366 if (sqlca.sqlerrd[2] != 1)
368 sprintf(argv[row], "%d", nuid);
371 if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[row]) == -1) {
372 sprintf(argv[0], "#%s", argv[row]);
379 /* setup_dusr - verify that the user is no longer being referenced
380 * and may safely be deleted.
383 int setup_dusr(q, argv)
387 EXEC SQL BEGIN DECLARE SECTION;
389 EXEC SQL END DECLARE SECTION;
391 id = *(int *)argv[0];
393 /*? Can this get wildcarded users? What happens then?! */
394 /*? How does the REPEATED keyword work? */
395 /* For now, only allow users to be deleted if their status is 0 */
396 EXEC SQL REPEATED SELECT status INTO :flag FROM users
398 if (flag != 0 && flag != 4)
401 EXEC SQL REPEATED DELETE FROM quota WHERE entity_id = :id AND type = 'USER';
402 EXEC SQL REPEATED DELETE FROM krbmap WHERE users_id = :id;
403 EXEC SQL REPEATED SELECT member_id INTO :idummy FROM imembers
404 WHERE member_id = :id AND member_type = 'USER';
405 if (sqlca.sqlerrd[2] > 0)
407 EXEC SQL REPEATED SELECT label INTO :cdummy FROM filesys WHERE owner = :id;
408 if (sqlca.sqlerrd[2]> 0)
410 EXEC SQL REPEATED SELECT name INTO :cdummy FROM list
411 WHERE acl_id = :id AND acl_type = 'USER';
412 if (sqlca.sqlerrd[2] > 0)
414 EXEC SQL REPEATED SELECT name INTO :cdummy FROM servers
415 WHERE acl_id = :id AND acl_type = 'USER';
416 if (sqlca.sqlerrd[2] > 0)
418 EXEC SQL REPEATED SELECT acl_id INTO :idummy FROM hostaccess
419 WHERE acl_d = :id AND acl_type = 'USER';
420 if (sqlca.sqlerrd[2] > 0)
428 /* setup_spop: verify that there is already a valid POP machine_id in the
429 * pop_id field. Also take care of keeping track of the post office usage.
431 int setup_spop(q, argv)
435 EXEC SQL BEGIN DECLARE SECTION;
438 EXEC SQL END DECLARE SECTION;
440 id = *(int *)argv[0];
441 EXEC SQL REPEATED SELECT potype, pop_id INTO :type, :mid FROM users
442 WHERE users_id = :id;
443 if(sqlca.sqlerrd[2] = 0)
445 EXEC SQL REPEATED SELECT mach_id INTO :mid FROM machine
446 WHERE mach_id = :mid;
447 if (sqlca.sqlerrd[2] = 0)
449 if (strcmp(strtrim(type), "POP"))
450 set_pop_usage(mid, 1);
455 /* setup_dpob: Take care of keeping track of the post office usage.
457 int setup_dpob(q, argv)
461 EXEC SQL BEGIN DECLARE SECTION;
464 EXEC SQL END DECLARE SECTION;
466 user = *(int *)argv[0];
467 EXEC SQL REPEATED SELECT potype, pop_id INTO :type, :id FROM users
468 WHERE users_id = :user;
469 if (ingres_errno) return(mr_errcode);
471 if (!strcmp(strtrim(type), "POP"))
472 set_pop_usage(id, -1);
477 /* setup_dmac - verify that the machine is no longer being referenced
478 * and may safely be deleted.
481 int setup_dmac(q, argv)
485 EXEC SQL BEGIN DECLARE SECTION;
487 EXEC SQL END DECLARE SECTION;
489 id = *(int *)argv[0];
490 EXEC SQL REPEATED SELECT login INTO :cdummy FROM users
491 WHERE potype='POP' AND pop_id = :id;
492 if (sqlca.sqlerrd[2] > 0)
494 EXEC SQL REPEATED SELECT mach_id INTO :idummy FROM serverhosts
496 if (sqlca.sqlerrd[2] > 0)
498 EXEC SQL REPEATED SELECT mach_id INTO :idummy FROM nfsphys
500 if (sqlca.sqlerrd[2] > 0)
502 EXEC SQL REPEATED SELECT mach_id INTO :idummy FROM hostaccess
504 if (sqlca.sqlerrd[2] > 0)
506 EXEC SQL REPEATED SELECT mach_id INTO :idummy FROM printcap
508 if (sqlca.sqlerrd[2] > 0)
510 EXEC SQL REPEATED SELECT quotaserver INTO :idummy FROM printcap
511 WHERE quotaserver = :id;
512 if (sqlca.sqlerrd[2] > 0)
514 EXEC SQL REPEATED SELECT mach_id INTO :idummy FROM palladium
516 if (sqlca.sqlerrd[2] > 0)
519 EXEC SQL REPEATED DELETE FROM mcmap WHERE mach_id = :id;
520 if (ingres_errno) return(mr_errcode);
525 /* setup_dclu - verify that the cluster is no longer being referenced
526 * and may safely be deleted.
529 int setup_dclu(q, argv)
533 EXEC SQL BEGIN DECLARE SECTION;
535 EXEC SQL END DECLARE SECTION;
537 id = *(int *)argv[0];
538 EXEC SQL REPEATED SELECT mach_id INTO :idummy FROM mcmap
540 if (sqlca.sqlerrd[2] > 0)
542 EXEC SQL REPEATED SELECT clu_id INTO :idummy FROM svc
544 if (sqlca.sqlerrd[2] > 0)
552 /* setup_alis - if argv[5] is non-zero and argv[6] is UNIQUE_ID, then allocate
553 * a new gid and put it in argv[6]. Otherwise if argv[6] is UNIQUE_ID but
554 * argv[5] is not, then remember that UNIQUE_ID is being stored by putting
555 * a -1 there. Remember that this is also used for ulis, with the indexes
559 int setup_alis(q, argv)
563 EXEC SQL BEGIN DECLARE SECTION;
565 EXEC SQL END DECLARE SECTION;
569 if (!strcmp(q->shortname, "alis"))
571 else if (!strcmp(q->shortname, "ulis"))
574 if (!strcmp(argv[idx], UNIQUE_GID) || atoi(argv[idx]) == -1) {
575 if (atoi(argv[idx - 1])) {
576 if (set_next_object_id("gid", "list", 1))
577 return(MR_INGRES_ERR);
578 EXEC SQL REPEATED SELECT value INTO :ngid FROM numvalues
580 if (ingres_errno) return(mr_errcode);
581 sprintf(argv[idx], "%d", ngid);
583 strcpy(argv[idx], "-1");
591 /* setup_dlist - verify that the list is no longer being referenced
592 * and may safely be deleted.
595 int setup_dlis(q, argv)
599 EXEC SQL BEGIN DECLARE SECTION;
601 EXEC SQL END DECLARE SECTION;
603 id = *(int *)argv[0];
604 EXEC SQL REPEATED SELECT member_id INTO :idummy FROM imembers
605 WHERE member_id = :id AND member_type='LIST';
606 if (sqlca.sqlerrd[2] > 0)
608 EXEC SQL REPEATED SELECT member_id INTO :idummy FROM imembers
610 if (sqlca.sqlerrd[2] > 0)
612 EXEC SQL REPEATED SELECT label INTO :cdummy FROM filesys
614 if (sqlca.sqlerrd[2] > 0)
616 EXEC SQL REPEATED SELECT tag INTO :cdummy FROM capacls
618 if (sqlca.sqlerrd[2] > 0)
620 EXEC SQL REPEATED SELECT name INTO :cdummy FROM list
621 WHERE acl_id = :id AND acl_type='LIST' AND list_id = :id;
622 if (sqlca.sqlerrd[2] > 0)
624 EXEC SQL REPEATED SELECT name INTO :cdummy FROM servers
625 WHERE acl_id = :id AND acl_type='LIST';
626 if (sqlca.sqlerrd[2] > 0)
628 EXEC SQL REPEATED SELECT entity_id INTO :idummy FROM quota
629 WHERE entity_id = :id AND type='GROUP';
630 if (sqlca.sqlerrd[2] > 0)
632 EXEC SQL REPEATED SELECT acl_id INTO :idummy FROM hostaccess
633 WHERE acl_id = :id AND acl_type='LIST';
634 if (sqlca.sqlerrd[2] > 0)
636 EXEC SQL REPEATED SELECT class INTO :cdummy FROM zephyr z
637 WHERE zephyr.xmt_type = 'LIST' AND z.xmt_id = :id
638 OR z.sub_type = 'LIST' AND z.sub_id = :id
639 OR z.iws_type = 'LIST' AND z.iws_id = :id
640 OR z.iui_type = 'LIST' AND z.iui_id = :id;
641 if (sqlca.sqlerrd[2] > 0)
649 /* setup_dsin - verify that the service is no longer being referenced
650 * and may safely be deleted.
653 int setup_dsin(q, argv)
657 EXEC SQL BEGIN DECLARE SECTION;
659 EXEC SQL END DECLARE SECTION;
663 for(c=name;*c;c++) if(islower(*c)) *c = toupper(*c);
664 EXEC SQL REPEATED SELECT service INTO :cdummy FROM serverhosts
665 WHERE service = :name;
666 if (sqlca.sqlerrd[2] > 0)
668 EXEC SQL REPEATED SELECT inprogress INTO :idummy FROM servers
670 if (sqlca.sqlerrd[2] > 0)
678 /* setup_dshi - verify that the service-host is no longer being referenced
679 * and may safely be deleted.
682 int setup_dshi(q, argv)
686 EXEC SQL BEGIN DECLARE SECTION;
689 EXEC SQL END DECLARE SECTION;
692 for(c=name;*c;c++) if(islower(*c)) *c = toupper(*c); /* to uppercase */
693 id = *(int *)argv[1];
694 EXEC SQL REPEATED SELECT inprogress INTO :idummy FROM serverhosts
695 WHERE service = :name AND mach_id = :id;
696 if (sqlca.sqlerrd[2] > 0)
705 ** setup_add_filesys - verify existance of referenced file systems
717 ** * extract directory prefix from name
718 ** * verify mach_id/dir in nfsphys
719 ** * verify access in {r, w, R, W}
721 ** Side effect: sets variable var_phys_id to the ID of the physical
722 ** filesystem (nfsphys_id for NFS, 0 for RVD)
725 ** MR_NFS - specified directory not exported
726 ** MR_FILESYS_ACCESS - invalid filesys access
730 EXEC SQL BEGIN DECLARE SECTION;
731 static int var_phys_id;
732 EXEC SQL END DECLARE SECTION;
740 EXEC SQL BEGIN DECLARE SECTION;
742 char ftype[32], *access;
743 EXEC SQL END DECLARE SECTION;
746 mach_id = *(int *)argv[2];
751 sprintf(ftype, "fs_access_%s", type);
752 EXEC SQL SELECT trans INTO :cdummy FROM alias
753 WHERE name = :ftype AND type = 'TYPE' and trans = :access;
754 if (ingres_errno) return(mr_errcode);
755 if (sqlca.sqlerrd[2] == 0) return(MR_FILESYS_ACCESS);
757 if (!strcmp(type, "NFS"))
758 return (check_nfs(mach_id, name, access));
764 /* Verify the arguments, depending on the FStype. Also, if this is an
765 * NFS filesystem, then update any quotas for that filesystem to reflect
769 setup_ufil(q, argv, cl)
776 EXEC SQL BEGIN DECLARE SECTION;
778 char *entity, ftype[32], *access;
780 EXEC SQL END DECLARE SECTION;
783 mach_id = *(int *)argv[3];
786 fid = *(int *)argv[0];
790 sprintf(ftype, "fs_access_%s", type);
791 EXEC SQL SELECT trans INTO :cdummy FROM alias
792 WHERE name = :ftype AND type='TYPE' AND trans = :access;
793 if (ingres_errno) return(mr_errcode);
794 if (sqlca.sqlerrd[2] == 0) return(MR_FILESYS_ACCESS);
796 if (!strcmp(type, "NFS")) {
797 status = check_nfs(mach_id, name, access);
798 EXEC SQL UPDATE quota SET phys_id = :var_phys_id
799 WHERE filsys_id = :fid;
800 if (ingres_errno) return(mr_errcode);
802 } else if (!strcmp(type, "AFS")) {
804 EXEC SQL REPEATED DELETE FROM quota
805 WHERE type = 'ANY' AND filsys_id = :fid;
806 EXEC SQL SELECT SUM (quota) INTO :total FROM quota
807 WHERE filsys_id = :fid AND phys_id != 0;
808 if (ingres_errno) return(mr_errcode);
811 * append quota (quota = total, filsys_id = fid,
812 * phys_id = 0, entity_id = 0, type = "ANY",
813 * modtime = "now", modby = who, modwith = entity)
815 EXEC SQL INSERT INTO quota (quota, filsys_id, phys_id, entity_id,
816 type, modtime, modby, modwith)
817 VALUES (:total, :fid, 0, 0,
818 'ANY', 'now', :who, :entity) ;
819 if (ingres_errno) return(mr_errcode);
822 EXEC SQL UPDATE quota SET phys_id = 0 WHERE filsys_id = :fid;
823 if (ingres_errno) return(mr_errcode);
829 /* Find the NFS physical partition that the named directory is on.
830 * This is done by comparing the dir against the mount point of the
831 * partition. To make sure we get the correct match when there is
832 * more than one, we sort the query in reverse order by dir name.
835 check_nfs(mach_id, name, access)
836 EXEC SQL BEGIN DECLARE SECTION;
838 EXEC SQL END DECLARE SECTION;
842 EXEC SQL BEGIN DECLARE SECTION;
844 EXEC SQL END DECLARE SECTION;
851 EXEC SQL DECLARE csr101 CURSOR FOR
852 SELECT nfsphys_id, TRIM (dir) FROM nfsphys
853 WHERE mach_id = :mach_id
855 EXEC SQL OPEN csr101;
857 EXEC SQL FETCH csr101 INTO :var_phys_id, :dir;
858 if(sqlca.sqlcode != 0) break;
862 if (*cp1++ != *cp2) break;
870 EXEC SQL CLOSE csr101;
877 /* setup_dfil: free any quota records and fsgroup info associated with
878 * a filesystem when it is deleted. Also adjust the allocation numbers.
881 setup_dfil(q, argv, cl)
886 EXEC SQL BEGIN DECLARE SECTION;
888 EXEC SQL END DECLARE SECTION;
890 id = *(int *)argv[0];
891 EXEC SQL REPEATED SELECT SUM (quota) INTO :total FROM quota
892 WHERE filsys_id = :id;
893 EXEC SQL REPEATED UPDATE nfsphys SET allocated = allocated - :total
894 WHERE nfsphys_id = filesys.phys_id AND filesys.filsys_id = :id;
895 /** Is SQL smart enough to do the PRODUCT above? */
896 /** Or should we code it using another SELECT? */
898 EXEC SQL REPEATED DELETE FROM quota WHERE filsys_id = :id;
899 EXEC SQL REPEATED DELETE FROM fsgroup WHERE filsys_id = :id;
900 EXEC SQL REPEATED DELETE FROM fsgroup WHERE group_id = :id;
901 if (ingres_errno) return(mr_errcode);
906 /* setup_dnfp: check to see that the nfs physical partition does not have
907 * any filesystems assigned to it before allowing it to be deleted.
910 setup_dnfp(q, argv, cl)
915 EXEC SQL BEGIN DECLARE SECTION;
918 EXEC SQL END DECLARE SECTION;
920 id = *(int *)argv[0];
922 EXEC SQL REPEATED SELECT label INTO :cdummy FROM filesys fs, nfsphys np
923 WHERE fs.mach_id = :id AND fs.phys_id = np.nfsphys_id
924 AND np.mach_id = :id AND np.dir = :dir;
925 if (sqlca.sqlerrd[2] > 0)
933 /* setup_dqot: Remove allocation from nfsphys before deleting quota.
934 * argv[0] = filsys_id
935 * argv[1] = type if "update_quota" or "delete_quota"
936 * argv[2 or 1] = users_id or list_id
939 setup_dqot(q, argv, cl)
944 EXEC SQL BEGIN DECLARE SECTION;
947 EXEC SQL END DECLARE SECTION;
949 fs = *(int *)argv[0];
950 if (!strcmp(q->name, "update_quota") || !strcmp(q->name, "delete_quota")) {
952 id = *(int *)argv[2];
955 id = *(int *)argv[1];
958 EXEC SQL REPEATED SELECT quota INTO :quota FROM quota
959 WHERE type = :qtype AND entity_id = :id AND filsys_id = :fs;
960 EXEC SQL REPEATED UPDATE nfsphys
961 SET allocated = nfsphys.allocated - :quota
962 WHERE nfsphys_id = filesys.physid AND filesys.filsys_id = :fs;
964 if (ingres_errno) return(mr_errcode);
969 /* setup_sshi: don't exclusive lock the machine table during
970 * set_server_host_internal.
973 setup_sshi(q, argv, cl)
979 EXEC SQL set lockmode session where readlock = system;
984 /* setup add_kerberos_user_mapping: add the string to the string
985 * table if necessary.
988 setup_akum(q, argv, cl)
993 EXEC SQL BEGIN DECLARE SECTION;
996 EXEC SQL END DECLARE SECTION;
999 if (name_to_id(name, "STRING", &id) != MR_SUCCESS) {
1000 if (q->type != APPEND) return(MR_STRING);
1001 EXEC SQL SELECT value INTO :id FROM numvalues
1002 WHERE name = 'strings_id';
1004 EXEC SQL UPDATE numvalues SET value = :id
1005 WHERE name = 'strings_id';
1006 EXEC SQL INSERT INTO strings (string_id, string) VALUES (:id, :name);
1007 cache_entry(name, "STRING", id);
1009 if (ingres_errno) return(mr_errcode);
1010 *(int *)argv[1] = id;
1016 /* FOLLOWUP ROUTINES */
1018 /* generic set_modtime routine. This takes the table name from the query,
1019 * and will update the modtime, modby, and modwho fields in the entry in
1020 * the table whose name field matches argv[0].
1023 set_modtime(q, argv, cl)
1028 char *name, *entity, *table;
1031 entity = cl->entity;
1032 who = cl->client_id;
1036 sprintf(stmt_buf,"UPDATE %s SET modtime = 'now', modby = %d, \
1037 modwith = '%s' WHERE %s.name = '%s'",table,who,entity,table,name);
1038 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
1043 /* generic set_modtime_by_id routine. This takes the table name from
1044 * the query, and the id name from the validate record,
1045 * and will update the modtime, modby, and modwho fields in the entry in
1046 * the table whose id matches argv[0].
1049 set_modtime_by_id(q, argv, cl)
1054 char *entity, *table, *id_name;
1057 entity = cl->entity;
1058 who = cl->client_id;
1060 id_name = q->validate->object_id;
1062 id = *(int *)argv[0];
1063 sprintf(stmt_buf,"UPDATE %s SET modtime = 'now', modby = %d, \
1064 modwith = '%s' WHERE %s.%s = %d",table,who,entity,table,id_name,id);
1065 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
1070 /* Sets the finger modtime on a user record. The users_id will be in argv[0].
1073 set_finger_modtime(q, argv, cl)
1078 EXEC SQL BEGIN DECLARE SECTION;
1081 EXEC SQL END DECLARE SECTION;
1083 entity = cl->entity;
1084 who = cl->client_id;
1085 users_id = *(int *)argv[0];
1087 EXEC SQL UPDATE users SET fmodtime='now', fmodby = :who, fmodwith = :entity
1088 WHERE users.users_id = :users_id;
1094 /* Sets the pobox modtime on a user record. The users_id will be in argv[0].
1097 set_pobox_modtime(q, argv, cl)
1102 EXEC SQL BEGIN DECLARE SECTION;
1105 EXEC SQL END DECLARE SECTION;
1107 entity = cl->entity;
1108 who = cl->client_id;
1109 users_id = *(int *)argv[0];
1111 EXEC SQL UPDATE users SET pmodtime='now', pmodby = :who, pmodwith = entity
1112 WHERE users.users_id = users_id;
1118 /* Like set_modtime, but uppercases the name first.
1121 set_uppercase_modtime(q, argv, cl)
1126 char *name, *entity, *table;
1129 entity = cl->entity;
1130 who = cl->client_id;
1133 for(c=name;*c;c++) if(islower(*c)) *c = toupper(*c); /** INGRES has an uppercase() functiuons, but it's not portable. */
1135 sprintf(stmt_buf,"UPDATE %s SET modtime = 'now', modby = %d, \
1136 modwith = '%s' WHERE %s.name = '%s'",table,who,entity,table,name);
1137 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
1143 /* Sets the modtime on the machine whose mach_id is in argv[0]. This routine
1144 * is necessary for add_machine_to_cluster becuase the table that query
1145 * operates on is "mcm", not "machine".
1148 set_mach_modtime_by_id(q, argv, cl)
1153 EXEC SQL BEGIN DECLARE SECTION;
1156 EXEC SQL END DECLARE SECTION;
1158 entity = cl->entity;
1159 who = cl->client_id;
1160 id = *(int *)argv[0];
1161 EXEC SQL UPDATE machine SET modtime='now', modby = :who, modwith = :entity
1162 WHERE machine.mach_id = :id;
1168 /* Sets the modtime on the cluster whose mach_id is in argv[0]. This routine
1169 * is necessary for add_cluster_data and delete_cluster_data becuase the
1170 * table that query operates on is "svc", not "cluster".
1173 set_cluster_modtime_by_id(q, argv, cl)
1178 EXEC SQL BEGIN DECLARE SECTION;
1181 EXEC SQL END DECLARE SECTION;
1183 entity = cl->entity;
1184 who = cl->client_id;
1186 id = *(int *)argv[0];
1187 EXEC SQL UPDATE cluster SET modtime='now', modby = :who, modwith = :entity
1188 WHERE cluster.clu_id = :id;
1193 /* sets the modtime on the serverhost where the service name is in argv[0]
1194 * and the mach_id is in argv[1].
1197 set_serverhost_modtime(q, argv, cl)
1202 EXEC SQL BEGIN DECLARE SECTION;
1203 char *entity, *serv;
1205 EXEC SQL END DECLARE SECTION;
1207 entity = cl->entity;
1208 who = cl->client_id;
1211 id = *(int *)argv[1];
1212 EXEC SQL UPDATE serverhosts
1213 SET modtime = 'now', modby = :who, modwith = :entity
1214 WHERE service = :serv AND mach_id = :id;
1219 /* sets the modtime on the nfsphys where the mach_id is in argv[0] and the
1220 * directory name is in argv[1].
1223 set_nfsphys_modtime(q, argv, cl)
1228 EXEC SQL BEGIN DECLARE SECTION;
1231 EXEC SQL END DECLARE SECTION;
1233 entity = cl->entity;
1234 who = cl->client_id;
1236 id = *(int *)argv[0];
1238 EXEC SQL UPDATE nfsphys SET modtime = 'now', modby = :who, modwith = :entity
1239 WHERE dir = :dir AND mach_id = :id;
1244 /* sets the modtime on a filesystem, where argv[0] contains the filesys
1248 set_filesys_modtime(q, argv, cl)
1253 EXEC SQL BEGIN DECLARE SECTION;
1254 char *label, *entity;
1256 EXEC SQL END DECLARE SECTION;
1258 entity = cl->entity;
1259 who = cl->client_id;
1262 if (!strcmp(q->shortname, "ufil"))
1265 EXEC SQL UPDATE filesys SET modtime = 'now', modby = :who,
1266 modwith = :entity, phys_id = :var_phys_id
1267 WHERE label = :label;
1272 /* sets the modtime on a zephyr class, where argv[0] contains the class
1276 set_zephyr_modtime(q, argv, cl)
1281 EXEC SQL BEGIN DECLARE SECTION;
1282 char *class, *entity;
1284 EXEC SQL END DECLARE SECTION;
1286 entity = cl->entity;
1287 who = cl->client_id;
1291 EXEC SQL UPDATE zephyr SET modtime = 'now', modby = :who, modwith = :entity
1292 WHERE class = :class;
1298 /* fixes the modby field. This will be the second to last thing in the
1299 * argv, the argv length is determined from the query structure. It is
1300 * passed as a pointer to an integer. This will either turn it into a
1301 * username, or # + the users_id.
1303 followup_fix_modby(q, sq, v, action, actarg, cl)
1305 register struct save_queue *sq;
1307 register int (*action)();
1308 register int actarg;
1312 char **argv, *malloc();
1316 while (sq_get_data(sq, &argv)) {
1319 status = id_to_name(id, "USER", &argv[i]);
1321 status = id_to_name(-id, "STRING", &argv[i]);
1322 if (status && status != MR_NO_MATCH)
1324 (*action)(q->vcnt, argv, actarg);
1325 for (j = 0; j < q->vcnt; j++)
1334 /* After retrieving a user account, fix the modby field and signature.
1335 * The modby field is the second to last thing in the
1336 * argv, the argv length is determined from the query structure. It is
1337 * passed as a pointer to an integer. This will either turn it into a
1338 * username, or # + the users_id. Only "gua*" queries have a signature,
1339 * these are ones with U_END return values. "gub*" queries also use this
1340 * routine but don't have a signature.
1342 followup_guax(q, sq, v, action, actarg, cl)
1344 register struct save_queue *sq;
1346 register int (*action)();
1347 register int actarg;
1351 char **argv, *malloc();
1353 char sigbuf[256], *rawsig, *kname;
1359 while (sq_get_data(sq, &argv)) {
1362 status = id_to_name(id, "USER", &argv[i]);
1364 status = id_to_name(-id, "STRING", &argv[i]);
1365 if (status && status != MR_NO_MATCH)
1368 if (q->vcnt == U_END) {
1369 com_err(whoami, 0, "compressing signature");
1370 rawsig = argv[U_SIGNATURE];
1371 bcopy(&rawsig[0], &id, sizeof(int));
1373 status = id_to_name(id, "STRING", &kname);
1374 bcopy(&rawsig[4], &si.timestamp, sizeof(int));
1375 si.timestamp = ntohl(si.timestamp);
1376 si.SigInfoVersion = 0; /* XXXXX this isn't used */
1377 kname_parse(si.pname, si.pinst, si.prealm, kname);
1378 si.rawsig = (unsigned char *)&rawsig[8];
1379 GDSS_Recompose(&si, sigbuf);
1380 argv[U_SIGNATURE] = strsave(sigbuf);
1383 (*action)(q->vcnt, argv, actarg);
1384 for (j = 0; j < q->vcnt; j++)
1394 ** followup_ausr - add finger and pobox entries, set_user_modtime
1397 ** argv[0] - login (add_user)
1398 ** argv[3] - last name
1399 ** argv[4] - first name
1400 ** argv[5] - middle name
1404 followup_ausr(q, argv, cl)
1409 EXEC SQL BEGIN DECLARE SECTION;
1410 int who, status, sigwho, id;
1411 char *login, *entity, *src, *dst, *name;
1413 EXEC SQL END DECLARE SECTION;
1415 char databuf[32], *kname_unparse();
1416 EXEC SQL BEGIN DECLARE SECTION;
1418 EXEC SQL END DECLARE SECTION;
1422 /* build fullname */
1423 if (strlen(argv[4]) && strlen(argv[5]))
1424 sprintf(fullname, "%s %s %s", argv[4], argv[5], argv[3]);
1425 else if (strlen(argv[4]))
1426 sprintf(fullname, "%s %s", argv[4], argv[3]);
1428 sprintf(fullname, "%s", argv[3]);
1431 sprintf(databuf, "%s:%s", argv[U_NAME], argv[U_MITID]);
1432 /* skip bytes for timestamp & kname */
1433 si.rawsig = (unsigned char *)&rawsig[8];
1434 status = GDSS_Verify(databuf, strlen(databuf), argv[U_SIGNATURE], &si);
1436 name = kname_unparse(si.pname, si.pinst, si.prealm);
1437 status = name_to_id(name, "STRING", &sigwho);
1438 if (status == MR_NO_MATCH) {
1439 EXEC SQL REPEATED SELECT value INTO :sigwho FROM numvalues
1440 WHERE name = 'strings_id';
1442 EXEC SQL REPEATED UPDATE numvalues SET value = :sigwho
1443 WHERE name = 'strings_id';
1444 EXEC SQL INSERT INTO strings (string_id, string)
1445 VALUES (:sigwho, :name);
1448 sigwho = htonl(sigwho);
1449 bcopy(&sigwho, &rawsig[0], sizeof(int));
1450 si.timestamp = htonl(si.timestamp);
1451 bcopy(&si.timestamp, &rawsig[4], sizeof(int));
1457 who = cl->client_id;
1458 entity = cl->entity;
1460 /* create finger entry, pobox & set modtime on user */
1462 EXEC SQL REPEATED UPDATE users
1463 SET modtime='now', modby=:who, modwith = :entity,
1464 fullname = :fullname, mit_affil = mit_year,
1465 signature = :rawsig,
1466 fmodtime='now', fmodby = :who, fmodwith = :entity,
1467 potype='NONE', pmodtime='now', pmodby = :who, pmodwith = :entity
1468 WHERE login = :login;
1470 EXEC SQL REPEATED UPDATE users
1471 SET modtime='now', modby=:who, modwith = :entity,
1472 fullname = :fullname, mit_affil = mit_year,
1473 fmodtime='now', fmodby = :who, fmodwith = :entity,
1474 potype='NONE', pmodtime='now', pmodby = :who, pmodwith = :entity
1475 WHERE login = :login;
1482 /* followup_gpob: fixes argv[2] based on the IDs currently there and the
1483 * type in argv[1]. Then completes the upcall to the user.
1485 * argv[2] is of the form "123:234" where the first integer is the machine
1486 * ID if it is a pop box, and the second is the string ID if it is an SMTP
1487 * box. argv[1] should be "POP", "SMTP", or "NONE". Boxes of type NONE
1491 followup_gpob(q, sq, v, action, actarg, cl)
1492 register struct query *q;
1493 register struct save_queue *sq;
1494 register struct validate *v;
1495 register int (*action)();
1499 char **argv, *index();
1501 int mid, sid, status;
1504 while (sq_get_data(sq, &argv)) {
1505 mr_trim_args(2, argv);
1507 p = index(argv[2], ':');
1509 mid = atoi(argv[2]);
1512 if (!strcmp(ptype, "POP")) {
1513 status = id_to_name(mid, "MACHINE", &argv[2]);
1514 if (status == MR_NO_MATCH)
1516 } else if (!strcmp(ptype, "SMTP")) {
1517 status = id_to_name(sid, "STRING", &argv[2]);
1518 if (status == MR_NO_MATCH)
1520 } else /* ptype == "NONE" */ {
1523 if (status) return(status);
1525 if (!strcmp(q->shortname, "gpob")) {
1526 sid = atoi(argv[4]);
1528 status = id_to_name(sid, "USER", &argv[4]);
1530 status = id_to_name(-sid, "STRING", &argv[4]);
1532 if (status && status != MR_NO_MATCH) return(status);
1534 (*action)(q->vcnt, argv, actarg);
1536 /* free saved data */
1544 return (MR_SUCCESS);
1548 /* followup_glin: fix the ace_name in argv[8]. argv[7] will contain the
1549 * ace_type: "LIST", "USER", or "NONE". Decode the id in argv[8] into the
1550 * proper name based on the type, and repace that string in the argv.
1551 * Also fixes the modby field by called followup_fix_modby.
1554 followup_glin(q, sq, v, action, actarg, cl)
1555 register struct query *q;
1556 register struct save_queue *sq;
1557 register struct validate *v;
1558 register int (*action)();
1562 char **argv, *malloc(), *realloc(), *type;
1563 int id, i, idx, status;
1566 if (!strcmp(q->shortname, "gsin"))
1569 while (sq_get_data(sq, &argv)) {
1570 mr_trim_args(q->vcnt, argv);
1572 id = atoi(argv[i = q->vcnt - 2]);
1574 status = id_to_name(id, "USER", &argv[i]);
1576 status = id_to_name(-id, "STRING", &argv[i]);
1577 if (status && status != MR_NO_MATCH)
1580 id = atoi(argv[idx]);
1581 type = argv[idx - 1];
1583 if (!strcmp(type, "LIST")) {
1584 status = id_to_name(id, "LIST", &argv[idx]);
1585 } else if (!strcmp(type, "USER")) {
1586 status = id_to_name(id, "USER", &argv[idx]);
1587 } else if (!strcmp(type, "KERBEROS")) {
1588 status = id_to_name(id, "STRING", &argv[idx]);
1589 } else if (!strcmp(type, "NONE")) {
1592 argv[idx] = strsave("NONE");
1596 argv[idx] = strsave("???");
1598 if (status && status != MR_NO_MATCH)
1601 if (!strcmp(q->shortname, "glin") && atoi(argv[6]) == -1) {
1602 argv[6] = realloc(argv[6], strlen(UNIQUE_GID) + 1);
1603 strcpy(argv[6], UNIQUE_GID);
1607 (*action)(q->vcnt, argv, actarg);
1609 /* free saved data */
1610 for (i = 0; i < q->vcnt; i++)
1616 return (MR_SUCCESS);
1620 /* followup_gqot: Fix the entity name, directory name & modby fields
1621 * argv[0] = filsys_id
1623 * argv[2] = entity_id
1624 * argv[3] = ascii(quota)
1627 followup_gqot(q, sq, v, action, actarg, cl)
1629 register struct save_queue *sq;
1631 register int (*action)();
1632 register int actarg;
1636 char **argv, *malloc();
1637 EXEC SQL BEGIN DECLARE SECTION;
1640 EXEC SQL END DECLARE SECTION;
1643 if (!strcmp(q->name, "get_quota") ||
1644 !strcmp(q->name, "get_quota_by_filesys"))
1648 while (sq_get_data(sq, &argv)) {
1650 switch (argv[1][0]) {
1652 status = id_to_name(atoi(argv[2]), "USER", &argv[2]);
1656 status = id_to_name(atoi(argv[2]), "LIST", &argv[2]);
1660 argv[2] = strsave("system:anyuser");
1664 argv[2] = malloc(8);
1665 sprintf(argv[2], "%d", id);
1668 id = atoi(argv[idx]);
1670 argv[idx] = malloc(256);
1674 EXEC SQL REPEATED SELECT name INTO :name FROM filesys
1675 WHERE label = :label;
1677 EXEC SQL REPEATED SELECT dir INTO :name FROM nfsphys
1678 WHERE nfsphys_id = :id;
1680 if (sqlca.sqlerrd[2] != 1) {
1681 sprintf(argv[idx], "#%d", id);
1684 id = atoi(argv[idx+3]);
1686 status = id_to_name(id, "USER", &argv[idx+3]);
1688 status = id_to_name(-id, "STRING", &argv[idx+3]);
1689 if (status && status != MR_NO_MATCH)
1691 (*action)(q->vcnt, argv, actarg);
1692 for (j = 0; j < q->vcnt; j++)
1701 /* followup_aqot: Add allocation to nfsphys after creating quota.
1702 * argv[0] = filsys_id
1703 * argv[1] = type if "add_quota" or "update_quota"
1705 * argv[3 or 2] = ascii(quota)
1708 followup_aqot(q, argv, cl)
1713 EXEC SQL BEGIN DECLARE SECTION;
1714 int quota, id, fs, who;
1715 char *entity, *qtype;
1716 EXEC SQL END DECLARE SECTION;
1718 fs = *(int *)argv[0];
1719 if (!strcmp(q->name, "add_quota") || !strcmp(q->name, "update_quota")) {
1721 id = *(int *)argv[2];
1722 quota = atoi(argv[3]);
1725 id = *(int *)argv[1];
1726 quota = atoi(argv[2]);
1728 who = cl->client_id;
1729 entity = cl->entity;
1731 EXEC SQL REPEATED UPDATE quota
1732 SET modtime = 'now', modby = :who, modwith = :entity
1733 WHERE filsys_id = :fs and type = :qtype and entity_id = :id;
1734 EXEC SQL REPEATED UPDATE nfsphys
1735 SET allocated = allocated + :quota
1736 WHERE nfsphys_id = filesys.phys_id AND filesys.filsys_id = :fs;
1737 if (ingres_errno) return(mr_errcode);
1742 followup_gpce(q, sq, v, action, actarg, cl)
1744 register struct save_queue *sq;
1746 register int (*action)();
1747 register int actarg;
1751 char **argv, *malloc();
1755 while (sq_get_data(sq, &argv)) {
1756 id = atoi(argv[PCAP_QSERVER]);
1757 status = id_to_name(id, "MACHINE", &argv[PCAP_QSERVER]);
1758 if (status) return (status);
1761 status = id_to_name(id, "USER", &argv[i]);
1763 status = id_to_name(-id, "STRING", &argv[i]);
1764 if (status && status != MR_NO_MATCH)
1766 (*action)(q->vcnt, argv, actarg);
1767 for (j = 0; j < q->vcnt; j++)
1779 followup_gzcl(q, sq, v, action, actarg, cl)
1780 register struct query *q;
1781 register struct save_queue *sq;
1782 register struct validate *v;
1783 register int (*action)();
1790 while (sq_get_data(sq, &argv)) {
1791 mr_trim_args(q->vcnt, argv);
1793 id = atoi(argv[i = q->vcnt - 2]);
1795 status = id_to_name(id, "USER", &argv[i]);
1797 status = id_to_name(-id, "STRING", &argv[i]);
1798 if (status && status != MR_NO_MATCH)
1801 for (i = 1; i < 8; i+=2) {
1802 id = atoi(argv[i+1]);
1803 if (!strcmp(argv[i], "LIST")) {
1804 status = id_to_name(id, "LIST", &argv[i+1]);
1805 } else if (!strcmp(argv[i], "USER")) {
1806 status = id_to_name(id, "USER", &argv[i+1]);
1807 } else if (!strcmp(argv[i], "KERBEROS")) {
1808 status = id_to_name(id, "STRING", &argv[i+1]);
1809 } else if (!strcmp(argv[i], "NONE")) {
1812 argv[i+1] = strsave("NONE");
1816 argv[i+1] = strsave("???");
1818 if (status && status != MR_NO_MATCH)
1823 (*action)(q->vcnt, argv, actarg);
1825 /* free saved data */
1826 for (i = 0; i < q->vcnt; i++)
1838 followup_gsha(q, sq, v, action, actarg, cl)
1839 register struct query *q;
1840 register struct save_queue *sq;
1841 register struct validate *v;
1842 register int (*action)();
1849 while (sq_get_data(sq, &argv)) {
1850 mr_trim_args(q->vcnt, argv);
1854 status = id_to_name(id, "USER", &argv[4]);
1856 status = id_to_name(-id, "STRING", &argv[4]);
1857 if (status && status != MR_NO_MATCH)
1861 if (!strcmp(argv[1], "LIST")) {
1862 status = id_to_name(id, "LIST", &argv[2]);
1863 } else if (!strcmp(argv[1], "USER")) {
1864 status = id_to_name(id, "USER", &argv[2]);
1865 } else if (!strcmp(argv[1], "KERBEROS")) {
1866 status = id_to_name(id, "STRING", &argv[2]);
1867 } else if (!strcmp(argv[1], "NONE")) {
1870 argv[2] = strsave("NONE");
1874 argv[2] = strsave("???");
1876 if (status && status != MR_NO_MATCH)
1880 (*action)(q->vcnt, argv, actarg);
1882 /* free saved data */
1883 for (i = 0; i < q->vcnt; i++)
1893 /* Special query routines */
1895 /* set_pobox - this does all of the real work.
1896 * argv = user_id, type, box
1897 * if type is POP, then box should be a machine, and its ID should be put in
1898 * pop_id. If type is SMTP, then box should be a string and its ID should
1899 * be put in box_id. If type is NONE, then box doesn't matter.
1902 int set_pobox(q, argv, cl)
1907 EXEC SQL BEGIN DECLARE SECTION;
1909 char *box, potype[9];
1910 EXEC SQL END DECLARE SECTION;
1914 user = *(int *)argv[0];
1916 EXEC SQL REPEATED SELECT pop_id, potype INTO :id, :potype FROM users
1917 WHERE users_id = :user;
1918 if (ingres_errno) return(mr_errcode);
1919 if (!strcmp(strtrim(potype), "POP"))
1920 set_pop_usage(id, -1);
1922 if (!strcmp(argv[1], "POP")) {
1923 status = name_to_id(box, "MACHINE", &id);
1924 if (status == MR_NO_MATCH)
1928 EXEC SQL REPEATED UPDATE users SET potype = 'POP', pop_id = :id
1929 WHERE users_id = :user;
1930 set_pop_usage(id, 1);
1931 } else if (!strcmp(argv[1], "SMTP")) {
1932 if (index(box, '/') || index(box, '|'))
1933 return(MR_BAD_CHAR);
1934 status = name_to_id(box, "STRING", &id);
1935 if (status == MR_NO_MATCH) {
1936 EXEC SQL REPEATED SELECT value INTO :id FROM numvalues
1937 WHERE name='strings_id';
1939 EXEC SQL REPEATED UPDATE numvalues SET value = :id
1940 WHERE name='strings_id';
1941 EXEC SQL INSERT INTO strings (string_id, string)
1945 EXEC SQL REPEATED UPDATE users SET potype='SMTP', box_id = :id
1946 WHERE users_id = :user;
1947 } else /* argv[1] == "NONE" */ {
1948 EXEC SQL REPEATED UPDATE users SET potype='NONE'
1949 WHERE users_id = :user;
1952 set_pobox_modtime(q, argv, cl);
1953 EXEC SQL REPEATED UPDATE tblstats SET updates = updates+1, modtime='now'
1954 WHERE tblstats.table_name='users';
1955 if (ingres_errno) return(mr_errcode);
1960 /* get_list_info: passed a wildcard list name, returns lots of stuff about
1961 * each list. This is tricky: first build a queue of all requested
1962 * data. Rest of processing consists of fixing gid, ace_name, and modby.
1965 get_list_info(q, aargv, cl, action, actarg)
1966 register struct query *q;
1969 register int (*action)();
1972 char *argv[13], *malloc(), *realloc();
1973 EXEC SQL BEGIN DECLARE SECTION;
1974 char *name, acl_type[9], listname[33], active[5], public[5], hidden[5];
1975 char maillist[5], grouplist[5], gid_str[6], acl_name[256], desc[256];
1976 char modtime[27], modby[256], modwith[9];
1977 int id, rowcount, acl_id, hid, modby_id;
1978 EXEC SQL END DECLARE SECTION;
1979 int returned, status;
1980 struct save_queue *sq, *sq_create();
1982 returned = rowcount = 0;
1986 EXEC SQL DECLARE csr102 CURSOR FOR SELECT list_id FROM list
1988 EXEC SQL OPEN csr102;
1991 EXEC SQL FETCH csr102 INTO :id;
1992 if(sqlca.sqlcode!=0) break;
1993 sq_save_data(sq, id);
1996 EXEC SQL CLOSE csr102;
1998 if (ingres_errno) return(mr_errcode);
2000 return(MR_NO_MATCH);
2002 argv[0] = listname; argv[1] = active; argv[2] = public; argv[3] = hidden;
2003 argv[4] = maillist; argv[5] = grouplist; argv[6] = gid_str;
2004 argv[7] = acl_type; argv[9] = desc; argv[10] = modtime; argv[12] = modwith;
2006 while (sq_get_data(sq, &id)) {
2011 * repeat retrieve (listname = l.#name, active = text(l.#active),
2012 * public = text(l.#public), hidden = text(l.#hidden),
2013 * hid = l.#hidden, maillist = text(l.#maillist),
2014 * group = text(l.#group), gid = text(l.#gid),
2015 * acl_type = trim(l.#acl_type), acl_id = l.#acl_id,
2016 * desc = l.#desc, modtime = l.#modtime, modby_id = l.#modby,
2017 * modwith =l.#modwith)
2018 * where l.list_id = :id
2020 EXEC SQL REPEATED SELECT name, text(active), text(public),
2021 text(hidden), hidden, text(maillist), text(grouplist), text(gid),
2022 trim(acl_type), acl_id, desc, modtime, modby, modwith
2023 INTO :listname, :active, :public, :hidden, :hid, :maillist,
2024 :grouplist, :gid_str, :acl_type, :acl_id, :desc,
2025 :modtime, :modby_id, :modwith
2026 FROM list WHERE list_id = :id;
2028 if (ingres_errno) return(mr_errcode);
2030 if (atoi(gid_str) == -1)
2031 argv[6] = UNIQUE_GID;
2033 argv[8] = malloc(0);
2034 if (!strcmp(acl_type, "LIST")) {
2035 status = id_to_name(acl_id, "LIST", &argv[8]);
2036 } else if (!strcmp(acl_type, "USER")) {
2037 status = id_to_name(acl_id, "USER", &argv[8]);
2038 } else if (!strcmp(acl_type, "KERBEROS")) {
2039 status = id_to_name(acl_id, "STRING", &argv[8]);
2040 } else if (!strcmp(acl_type, "NONE")) {
2043 argv[8] = strsave("NONE");
2047 argv[8] = strsave("???");
2049 if (status && status != MR_NO_MATCH) return(status);
2051 argv[11] = malloc(0);
2053 status = id_to_name(modby_id, "USER", &argv[11]);
2055 status = id_to_name(-modby_id, "STRING", &argv[11]);
2056 if (status && status != MR_NO_MATCH) return(status);
2058 mr_trim_args(q->vcnt, argv);
2060 (*action)(q->vcnt, argv, actarg);
2066 if (ingres_errno) return(mr_errcode);
2067 return (MR_SUCCESS);
2071 /* Add_member_to_list: do list flattening as we go! MAXLISTDEPTH is
2072 * how many different ancestors a member is allowed to have.
2075 #define MAXLISTDEPTH 1024
2077 int add_member_to_list(q, argv, cl)
2082 EXEC SQL BEGIN DECLARE SECTION;
2083 int id, lid, mid, error, who, ref;
2084 char *mtype, dtype[9], *entity;
2085 EXEC SQL END DECLARE SECTION;
2086 int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a;
2087 int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d;
2089 char *dtypes[MAXLISTDEPTH];
2090 char *iargv[3], *buf;
2092 lid = *(int *)argv[0];
2094 mid = *(int *)argv[2];
2095 /* if the member is already a direct member of the list, punt */
2097 * repeat retrieve (exists = any(m.list_id where m.list_id=@lid and
2098 * m.member_id = :mid and m.member_type = :mtype
2099 * and m.direct = 1))
2101 EXEC SQL REPEATED SELECT list_id INTO :idummy FROM imembers
2102 WHERE list_id = :lid AND member_id = :mid
2103 AND member_type = :mtype AND direct = 1;
2104 if (sqlca.sqlerrd[2] > 0)
2106 if (!strcasecmp(mtype, "STRING")) {
2108 status = id_to_name(mid, "STRING", &buf);
2109 if (status) return(status);
2110 if (index(buf, '/') || index(buf, '|')) {
2112 return(MR_BAD_CHAR);
2120 EXEC SQL DECLARE csr103 CURSOR FOR
2121 SELECT list_id, ref_count FROM imembers
2122 WHERE member_id = :lid AND member_type='LIST';
2123 EXEC SQL OPEN csr103;
2125 EXEC SQL FETCH csr103 INTO :id, :ref;
2126 if(sqlca.sqlcode != 0) break;
2128 ancestors[acount++] = id;
2129 if (acount >= MAXLISTDEPTH) break;
2131 EXEC SQL CLOSE csr103;
2132 if (ingres_errno) return(mr_errcode);
2133 if (acount >= MAXLISTDEPTH) {
2134 return(MR_INTERNAL);
2136 descendants[0] = mid;
2141 if (!strcmp(mtype, "LIST")) {
2142 EXEC SQL DECLARE csr104 CURSOR FOR
2143 SELECT member_id, member_type, ref_count
2145 WHERE list_id = :mid;
2146 EXEC SQL OPEN csr104;
2148 EXEC SQL FETCH csr104 INTO :id, :dtype, :ref;
2149 if(sqlca.sqlcode != 0) break;
2152 dtypes[dcount] = "LIST";
2155 dtypes[dcount] = "USER";
2158 dtypes[dcount] = "STRING";
2161 dtypes[dcount] = "KERBEROS";
2168 descendants[dcount++] = id;
2169 if (dcount >= MAXLISTDEPTH) {
2174 EXEC SQL CLOSE csr104;
2175 if (ingres_errno) return(mr_errcode);
2177 return(MR_INTERNAL);
2179 for (a = 0; a < acount; a++) {
2181 for (d = 0; d < dcount; d++) {
2182 mid = descendants[d];
2184 if (mid == lid && !strcmp(mtype, "LIST")) {
2185 return(MR_LISTLOOP);
2188 * repeat retrieve (exists = any(m.ref_count where m.list_id = :lid
2189 * and m.member_id = :mid
2190 * and m.member_type = :mtype))
2192 EXEC SQL REPEATED SELECT ref_count INTO :idummy FROM imembers
2193 WHERE list_id = :lid AND member_id = :mid
2194 AND m.member_type = :mtype;
2195 ref = aref[a] * dref[d];
2196 if (sqlca.sqlerrd[2] > 0) {
2197 if (a == 0 && d == 0) {
2198 EXEC SQL UPDATE imembers
2199 SET ref_count = ref_count+ref, direct=1
2200 WHERE list_id = :lid AND member_id = :mid
2201 AND member_type = :mtype;
2203 EXEC SQL UPDATE imembers
2204 SET ref_count = ref_count+ref
2205 WHERE list_id = :lid AND member_id = :mid
2206 AND member_type = :mtype;
2209 incremental_clear_before();
2210 if (a == 0 && d == 0) {
2211 EXEC SQL INSERT INTO imembers
2212 (list_id, member_id, direct, member_type, ref_count)
2213 VALUES (:lid, :mid, 1, :mtype, 1);
2215 EXEC SQL INSERT INTO imembers
2216 (list_id, member_id, member_type, ref_count)
2217 VALUES (:lid, :mid, :mtype, 1);
2219 iargv[0] = (char *)lid;
2221 iargv[2] = (char *)mid;
2222 incremental_after("members", 0, iargv);
2226 lid = *(int *)argv[0];
2227 entity = cl->entity;
2228 who = cl->client_id;
2229 EXEC SQL REPEATED UPDATE list
2230 SET modtime='now', modby = :who, modwith = :entity
2231 WHERE list_id = :lid;
2232 if (ingres_errno) return(mr_errcode);
2237 /* Delete_member_from_list: do list flattening as we go!
2240 int delete_member_from_list(q, argv, cl)
2245 EXEC SQL BEGIN DECLARE SECTION;
2246 int id, lid, mid, cnt, error, who, ref;
2247 char *mtype, dtype[9], *entity;
2248 EXEC SQL END DECLARE SECTION;
2249 int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a;
2250 int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d;
2251 char *dtypes[MAXLISTDEPTH];
2254 lid = *(int *)argv[0];
2256 mid = *(int *)argv[2];
2257 /* if the member is not a direct member of the list, punt */
2259 * repeat retrieve (exists = any(m.list_id where m.list_id=@lid and
2260 * m.member_id = :mid and m.member_type = :mtype
2261 * and m.direct = 1))
2263 EXEC SQL REPEATED SELECT list_id INTO :idummy FROM imembers
2264 WHERE list_id = :lid AND member_id = :mid
2265 AND member_type = :mtype AND direct = 1;
2266 if (ingres_errno) return(mr_errcode);
2267 if (sqlca.sqlcode == 100)
2268 return(MR_NO_MATCH);
2272 EXEC SQL DECLARE csr105 CURSOR FOR
2273 SELECT list_id, ref_count FROM imembers
2274 WHERE member_id = :lid AND member_type = 'LIST';
2275 EXEC SQL OPEN csr105;
2277 EXEC SQL FETCH csr105 INTO :id, :ref;
2278 if(sqlca.sqlcode!=0) break;
2280 ancestors[acount++] = id;
2281 if (acount >= MAXLISTDEPTH) break;
2283 EXEC SQL CLOSE csr105;
2286 if (acount >= MAXLISTDEPTH)
2287 return(MR_INTERNAL);
2288 descendants[0] = mid;
2293 if (!strcmp(mtype, "LIST")) {
2294 EXEC SQL DECLARE csr106 CURSOR FOR
2295 SELECT member_id, member_type, ref_count FROM imembers
2296 WHERE list_id = :mid;
2297 EXEC SQL OPEN csr106;
2299 EXEC SQL FETCH csr106 INTO :id, :dtype, :ref;
2300 if(sqlca.sqlcode!=0) break;
2303 dtypes[dcount] = "LIST";
2306 dtypes[dcount] = "USER";
2309 dtypes[dcount] = "STRING";
2312 dtypes[dcount] = "KERBEROS";
2319 descendants[dcount++] = id;
2320 if (dcount >= MAXLISTDEPTH) break;
2322 EXEC SQL CLOSE csr106;
2326 return(MR_INTERNAL);
2328 for (a = 0; a < acount; a++) {
2330 for (d = 0; d < dcount; d++) {
2331 mid = descendants[d];
2333 if (mid == lid && !strcmp(mtype, "LIST")) {
2334 return(MR_LISTLOOP);
2336 EXEC SQL REPEATED SELECT ref_count INTO :cnt FROM imembers
2337 WHERE list_id = :lid AND member_id = :mid AND member_type = :mtype;
2338 ref = aref[a] * dref[d];
2340 iargv[0] = (char *)lid;
2342 iargv[2] = (char *)mid;
2343 incremental_before("members", 0, iargv);
2344 EXEC SQL DELETE FROM imembers
2345 WHERE list_id = :lid AND member_id = :mid
2346 AND member_type= :mtype;
2347 incremental_clear_after();
2348 } else if (a == 0 && d == 0) {
2349 EXEC SQL UPDATE imembers
2350 SET ref_count = refcount - :ref, direct = 0
2351 WHERE list_id = :lid AND member_id = :mid
2352 AND member_type = :mtype;
2354 EXEC SQL UPDATE imembers
2355 SET ref_count=refcount-:ref
2356 WHERE list_id = :lid AND member_id = :mid
2357 AND member_type = :mtype;
2361 lid = *(int *)argv[0];
2362 entity = cl->entity;
2363 who = cl->client_id;
2364 EXEC SQL UPDATE list SET modtime = 'now', modby = :who, modwith = :entity
2365 WHERE list_id = :lid;
2366 if (ingres_errno) return(mr_errcode);
2371 /* get_ace_use - given a type and a name, return a type and a name.
2372 * The ace_type is one of "LIST", "USER", "RLIST", or "RUSER" in argv[0],
2373 * and argv[1] will contain the ID of the entity in question. The R*
2374 * types mean to recursively look at every containing list, not just
2375 * when the object in question is a direct member. On return, the
2376 * usage type will be one of LIST, SERVICE, FILESYS, QUOTA, QUERY, or ZEPHYR.
2379 int get_ace_use(q, argv, cl, action, actarg)
2387 EXEC SQL BEGIN DECLARE SECTION;
2389 int aid, listid, id;
2390 EXEC SQL END DECLARE SECTION;
2391 struct save_queue *sq, *sq_create();
2394 aid = *(int *)argv[1];
2395 if (!strcmp(atype, "LIST") || !strcmp(atype, "USER") ||
2396 !strcmp(atype, "KERBEROS")) {
2397 return(get_ace_internal(atype, aid, action, actarg));
2401 if (!strcmp(atype, "RLIST")) {
2402 sq_save_data(sq, aid);
2403 /* get all the list_id's of containing lists */
2404 EXEC SQL DECLARE csr107 CURSOR FOR
2405 SELECT list_id FROM imembers
2406 WHERE member_type='LIST' AND member_id = :aid;
2407 EXEC SQL OPEN csr107;
2409 EXEC SQL FETCH csr107 INTO :listid;
2410 if(sqlca.sqlcode != 0) break;
2411 sq_save_unique_data(sq, listid);
2413 EXEC SQL CLOSE csr107;
2414 /* now process each one */
2415 while (sq_get_data(sq, &id)) {
2416 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2421 if (!strcmp(atype, "RUSER")) {
2422 EXEC SQL DECLARE csr108 CURSOR FOR
2423 SELECT list_id FROM imembers
2424 WHERE member_type='USER' AND member_id = :aid;
2425 EXEC SQL OPEN csr108;
2427 EXEC SQL FETCH csr108 INTO :listid;
2428 if(sqlca.sqlcode != 0) break;
2429 sq_save_data(sq, listid);
2431 EXEC SQL CLOSE csr108;
2432 /* now process each one */
2433 while (sq_get_data(sq, &id)) {
2434 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2437 if (get_ace_internal("USER", aid, action, actarg) == MR_SUCCESS)
2441 if (!strcmp(atype, "RKERBERO")) {
2442 EXEC SQL DECLARE csr109 CURSOR FOR
2443 SELECT list_id FROM imembers
2444 WHERE member_type='KERBEROS' AND member_id = :aid;
2445 EXEC SQL OPEN csr109;
2447 EXEC SQL FETCH csr109 INTO :listid;
2448 if(sqlca.sqlcode != 0) break;
2449 sq_save_data(sq, listid);
2451 EXEC SQL CLOSE csr109;
2452 /* now process each one */
2453 while (sq_get_data(sq, &id)) {
2454 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2457 if (get_ace_internal("KERBEROS", aid, action, actarg) == MR_SUCCESS)
2462 if (ingres_errno) return(mr_errcode);
2463 if (!found) return(MR_NO_MATCH);
2468 /* This looks up a single list or user for ace use. atype must be "USER"
2469 * or "LIST", and aid is the ID of the corresponding object. This is used
2470 * by get_ace_use above.
2473 get_ace_internal(atype, aid, action, actarg)
2474 EXEC SQL BEGIN DECLARE SECTION;
2477 EXEC SQL END DECLARE SECTION;
2483 EXEC SQL BEGIN DECLARE SECTION;
2485 EXEC SQL END DECLARE SECTION;
2488 if (!strcmp(atype, "LIST")) {
2489 rargv[0] = "FILESYS";
2490 EXEC SQL DECLARE csr110 CURSOR FOR
2491 SELECT label FROM filesys
2492 WHERE owners = :aid;
2493 EXEC SQL OPEN csr110;
2495 EXEC SQL FETCH csr110 INTO :name;
2496 if(sqlca.sqlcode != 0) break;
2497 (*action)(2, rargv, actarg);
2500 EXEC SQL CLOSE csr110;
2503 EXEC SQL DECLARE csr111 CURSOR FOR
2504 SELECT capability FROM capacls
2505 WHERE list_id = :aid ;
2506 EXEC SQL OPEN csr111;
2508 EXEC SQL FETCH csr111 INTO :name ;
2509 if(sqlca.sqlcode != 0) break;
2510 (*action)(2, rargv, actarg);
2513 EXEC SQL CLOSE csr111;
2514 } else if (!strcmp(atype, "USER")) {
2515 rargv[0] = "FILESYS";
2516 EXEC SQL DECLARE csr112 CURSOR FOR
2517 SELECT label FROM filesys
2519 EXEC SQL OPEN csr112;
2521 EXEC SQL FETCH csr112 INTO :name ;
2522 if(sqlca.sqlcode != 0) break;
2523 (*action)(2, rargv, actarg);
2526 EXEC SQL CLOSE csr112;
2530 EXEC SQL DECLARE csr113 CURSOR FOR
2531 SELECT name FROM list
2532 WHERE acl_type = :atype AND acl_id = :aid;
2533 EXEC SQL OPEN csr113;
2535 EXEC SQL FETCH csr113 INTO :name;
2536 if(sqlca.sqlcode != 0) break;
2537 (*action)(2, rargv, actarg);
2540 EXEC SQL CLOSE csr113;
2542 rargv[0] = "SERVICE";
2543 EXEC SQL DECLARE csr114 CURSOR FOR
2544 SELECT name FROM servers
2545 WHERE acl_type = :atype AND acl_id = :aid;
2546 EXEC SQL OPEN csr114;
2548 EXEC SQL FETCH csr114 INTO :name;
2549 if(sqlca.sqlcode != 0) break;
2550 (*action)(2, rargv, actarg);
2553 EXEC SQL CLOSE csr114;
2555 rargv[0] = "HOSTACCESS";
2556 EXEC SQL DECLARE csr115 CURSOR FOR
2557 SELECT name FROM machine, hostaccess
2558 WHERE mach_id = hostaccess.mach_id AND hostaccess.acl_type = :atype
2559 AND hostaccess.acl_id = :aid;
2560 EXEC SQL OPEN csr115;
2562 EXEC SQL FETCH csr115 INTO :name;
2563 if(sqlca.sqlcode != 0) break;
2564 (*action)(2, rargv, actarg);
2567 EXEC SQL CLOSE csr115;
2569 rargv[0] = "ZEPHYR";
2570 EXEC SQL DECLARE csr116 CURSOR FOR
2571 SELECT class FROM zephyr
2572 WHERE zephyr.xmt_type = :atype AND zephyr.xmt_id = :aid
2573 OR zephyr.sub_type = :atype AND zephyr.sub_id = :aid
2574 OR zephyr.iws_type = :atype AND zephyr.iws_id = :aid
2575 OR zephyr.iui_type = :atype AND zephyr.iui_id = :aid;
2576 EXEC SQL OPEN csr116;
2578 EXEC SQL FETCH csr116 INTO :name;
2579 if(sqlca.sqlcode != 0) break;
2580 (*action)(2, rargv, actarg);
2583 EXEC SQL CLOSE csr116;
2585 if (!found) return(MR_NO_MATCH);
2590 /* get_lists_of_member - given a type and a name, return the name and flags
2591 * of all of the lists of the given member. The member_type is one of
2592 * "LIST", "USER", "STRING", "RLIST", "RUSER", or "RSTRING" in argv[0],
2593 * and argv[1] will contain the ID of the entity in question. The R*
2594 * types mean to recursively look at every containing list, not just
2595 * when the object in question is a direct member.
2598 int get_lists_of_member(q, argv, cl, action, actarg)
2605 int found = 0, direct = 1;
2607 EXEC SQL BEGIN DECLARE SECTION;
2609 int aid, listid, id;
2610 char name[33], active[5], public[5], hidden[5], maillist[5], grouplist[5];
2611 EXEC SQL END DECLARE SECTION;
2614 aid = *(int *)argv[1];
2615 if (!strcmp(atype, "RLIST")) {
2619 if (!strcmp(atype, "RUSER")) {
2623 if (!strcmp(atype, "RSTRING")) {
2627 if (!strcmp(atype, "RKERBEROS")) {
2636 rargv[4] = maillist;
2637 rargv[5] = grouplist;
2640 * repeat retrieve (name = list.#name, active = text(list.#active),
2641 * public = text(list.#public), hidden = text(list.#hidden),
2642 * maillist = text(list.#maillist), group = text(list.#group))
2643 * where list.list_id = m.list_id and m.direct = 1 and
2644 * m.member_type = :atype and m.member_id = :aid
2646 EXEC SQL DECLARE csr117a CURSOR FOR
2647 SELECT name, text(active), text(public), text(hidden),
2648 text(maillist), text(grouplist)
2649 FROM list l, imembers m
2650 WHERE l.list_id = m.list_id AND m.direct = 1
2651 AND m.member_type = :atype AND m.member_id = :aid;
2652 EXEC SQL OPEN csr117a;
2654 EXEC SQL FETCH csr117a
2655 INTO :name, :active, :public, :hidden, :maillist, :grouplist;
2656 if(sqlca.sqlcode != 0) break;
2657 (*action)(6, rargv, actarg);
2660 EXEC SQL CLOSE csr117a;
2662 EXEC SQL DECLARE csr117b CURSOR FOR
2663 SELECT name, text(active), text(public), text(hidden),
2664 text(maillist), text(grouplist)
2665 FROM list l, imembers m
2666 WHERE l.list_id = m.list_id
2667 AND m.member_type = :atype AND m.member_id = :aid;
2668 EXEC SQL OPEN csr117b;
2670 EXEC SQL FETCH csr117b
2671 INTO :name, :active, :public, :hidden, :maillist, :grouplist;
2672 if(sqlca.sqlcode != 0) break;
2673 (*action)(6, rargv, actarg);
2676 EXEC SQL CLOSE csr117b;
2679 if (ingres_errno) return(mr_errcode);
2680 if (!found) return(MR_NO_MATCH);
2685 /* qualified_get_lists: passed "TRUE", "FALSE", or "DONTCARE" for each of
2686 * the five flags associated with each list. It will return the name of
2687 * each list that meets the quailifications. It does this by building a
2688 * where clause based on the arguments, then doing a retrieve.
2691 static char *lflags[5] = { "active", "public", "hidden", "maillist", "group" };
2693 int qualified_get_lists(q, argv, cl, action, actarg)
2700 return(qualified_get(q, argv, action, actarg, "l.list_id != 0",
2701 "l", "name", lflags));
2705 /** get_members_of_list - optimized query for retrieval of list members
2708 ** argv[0] - list_id
2711 ** - retrieve USER members, then LIST members, then STRING members
2714 get_members_of_list(q, argv, cl, action, actarg)
2721 EXEC SQL BEGIN DECLARE SECTION;
2722 int list_id, member_id;
2723 char member_name[129], member_type[9];
2724 EXEC SQL END DECLARE SECTION;
2727 struct save_queue *sq;
2729 list_id = *(int *)argv[0];
2733 EXEC SQL DECLARE csr118 CURSOR FOR
2734 SELECT member_type, member_id FROM imembers
2735 WHERE list_id = :list_id AND direct=1;
2736 EXEC SQL OPEN csr118;
2738 EXEC SQL FETCH csr118 INTO :member_type, :member_id;
2739 if (sqlca.sqlcode != 0) break;
2742 sq_save_data(sq, (member_type[0] << 24) | (member_id & 0xffffff));
2744 EXEC SQL CLOSE csr118;
2746 if (members <= 49) {
2747 targv[1] = malloc(0);
2748 while (sq_remove_data(sq, &member_id)) {
2749 switch (member_id >> 24) {
2752 id_to_name(member_id & 0xffffff, "USER", &targv[1]);
2753 (*action)(2, targv, actarg);
2757 id_to_name(member_id & 0xffffff, "LIST", &targv[1]);
2758 (*action)(2, targv, actarg);
2761 targv[0] = "STRING";
2762 id_to_name(member_id & 0xffffff, "STRING", &targv[1]);
2763 (*action)(2, targv, actarg);
2766 targv[0] = "KERBEROS";
2767 id_to_name(member_id & 0xffffff, "STRING", &targv[1]);
2768 (*action)(2, targv, actarg);
2772 return(MR_INTERNAL);
2781 targv[1] = member_name;
2783 EXEC SQL DECLARE csr119 CURSOR FOR
2784 SELECT users.login FROM users, imembers
2785 WHERE imembers.list_id = :list_id AND imembers.member_type = 'USER'
2786 AND imembers.member_id = users.users_id AND imembers.direct=1
2788 EXEC SQL OPEN csr119;
2790 EXEC SQL FETCH csr119 INTO :member_name;
2791 if(sqlca.sqlcode != 0) break;
2792 (*action)(2, targv, actarg);
2794 EXEC SQL CLOSE csr119;
2795 if (ingres_errno) return(mr_errcode);
2798 EXEC SQL DECLARE csr120 CURSOR FOR
2799 SELECT list.name FROM list, imembers
2800 WHERE imembers.list_id = :list_id AND imembers.member_type='LIST'
2801 AND imembers.member_id = list.list_id AND imembers.direct=1
2803 EXEC SQL OPEN csr120;
2805 EXEC SQL FETCH csr120 INTO :member_name;
2806 if(sqlca.sqlcode != 0) break;
2807 (*action)(2, targv, actarg);
2809 EXEC SQL CLOSE csr120;
2810 if (ingres_errno) return(mr_errcode);
2812 targv[0] = "STRING";
2813 EXEC SQL DECLARE csr121 CURSOR FOR
2814 SELECT strings.string FROM strings, imembers
2815 WHERE imembers.list_id = :listid AND imembers.member_type='STRING'
2816 AND imembers.member_id = strings.string_id AND imembers.direct=1
2818 EXEC SQL OPEN csr121;
2820 EXEC SQL FETCH csr121 INTO :member_name;
2821 if(sqlca.sqlcode != 0) break;
2822 (*action)(2, targv, actarg);
2824 EXEC SQL CLOSE csr121;
2825 if (ingres_errno) return(mr_errcode);
2827 targv[0] = "KERBEROS";
2828 EXEC SQL DECLARE csr122 CURSOR FOR
2829 SELECT strings.string FROM strings, imembers
2830 WHERE imembers.list_id = :listid AND imembers.member_type='KERBEROS'
2831 AND imembers.member_id = strings.string_id AND imembers.direct=1
2833 EXEC SQL OPEN csr122;
2835 EXEC SQL FETCH csr122 INTO :member_name;
2836 if(sqlca.sqlcode != 0) break;
2837 (*action)(2, targv, actarg);
2839 EXEC SQL CLOSE csr122;
2840 if (ingres_errno) return(mr_errcode);
2846 /* count_members_of_list: this is a simple query, but it cannot be done
2847 * through the dispatch table.
2850 int count_members_of_list(q, argv, cl, action, actarg)
2857 EXEC SQL BEGIN DECLARE SECTION;
2859 EXEC SQL END DECLARE SECTION;
2860 char *rargv[1], countbuf[5];
2862 list = *(int *)argv[0];
2863 rargv[0] = countbuf;
2864 EXEC SQL REPEATED SELECT count (*) INTO :ct FROM imembers
2865 WHERE list_id = :list AND direct=1;
2866 if (ingres_errno) return(mr_errcode);
2867 sprintf(countbuf, "%d", ct);
2868 (*action)(1, rargv, actarg);
2873 /* qualified_get_server: passed "TRUE", "FALSE", or "DONTCARE" for each of
2874 * the three flags associated with each service. It will return the name of
2875 * each service that meets the quailifications. It does this by building a
2876 * where clause based on the arguments, then doing a retrieve.
2879 static char *sflags[3] = { "enable", "inprogress", "harderror" };
2881 int qualified_get_server(q, argv, cl, action, actarg)
2888 return(qualified_get(q, argv, action, actarg, "s.name != ''",
2889 "s", "name", sflags));
2893 /* generic qualified get routine, used by qualified_get_lists,
2894 * qualified_get_server, and qualified_get_serverhost.
2896 * start - a simple where clause, must not be empty
2897 * range - the name of the range variable
2898 * field - the field to return
2899 * flags - an array of strings, names of the flag variables
2902 int qualified_get(q, argv, action, actarg, start, range, field, flags)
2912 char name[33], qual[256], *rvar, *rtbl, *rfield;
2914 char *rargv[1], buf[32];
2916 strcpy(qual, start);
2917 for (i = 0; i < q->argc; i++) {
2918 if (!strcmp(argv[i], "TRUE")) {
2919 sprintf(buf, " and %s.%s != 0", range, flags[i]);
2920 (void) strcat(qual, buf);
2921 } else if (!strcmp(argv[i], "FALSE")) {
2922 sprintf(buf, " and %s.%s = 0", range, flags[i]);
2923 (void) strcat(qual, buf);
2931 sprintf(stmt_buf,"SELECT %s.%s FROM %s WHERE %s",rtbl,rfield,rtbl,qual);
2932 EXEC SQL PREPARE stmt FROM :stmt_buf;
2933 EXEC SQL DESCRIBE stmt INTO :SQLDA;
2934 SQLDA->sqlvar[0].sqldata=name;
2935 SQLDA->sqlvar[0].sqllen=32;
2936 EXEC SQL DECLARE csr123 CURSOR FOR stmt;
2937 EXEC SQL OPEN csr123;
2939 EXEC SQL FETCH csr123 USING DESCRIPTOR :SQLDA;
2940 if(sqlca.sqlcode != 0) break;
2942 (*action)(1, rargv, actarg);
2944 EXEC SQL CLOSE csr123;
2945 if (ingres_errno) return(mr_errcode);
2947 return(MR_NO_MATCH);
2952 /* qualified_get_serverhost: passed "TRUE", "FALSE", or "DONTCARE" for each of
2953 * the five flags associated with each serverhost. It will return the name of
2954 * each service and host that meets the quailifications. It does this by
2955 * building a where clause based on the arguments, then doing a retrieve.
2958 static char *shflags[6] = { "service", "enable", "override", "success",
2959 "inprogress", "hosterror" };
2961 int qualified_get_serverhost(q, argv, cl, action, actarg)
2968 EXEC SQL BEGIN DECLARE SECTION;
2969 char sname[33], mname[33], qual[256];
2970 EXEC SQL END DECLARE SECTION;
2971 char *rargv[2], buf[32];
2974 /** the uppercase() function is INGRES-specific */
2975 sprintf(qual, "machine.mach_id = serverhosts.mach_id AND \
2976 serverhosts.service = uppercase('%s')",
2978 for (i = 1; i < q->argc; i++) {
2979 if (!strcmp(argv[i], "TRUE")) {
2980 sprintf(buf, " AND serverhosts.%s != 0", shflags[i]);
2982 } else if (!strcmp(argv[i], "FALSE")) {
2983 sprintf(buf, " AND serverhosts.%s = 0", shflags[i]);
2990 EXEC SQL DECLARE csr124 CURSOR FOR
2991 SELECT serverhosts.service, machine.name FROM serverhosts, machine
2993 EXEC SQL OPEN csr124;
2995 EXEC SQL FETCH csr124 INTO :sname, :mname;
2996 if(sqlca.sqlcode != 0) break;
2998 (*action)(2, rargv, actarg);
3000 EXEC SQL CLOSE csr124;
3002 if (ingres_errno) return(mr_errcode);
3004 return(MR_NO_MATCH);
3009 /* register_user - change user's login name and allocate a pobox, group,
3010 * filesystem, and quota for them. The user's status must start out as 0,
3011 * and is left as 2. Arguments are: user's UID, new login name, and user's
3012 * type for filesystem allocation (MR_FS_STUDENT, MR_FS_FACULTY,
3013 * MR_FS_STAFF, MR_FS_MISC).
3016 register_user(q, argv, cl)
3021 EXEC SQL BEGIN DECLARE SECTION;
3022 char *login, dir[65], *entity, *directory, machname[33];
3023 int who, rowcount, mid, uid, users_id, flag, utype, nid, list_id, quota;
3024 int size, alloc, pid, m_id, ostatus, nstatus, gidval, fsidval;
3025 EXEC SQL END DECLARE SECTION;
3026 char buffer[256], *aargv[3];
3029 entity = cl->entity;
3030 who = cl->client_id;
3032 uid = atoi(argv[0]);
3034 utype = atoi(argv[2]);
3037 EXEC SQL REPEATED SELECT users_id, status INTO :users_id, :ostatus
3039 WHERE uid = :uid AND (status=0 OR status=5 OR status=6);
3041 if (sqlca.sqlerrd[2] == 0)
3042 return(MR_NO_MATCH);
3043 if (sqlca.sqlerrd[2] > 1)
3044 return(MR_NOT_UNIQUE);
3046 /* check new login name */
3047 EXEC SQL REPEATED SELECT login INTO :cdummy FROM users
3048 WHERE login = :login AND users_id != :users_id;
3049 if (ingres_errno) return(mr_errcode);
3050 if (sqlca.sqlerrd[2] > 0) return(MR_IN_USE);
3051 EXEC SQL REPEATED SELECT name INTO :cdummy FROM list
3052 WHERE name = :login;
3053 if (ingres_errno) return(mr_errcode);
3054 if (sqlca.sqlerrd[2] > 0) return(MR_IN_USE);
3055 EXEC SQL REPEATED SELECT label INTO :cdummy FROM filesys
3056 WHERE label = :login;
3057 if (ingres_errno) return(mr_errcode);
3058 if (sqlca.sqlerrd[2] > 0) return(MR_IN_USE);
3059 com_err(whoami, 0, "login name OK");
3061 /* choose place for pobox, put in mid */
3062 EXEC SQL REPEATED SELECT sh.mach_id, m.name
3063 INTO :mid, :machname FROM serverhosts sh, machine m
3064 WHERE sh.service='POP' AND sh.value2 - sh.value1 =
3065 (SELECT MAX(value2 - value1) FROM serverhosts
3066 WHERE service = 'POP');
3067 if (ingres_errno) return(mr_errcode);
3068 if (sqlca.sqlerrd[2] == 0)
3069 return(MR_NO_POBOX);
3071 /* change login name, set pobox */
3072 sprintf(buffer, "users.users_id = %d", users_id);
3073 incremental_before("users", buffer, 0);
3075 if (ostatus == 5 || ostatus == 6)
3077 EXEC SQL REPEATED UPDATE users SET login = :login, status = :nstatus,
3078 modtime='now', modby = :who, modwith = :entity, potype='POP',
3079 pop_id = :mid, pmodtime='now', pmodby = :who, pmodwith = :entity
3080 WHERE users_id = :users_id;
3082 if (ingres_errno) return(mr_errcode);
3083 if (sqlca.sqlerrd[2] != 1)
3084 return(MR_INTERNAL);
3085 set_pop_usage(mid, 1);
3086 com_err(whoami, 0, "set login name to %s and pobox to %s", login,
3088 incremental_after("users", buffer, 0);
3090 /* create group list */
3091 if (set_next_object_id("gid", "list", 1))
3093 if (set_next_object_id("list_id", "list", 0))
3095 EXEC SQL REPEATED SELECT value INTO :list_id FROM numvalues
3096 WHERE name='list_id';
3097 if (ingres_errno) return(mr_errcode);
3098 if (sqlca.sqlerrd[2] != 1)
3099 return(MR_INTERNAL);
3100 incremental_clear_before();
3101 EXEC SQL SELECT value INTO :gidval FROM numvalues WHERE name = 'gid';
3102 EXEC SQL REPEATED INSERT INTO list
3103 (name, list_id, active, public, hidden, maillist, grouplist,
3104 gid, desc, acl_type, acl_id,
3105 modtime, modby, modwith)
3106 VALUES (:login, :list_id, 1, 0, 0, 0, 1,
3107 :gidval, 'User Group', 'USER', :users_id,
3108 'now', :who, :entity);
3109 if (ingres_errno) return(mr_errcode);
3110 if (sqlca.sqlerrd[2] != 1)
3111 return(MR_INTERNAL);
3112 sprintf(buffer, "l.list_id = %d", list_id);
3113 incremental_after("list", buffer, 0);
3114 aargv[0] = (char *) list_id;
3116 aargv[2] = (char *) users_id;
3117 incremental_clear_before();
3118 EXEC SQL REPEATED INSERT INTO imembers
3119 (list_id, member_type, member_id, ref_count, direct)
3120 VALUES (:list_id, 'USER', :users_id, 1, 1);
3121 if (ingres_errno) return(mr_errcode);
3122 if (sqlca.sqlerrd[2] != 1)
3123 return(MR_INTERNAL);
3124 incremental_after("members", 0, aargv);
3126 /* decide where to put filesystem */
3129 EXEC SQL DECLARE csr125 CURSOR FOR
3130 SELECT mach_id, trim(nfsphys.dir), nfsphys_id, status, size, allocated
3132 EXEC SQL OPEN csr125;
3134 EXEC SQL FETCH csr125 INTO :mid, :dir, :nid, :flag, :size, :alloc;
3135 if(sqlca.sqlcode != 0) break;
3136 if ((flag & utype) && (size != 0) && (size - alloc > maxsize)) {
3137 maxsize = size - alloc;
3140 directory = strsave(dir);
3145 EXEC SQL CLOSE csr125;
3146 if (ingres_errno) return(mr_errcode);
3148 return(MR_NO_FILESYS);
3150 /* create filesystem */
3151 if (set_next_object_id("filsys_id", "filesys", 0))
3153 incremental_clear_before();
3154 EXEC SQL SELECT value INTO :fsidval FROM numvalues
3155 WHERE numvalues.name='filsys_id';
3156 EXEC SQL REPEATED INSERT INTO filesys
3157 (filsys_id, phys_id, label, type, mach_id, name,
3158 mount, access, comments, owner, owners, createflg,
3159 lockertype, modtime, modby, modwith)
3161 (:fsidval, :pid, :login, 'NFS', :m_id, :directory+'/'+:login,
3162 '/mit/'+:login, 'w', 'User Locker', :users_id, :list_id, 1,
3163 'HOMEDIR', 'now', :who, :entity) ;
3164 if (ingres_errno) return(mr_errcode);
3165 if (sqlca.sqlerrd[2] != 1)
3166 return(MR_INTERNAL);
3167 incremental_after("filesys",
3168 "fs.filsys_id = numvalues.value and numvalues.name = 'filsys_id'",
3170 com_err(whoami, 0, "filesys on mach %d in %s/%s", m_id,
3174 EXEC SQL REPEATED SELECT value INTO :quota FROM numvalues
3175 WHERE name='def_quota';
3176 if (ingres_errno) return(mr_errcode);
3177 if (sqlca.sqlerrd[2] != 1)
3178 return(MR_NO_QUOTA);
3179 incremental_clear_before();
3180 EXEC SQL SELECT value INTO :fsidval FROM numvalues
3181 WHERE numvalues.name = 'filsys_id';
3182 EXEC SQL REPEATED INSERT INTO quota
3183 (entity_id, filsys_id, type, quota, phys_id, modtime, modby, modwith)
3185 (:users_id, :fsidval, 'USER', :quota, :pid, 'now', :who, :entity);
3186 if (ingres_errno) return(mr_errcode);
3187 if (sqlca.sqlerrd[2] != 1)
3188 return(MR_INTERNAL);
3189 EXEC SQL REPEATED UPDATE nfsphys SET allocated=allocated + :quota
3190 WHERE nfsphys_id = filesys.phys_id
3191 AND filesys.filsys_id = numvalues.value
3192 AND numvalues.name = 'filsys_id';
3193 if (ingres_errno) return(mr_errcode);
3194 if (sqlca.sqlerrd[2] != 1)
3195 return(MR_INTERNAL);
3199 sprintf(buffer, "q.entity_id = %d and q.filsys_id = numvalues.value and q.type = 'USER' and numvalues.name = 'filsys_id'", users_id);
3200 incremental_after("quota", buffer, aargv);
3201 com_err(whoami, 0, "quota of %d assigned", quota);
3202 if (ingres_errno) return(mr_errcode);
3204 cache_entry(login, "USER", users_id);
3206 EXEC SQL REPEATED UPDATE tblstats SET updates=updates+1, modtime='now'
3207 WHERE table_name='users';
3208 EXEC SQL REPEATED UPDATE tblstats SET appends=appends+1, modtime='now'
3209 WHERE table_name='list' OR table_name='filesys' OR table_name='quota';
3210 if (ingres_errno) return(mr_errcode);
3216 /** set_pop_usage - incr/decr usage count for pop server in serverhosts talbe
3220 ** delta (will be +/- 1)
3223 ** - incr/decr value field in serverhosts table for pop/mach_id
3227 static int set_pop_usage(id, cnt)
3228 EXEC SQL BEGIN DECLARE SECTION;
3231 EXEC SQL END DECLARE SECTION;
3233 EXEC SQL REPEATED UPDATE serverhosts SET value1 = value1 + :cnt
3234 WHERE serverhosts.service = 'POP' AND serverhosts.mach_id = :id;
3236 if (ingres_errno) return(mr_errcode);
3242 /* Validation Routines */
3244 validate_row(q, argv, v)
3245 register struct query *q;
3247 register struct validate *v;
3249 EXEC SQL BEGIN DECLARE SECTION;
3250 char *rvar, *tbl, *name;
3253 EXEC SQL END DECLARE SECTION;
3255 /* build where clause */
3256 build_qual(v->qual, v->argc, argv, qual);
3258 /* setup ingres variables */
3263 if (log_flags & LOG_VALID)
3264 /* tell the logfile what we're doing */
3265 com_err(whoami, 0, "validating row: %s", qual);
3267 /* look for the record */
3269 * range of rvar is table
3270 * retrieve (rowcount = count(rvar.name where qual))
3272 sprintf(stmt_buf,"SELECT COUNT (*) FROM %s %s WHERE %s",tbl,rvar,qual);
3273 EXEC SQL PREPARE stmt FROM :stmt_buf;
3274 EXEC SQL DESCRIBE stmt INTO :SQLDA;
3275 SQLDA->sqlvar[0].sqldata=&rowcount;
3276 SQLDA->sqlvar[0].sqllen=sizeof(rowcount);
3277 EXEC SQL DECLARE csr126 CURSOR FOR stmt;
3278 EXEC SQL OPEN csr126;
3279 EXEC SQL FETCH csr126 USING DESCRIPTOR :SQLDA;
3280 EXEC SQL CLOSE csr126;
3282 if (ingres_errno) return(mr_errcode);
3283 if (rowcount == 0) return(MR_NO_MATCH);
3284 if (rowcount > 1) return(MR_NOT_UNIQUE);
3288 validate_fields(q, argv, vo, n)
3290 register char *argv[];
3291 register struct valobj *vo;
3294 register int status;
3299 if (log_flags & LOG_VALID)
3300 com_err(whoami, 0, "validating %s in %s: %s",
3301 vo->namefield, vo->table, argv[vo->index]);
3302 status = validate_name(argv, vo);
3306 if (log_flags & LOG_VALID)
3307 com_err(whoami, 0, "validating %s in %s: %s",
3308 vo->idfield, vo->table, argv[vo->index]);
3309 status = validate_id(q, argv, vo);
3313 if (log_flags & LOG_VALID)
3314 com_err(whoami, 0, "validating date: %s", argv[vo->index]);
3315 status = validate_date(argv, vo);
3319 if (log_flags & LOG_VALID)
3320 com_err(whoami, 0, "validating %s type: %s",
3321 vo->table, argv[vo->index]);
3322 status = validate_type(argv, vo);
3326 if (log_flags & LOG_VALID)
3327 com_err(whoami, 0, "validating typed data (%s): %s",
3328 argv[vo->index - 1], argv[vo->index]);
3329 status = validate_typedata(q, argv, vo);
3333 if (log_flags & LOG_VALID)
3334 com_err(whoami, 0, "validating rename %s in %s",
3335 argv[vo->index], vo->table);
3336 status = validate_rename(argv, vo);
3340 if (log_flags & LOG_VALID)
3341 com_err(whoami, 0, "validating chars: %s", argv[vo->index]);
3342 status = validate_chars(argv[vo->index]);
3350 status = lock_table(vo);
3354 if (status != MR_EXISTS) return(status);
3358 if (ingres_errno) return(mr_errcode);
3363 /* validate_chars: verify that there are no illegal characters in
3364 * the string. Legal characters are printing chars other than
3365 * ", *, ?, \, [ and ].
3367 static int illegalchars[] = {
3368 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
3369 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
3370 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
3371 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
3372 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* : - O */
3373 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* P - _ */
3374 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
3375 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
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,
3381 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3382 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3383 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3390 if (illegalchars[*s++])
3391 return(MR_BAD_CHAR);
3396 validate_id(q, argv, vo)
3399 register struct valobj *vo;
3401 EXEC SQL BEGIN DECLARE SECTION;
3402 char *name, *tbl, *namefield, *idfield;
3404 EXEC SQL END DECLARE SECTION;
3408 name = argv[vo->index];
3410 namefield = vo->namefield;
3411 idfield = vo->idfield;
3413 if ((!strcmp(tbl, "users") && !strcmp(namefield, "login")) ||
3414 !strcmp(tbl, "machine") ||
3415 !strcmp(tbl, "filesys") ||
3416 !strcmp(tbl, "list") ||
3417 !strcmp(tbl, "cluster") ||
3418 !strcmp(tbl, "strings")) {
3419 if (!strcmp(tbl, "machine"))
3420 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3421 status = name_to_id(name, tbl, &id);
3423 *(int *)argv[vo->index] = id;
3425 } else if (status == MR_NO_MATCH && !strcmp(tbl, "strings") &&
3426 (q->type == APPEND || q->type == UPDATE)) {
3427 EXEC SQL SELECT value INTO :id FROM numvalues
3428 WHERE name = 'strings_id';
3430 EXEC SQL UPDATE numvalues SET value = :id WHERE name = 'string_id';
3431 EXEC SQL INSERT INTO strings (string_id, string) VALUES (:id, :name);
3432 cache_entry(name, "STRING", id);
3433 *(int *)argv[vo->index] = id;
3435 } else if (status == MR_NO_MATCH || status == MR_NOT_UNIQUE)
3441 if (!strcmp(namefield, "uid")) {
3443 * retrieve (id = table.idfield) where table.namefield = int4(name)
3445 sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s.%s = %s",idfield,tbl,tbl,namefield,name);
3446 if (ingres_errno) return(mr_errcode);
3449 * retrieve (id = table.idfield) where table.namefield = name
3451 sprintf(stmt_buf,SELECT %s FROM %s WHERE %s.%s = '%s'",idfield,tbl,tbl,namefield,name);
3452 if (ingres_errno) return(mr_errcode);
3454 EXEC SQL PREPARE stmt FROM :stmt_buf;
3455 EXEC SQL DESCRIBE stmt INTO :SQLDA;
3456 SQLDA->sqlvar[0].sqldata=&id;
3457 SQLDA->sqlvar[0].sqllen=sizeof(id);
3458 EXEC SQL DECLARE csr127 CURSOR FOR stmt;
3459 EXEC SQL OPEN csr127;
3460 EXEC SQL FETCH csr127 USING DESCRIPTOR :SQLDA;
3461 if(sqlca.sqlcode == 0) rowcount=1; else rowcount=0;
3462 EXEC SQL FETCH csr127 USING DESCRIPTOR :SQLDA;
3463 if(sqlca.sqlcode == 0) rowcount=2;
3464 EXEC SQL CLOSE csr127;
3466 if (rowcount != 1) return(vo->error);
3467 *(int *)argv[vo->index] = id;
3471 validate_name(argv, vo)
3473 register struct valobj *vo;
3475 EXEC SQL BEGIN DECLARE SECTION;
3476 char *name, *tbl, *namefield;
3478 EXEC SQL END DECLARE SECTION;
3481 name = argv[vo->index];
3483 namefield = vo->namefield;
3484 if (!strcmp(tbl, "servers") && !strcmp(namefield, "name")) {
3485 for (c = name; *c; c++)
3490 * retrieve (rowcount = countu(table.namefield
3491 * where table.namefield = name))
3493 sprintf(stmt_buf,"SELECT COUNT (DISTINCT *) FROM %s WHERE %s.%s = '%s'",
3494 tbl,tbl,namefield,name);
3495 EXEC SQL PREPARE stmt FROM :stmt_buf;
3496 EXEC SQL DESCRIBE stmt INTO :SQLDA;
3497 SQLDA->sqlvar[0].sqldata=&rowcount;
3498 SQLDA->sqlvar[0].sqllen=sizeof(rowcount);
3500 EXEC SQL DECLARE csr128 CURSOR FOR stmt;
3501 EXEC SQL OPEN csr128;
3502 EXEC SQL FETCH csr128 USING DESCRIPTOR :SQLDA;
3503 EXEC SQL CLOSE csr128;
3505 if (ingres_errno) return(mr_errcode);
3506 return ((rowcount == 1) ? MR_EXISTS : vo->error);
3509 validate_date(argv, vo)
3513 EXEC SQL BEGIN DECLARE SECTION;
3517 EXEC SQL END DECLARE SECTION;
3519 idate = argv[vo->index];
3521 * retrieve (dd = interval("years", date(idate) - date("today")))
3523 EXEC SQL SELECT interval('years',date(:idate)-date('today')) INTO :dd;
3525 if (sqlca.sqlcode != 0 || dd > 5.0) return(MR_DATE);
3530 validate_rename(argv, vo)
3534 EXEC SQL BEGIN DECLARE SECTION;
3535 char *name, *tbl, *namefield, *idfield;
3537 EXEC SQL END DECLARE SECTION;
3541 c = name = argv[vo->index];
3543 if (illegalchars[*c++])
3544 return(MR_BAD_CHAR);
3546 /* minor kludge to upcasify machine names */
3547 if (!strcmp(tbl, "machine"))
3548 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3549 namefield = vo->namefield;
3550 idfield = vo->idfield;
3553 if (!strcmp(argv[vo->index], argv[vo->index - 1]))
3556 * retrieve (id = any(table.namefield where table.namefield = name))
3558 sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s.%s = '%s'",
3559 namefield,tbl,tbl,namefield,name);
3560 EXEC SQL PREPARE stmt FROM :stmt_buf;
3561 EXEC SQL DESCRIBE stmt INTO :SQLDA;
3562 SQLDA->sqlvar[0].sqldata = cdummy;
3563 SQLDA->sqlvar[0].sqllen = MR_CDUMMY_LEN-1;
3564 EXEC SQL DECLARE csr129 CURSOR FOR stmt;
3565 EXEC SQL OPEN csr129;
3566 EXEC SQL FETCH csr129 USING DESCRIPTOR :SQLDA;
3567 if(sqlca.sqlcode == 0) id=1; else id=0;
3568 EXEC SQL CLOSE csr129;
3570 if (ingres_errno) return(mr_errcode);
3576 status = name_to_id(name, tbl, &id);
3577 if (status == MR_NO_MATCH || id == *(int *)argv[vo->index - 1])
3584 validate_type(argv, vo)
3586 register struct valobj *vo;
3588 EXEC SQL BEGIN DECLARE SECTION;
3591 EXEC SQL END DECLARE SECTION;
3594 typename = vo->table;
3595 c = value = argv[vo->index];
3597 if (illegalchars[*c])
3598 return(MR_BAD_CHAR);
3601 /* uppercase type fields */
3602 for (c = value; *c; c++) if (islower(*c)) *c = toupper(*c);
3604 EXEC SQL SELECT trans INTO :cdummy FROM alias
3605 WHERE name = :typename AND type='TYPE' AND trans = :value;
3606 if (ingres_errno) return(mr_errcode);
3607 return (sqlca.sqlerrd[2] ? MR_EXISTS : vo->error);
3610 /* validate member or type-specific data field */
3612 validate_typedata(q, argv, vo)
3613 register struct query *q;
3614 register char *argv[];
3615 register struct valobj *vo;
3617 EXEC SQL BEGIN DECLARE SECTION;
3620 char data_type[129];
3622 EXEC SQL END DECLARE SECTION;
3627 /* get named object */
3628 name = argv[vo->index];
3630 /* get field type string (known to be at index-1) */
3631 field_type = argv[vo->index-1];
3633 /* get corresponding data type associated with field type name */
3634 EXEC SQL SELECT trans INTO :data_type FROM alias
3635 WHERE name = :field_type AND type='TYPEDATA';
3636 if (ingres_errno) return(mr_errcode);
3637 if (sqlca.sqlerrd[2] != 1) return(MR_TYPE);
3639 /* now retrieve the record id corresponding to the named object */
3640 if (index(data_type, ' '))
3641 *index(data_type, ' ') = 0;
3642 if (!strcmp(data_type, "user")) {
3644 status = name_to_id(name, data_type, &id);
3645 if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
3647 if (status) return(status);
3648 } else if (!strcmp(data_type, "list")) {
3650 status = name_to_id(name, data_type, &id);
3651 if (status && status == MR_NOT_UNIQUE)
3653 if (status == MR_NO_MATCH) {
3654 /* if idfield is non-zero, then if argv[0] matches the string
3655 * that we're trying to resolve, we should get the value of
3656 * numvalues.[idfield] for the id.
3658 if (vo->idfield && !strcmp(argv[0], argv[vo->index])) {
3659 set_next_object_id(q->validate->object_id, q->rtable, 0);
3661 EXEC SQL REPEATED SELECT value INTO :id FROM numvalues
3663 if (sqlca.sqlerrd[2] != 1) return(MR_LIST);
3666 } else if (status) return(status);
3667 } else if (!strcmp(data_type, "machine")) {
3669 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3670 status = name_to_id(name, data_type, &id);
3671 if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
3673 if (status) return(status);
3674 } else if (!strcmp(data_type, "string")) {
3676 status = name_to_id(name, data_type, &id);
3677 if (status && status == MR_NOT_UNIQUE)
3679 if (status == MR_NO_MATCH) {
3680 if (q->type != APPEND && q->type != UPDATE) return(MR_STRING);
3681 EXEC SQL SELECT value INTO :id FROM numvalues WHERE name = 'strings_id';
3683 EXEC SQL UPDATE numvalues SET value = :id WHERE name = 'strings_id';
3684 EXEC SQL INSERT INTO strings (string_id, string) VALUES (:id, :name);
3685 cache_entry(name, "STRING", id);
3686 } else if (status) return(status);
3687 } else if (!strcmp(data_type, "none")) {
3693 /* now set value in argv */
3694 *(int *)argv[vo->index] = id;
3700 /* Lock the table named by the validation object */
3705 sprintf(stmt_buf,"UPDATE %s SET modtime='now' WHERE %s.%s = 0",
3706 vo->table,vo->table,vo->idfield);
3707 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
3708 if (ingres_errno) return(mr_errcode);
3709 if (sqlca.sqlerrd[2] != 1)
3716 /* Check the database at startup time. For now this just resets the
3717 * inprogress flags that the DCM uses.
3720 sanity_check_database()