6 * Copyright (C) 1987 by the Massachusetts Institute of Technology
7 * For copying and distribution information, please see the file
13 static char *rcsid_qsupport_dc = "$Header$";
16 #include <mit-copyright.h>
18 #include "mr_server.h"
23 EXEC SQL INCLUDE sqlca;
24 EXEC SQL INCLUDE sqlda;
27 extern char *whoami, *strsave();
28 extern int ingres_errno, mr_errcode;
30 EXEC SQL BEGIN DECLARE SECTION;
31 extern char stmt_buf[];
32 EXEC SQL END DECLARE SECTION;
34 EXEC SQL WHENEVER SQLERROR CALL ingerr;
39 /* Setup routine for add_user
41 * Inputs: argv[0] - login
46 * - if argv[1] == UNIQUE_UID then set argv[1] = next(uid)
47 * - if argv[0] == UNIQUE_LOGIN then set argv[0] = "#<uid>"
50 setup_ausr(q, argv, cl)
52 register char *argv[];
56 EXEC SQL BEGIN DECLARE SECTION;
58 EXEC SQL END DECLARE SECTION;
60 if (!strcmp(q->shortname, "uusr") || !strcmp(q->shortname, "uuac"))
64 if (!strcmp(argv[row], UNIQUE_UID) || atoi(argv[row]) == -1) {
65 if (set_next_object_id("uid", "users", 1))
66 return(MR_INGRES_ERR);
67 EXEC SQL SELECT value INTO :nuid FROM numvalues WHERE name = 'uid';
68 if (sqlca.sqlerrd[2] != 1)
70 sprintf(argv[row], "%d", nuid);
73 if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[row]) == -1) {
74 sprintf(argv[0], "#%s", argv[row]);
77 if((mr_errcode=prefetch_value(q,argv,cl))!=MR_SUCCESS)
84 /* setup_dusr - verify that the user is no longer being referenced
85 * and may safely be deleted.
88 int setup_dusr(q, argv)
92 EXEC SQL BEGIN DECLARE SECTION;
94 EXEC SQL END DECLARE SECTION;
98 /* For now, only allow users to be deleted if their status is 0 */
99 EXEC SQL REPEATED SELECT status INTO :flag FROM users
100 WHERE users_id = :id;
101 if (flag != 0 && flag != 4)
104 EXEC SQL REPEATED DELETE FROM quota WHERE entity_id = :id AND type='USER';
105 EXEC SQL REPEATED DELETE FROM krbmap WHERE users_id = :id;
106 EXEC SQL REPEATED SELECT COUNT(member_id) INTO :cnt FROM imembers
107 WHERE member_id = :id AND member_type = 'USER';
110 EXEC SQL REPEATED SELECT COUNT(label) INTO :cnt FROM filesys
114 EXEC SQL REPEATED SELECT COUNT(name) INTO :cnt FROM list
115 WHERE acl_id = :id AND acl_type = 'USER';
118 EXEC SQL REPEATED SELECT COUNT(name) INTO :cnt FROM servers
119 WHERE acl_id = :id AND acl_type = 'USER';
122 EXEC SQL REPEATED SELECT COUNT(acl_id) INTO :cnt FROM hostaccess
123 WHERE acl_id = :id AND acl_type = 'USER';
132 /* setup_spop: verify that there is already a valid POP machine_id in the
133 * pop_id field. Also take care of keeping track of the post office usage.
135 int setup_spop(q, argv)
139 EXEC SQL BEGIN DECLARE SECTION;
142 EXEC SQL END DECLARE SECTION;
144 id = *(int *)argv[0];
145 EXEC SQL REPEATED SELECT potype, pop_id INTO :type, :mid FROM users
146 WHERE users_id = :id;
147 if(sqlca.sqlerrd[2] = 0)
149 EXEC SQL REPEATED SELECT mach_id INTO :mid FROM machine
150 WHERE mach_id = :mid;
151 if (sqlca.sqlerrd[2] = 0)
153 if (strcmp(strtrim(type), "POP"))
154 set_pop_usage(mid, 1);
159 /* setup_dpob: Take care of keeping track of the post office usage.
161 int setup_dpob(q, argv)
165 EXEC SQL BEGIN DECLARE SECTION;
168 EXEC SQL END DECLARE SECTION;
170 user = *(int *)argv[0];
171 EXEC SQL REPEATED SELECT potype, pop_id INTO :type, :id FROM users
172 WHERE users_id = :user;
173 if (ingres_errno) return(mr_errcode);
175 if (!strcmp(strtrim(type), "POP"))
176 set_pop_usage(id, -1);
181 /* setup_dmac - verify that the machine is no longer being referenced
182 * and may safely be deleted.
185 int setup_dmac(q, argv)
189 EXEC SQL BEGIN DECLARE SECTION;
191 EXEC SQL END DECLARE SECTION;
193 id = *(int *)argv[0];
194 EXEC SQL REPEATED SELECT COUNT(login) INTO :cnt FROM users
195 WHERE potype='POP' AND pop_id = :id;
198 EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM serverhosts
202 EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM nfsphys
206 EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM hostaccess
210 EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM printcap
214 EXEC SQL REPEATED SELECT COUNT(quotaserver) INTO :cnt FROM printcap
215 WHERE quotaserver = :id;
218 EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM palladium
223 EXEC SQL REPEATED DELETE FROM mcmap WHERE mach_id = :id;
224 if (ingres_errno) return(mr_errcode);
229 /* setup_dsnt - verify that the subnet is no longer being referenced
230 * and may safely be deleted.
233 int setup_dsnt(q, argv)
237 EXEC SQL BEGIN DECLARE SECTION;
238 int flag, id, cnt = 0;
239 EXEC SQL END DECLARE SECTION;
242 id = *(int *)argv[0];
243 EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM machine
252 /* setup_dclu - verify that the cluster is no longer being referenced
253 * and may safely be deleted.
256 int setup_dclu(q, argv)
260 EXEC SQL BEGIN DECLARE SECTION;
262 EXEC SQL END DECLARE SECTION;
264 id = *(int *)argv[0];
265 EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM mcmap
269 EXEC SQL REPEATED SELECT COUNT(clu_id) INTO :cnt FROM svc
279 /* setup_alis - if argv[5] is non-zero and argv[6] is UNIQUE_ID, then allocate
280 * a new gid and put it in argv[6]. Otherwise if argv[6] is UNIQUE_ID but
281 * argv[5] is not, then remember that UNIQUE_ID is being stored by putting
282 * a -1 there. Remember that this is also used for ulis, with the indexes
283 * at 6 & 7. Also check that the list name does not contain uppercase
284 * characters, control characters, @, or :.
287 static int badlistchars[] = {
288 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
289 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
290 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
291 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, /* 0 - ? */
292 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
293 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, /* P - _ */
294 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
295 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
296 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
297 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
298 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
299 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
300 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
301 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
302 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
303 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
306 int setup_alis(q, argv, cl)
311 EXEC SQL BEGIN DECLARE SECTION;
313 EXEC SQL END DECLARE SECTION;
318 if (!strcmp(q->shortname, "alis"))
320 else if (!strcmp(q->shortname, "ulis"))
323 for (p = (unsigned char *) argv[idx]; *p; p++)
324 if (badlistchars[*p])
327 if (!strcmp(argv[6 + idx], UNIQUE_GID) || atoi(argv[6 + idx]) == -1) {
328 if (atoi(argv[5 + idx])) {
329 if (set_next_object_id("gid", "list", 1))
330 return(MR_INGRES_ERR);
331 EXEC SQL REPEATED SELECT value INTO :ngid FROM numvalues
333 if (ingres_errno) return(mr_errcode);
334 sprintf(argv[6 + idx], "%d", ngid);
336 strcpy(argv[6 + idx], "-1");
340 if((mr_errcode=prefetch_value(q,argv,cl))!=MR_SUCCESS)
347 /* setup_dlis - verify that the list is no longer being referenced
348 * and may safely be deleted.
351 int setup_dlis(q, argv)
357 id = *(int *)argv[0];
358 sprintf(stmt_buf,"SELECT member_id FROM imembers WHERE member_id = %d AND member_type='LIST'",id);
359 if(ec=mr_select_any(stmt_buf)) {
360 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
363 sprintf(stmt_buf,"SELECT member_id FROM imembers WHERE list_id = %d",id);
364 if(ec=mr_select_any(stmt_buf)) {
365 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
368 sprintf(stmt_buf,"SELECT label FROM filesys WHERE owners = %d",id);
369 if(ec=mr_select_any(stmt_buf)) {
370 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
373 sprintf(stmt_buf,"SELECT tag FROM capacls WHERE list_id = %d",id);
374 if(ec=mr_select_any(stmt_buf)) {
375 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
378 sprintf(stmt_buf,"SELECT name FROM list WHERE acl_id = %d AND acl_type='LIST' AND list_id != %d",id,id);
379 if(ec=mr_select_any(stmt_buf)) {
380 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
383 sprintf(stmt_buf,"SELECT name FROM servers WHERE acl_id = %d AND acl_type='LIST'",id);
384 if(ec=mr_select_any(stmt_buf)) {
385 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
388 sprintf(stmt_buf,"SELECT entity_id FROM quota WHERE entity_id = %d AND type='GROUP'",id);
389 if(ec=mr_select_any(stmt_buf)) {
390 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
393 sprintf(stmt_buf,"SELECT acl_id FROM hostaccess WHERE acl_id = %d AND acl_type='LIST'",id);
394 if(ec=mr_select_any(stmt_buf)) {
395 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
398 sprintf(stmt_buf,"SELECT class FROM zephyr z \
399 WHERE z.xmt_type = 'LIST' AND z.xmt_id = %d \
400 OR z.sub_type = 'LIST' AND z.sub_id = %d \
401 OR z.iws_type = 'LIST' AND z.iws_id = %d \
402 OR z.iui_type = 'LIST' AND z.iui_id = %d",id,id,id,id);
403 if(ec=mr_select_any(stmt_buf)) {
404 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
411 /* setup_dsin - verify that the service is no longer being referenced
412 * and may safely be deleted.
415 int setup_dsin(q, argv)
419 EXEC SQL BEGIN DECLARE SECTION;
422 EXEC SQL END DECLARE SECTION;
424 sprintf(stmt_buf,"SELECT service FROM serverhosts WHERE service = UPPERCASE('%s')",argv[0]);
425 if(ec=mr_select_any(stmt_buf)) {
433 EXEC SQL SELECT inprogress INTO :ec FROM servers
434 WHERE name=UPPERCASE(:svrname);
444 /* setup_dshi - verify that the service-host is no longer being referenced
445 * and may safely be deleted.
448 int setup_dshi(q, argv)
452 EXEC SQL BEGIN DECLARE SECTION;
455 EXEC SQL END DECLARE SECTION;
458 id = *(int *)argv[1];
460 EXEC SQL SELECT inprogress INTO :ec FROM serverhosts
461 WHERE service=UPPERCASE(:svrname) AND mach_id = :id;
473 ** setup_add_filesys - verify existance of referenced file systems
485 ** * extract directory prefix from name
486 ** * verify mach_id/dir in nfsphys
487 ** * verify access in {r, w, R, W}
489 ** Side effect: sets variable _var_phys_id to the ID of the physical
490 ** filesystem (nfsphys_id for NFS, 0 for RVD)
493 ** MR_NFS - specified directory not exported
494 ** MR_FILESYS_ACCESS - invalid filesys access
498 EXEC SQL BEGIN DECLARE SECTION;
500 EXEC SQL END DECLARE SECTION;
502 setup_afil(q, argv, cl)
509 EXEC SQL BEGIN DECLARE SECTION;
511 char ftype[32], *access;
512 EXEC SQL END DECLARE SECTION;
515 mach_id = *(int *)argv[2];
520 sprintf(ftype, "fs_access_%s", type);
521 EXEC SQL SELECT COUNT(trans) INTO :ok FROM alias
522 WHERE name = :ftype AND type = 'TYPE' and trans = :access;
523 if (ingres_errno) return(mr_errcode);
524 if (ok == 0) return(MR_FILESYS_ACCESS);
526 if((mr_errcode=prefetch_value(q,argv,cl))!=MR_SUCCESS)
529 if (!strcmp(type, "NFS"))
530 return (check_nfs(mach_id, name, access));
536 /* Verify the arguments, depending on the FStype. Also, if this is an
537 * NFS filesystem, then update any quotas for that filesystem to reflect
541 setup_ufil(q, argv, cl)
548 EXEC SQL BEGIN DECLARE SECTION;
549 int fid, total, who, ok;
550 char *entity, ftype[32], *access;
551 short int total_null;
552 EXEC SQL END DECLARE SECTION;
556 mach_id = *(int *)argv[3];
559 fid = *(int *)argv[0];
563 sprintf(ftype, "fs_access_%s", type);
564 EXEC SQL SELECT COUNT(trans) INTO :ok FROM alias
565 WHERE name = :ftype AND type='TYPE' AND trans = :access;
566 if (ingres_errno) return(mr_errcode);
567 if (ok == 0) return(MR_FILESYS_ACCESS);
569 EXEC SQL SELECT type INTO :ftype FROM filesys
570 WHERE filsys_id = :fid;
572 if (ingres_errno) return(mr_errcode);
574 if (!strcmp(type, "NFS")) {
575 status = check_nfs(mach_id, name, access);
576 EXEC SQL UPDATE quota SET phys_id = :_var_phys_id
577 WHERE filsys_id = :fid;
578 if (ingres_errno) return(mr_errcode);
580 } else if (!strcmp(type, "AFS") && strcmp(ftype, "AFS")) {
582 EXEC SQL REPEATED DELETE FROM quota
583 WHERE type = 'ANY' AND filsys_id = :fid;
584 EXEC SQL SELECT SUM (quota) INTO :total:total_null FROM quota
585 WHERE filsys_id = :fid AND phys_id != 0;
586 if (ingres_errno) return(mr_errcode);
587 if (!total_null && (total != 0)) {
589 * append quota (quota = total, filsys_id = fid,
590 * phys_id = 0, entity_id = 0, type = "ANY",
591 * modtime = "now", modby = who, modwith = entity)
593 EXEC SQL INSERT INTO quota (quota, filsys_id, phys_id, entity_id,
594 type, modtime, modby, modwith)
595 VALUES (:total, :fid, 0, 0,
596 'ANY', 'now', :who, :entity) ;
597 if (ingres_errno) return(mr_errcode);
600 EXEC SQL UPDATE quota SET phys_id = 0 WHERE filsys_id = :fid;
601 if (ingres_errno) return(mr_errcode);
607 /* Find the NFS physical partition that the named directory is on.
608 * This is done by comparing the dir against the mount point of the
609 * partition. To make sure we get the correct match when there is
610 * more than one, we sort the query in reverse order by dir name.
613 check_nfs(mach_id, name, access)
614 EXEC SQL BEGIN DECLARE SECTION;
616 EXEC SQL END DECLARE SECTION;
620 EXEC SQL BEGIN DECLARE SECTION;
622 EXEC SQL END DECLARE SECTION;
629 EXEC SQL DECLARE csr101 CURSOR FOR
630 SELECT nfsphys_id, TRIM (dir) FROM nfsphys
631 WHERE mach_id = :mach_id
635 EXEC SQL OPEN csr101;
639 EXEC SQL FETCH csr101 INTO :_var_phys_id, :dir;
640 if(sqlca.sqlcode != 0) break;
644 if (*cp1++ != *cp2) break;
652 EXEC SQL CLOSE csr101;
659 /* setup_dfil: free any quota records and fsgroup info associated with
660 * a filesystem when it is deleted. Also adjust the allocation numbers.
663 setup_dfil(q, argv, cl)
668 EXEC SQL BEGIN DECLARE SECTION;
669 int id, total, phys_id;
671 EXEC SQL END DECLARE SECTION;
673 id = *(int *)argv[0];
674 EXEC SQL REPEATED SELECT SUM (quota) INTO :total:none FROM quota
675 WHERE filsys_id = :id;
679 /** What if there are multiple phys_id's per f/s? (bad data) **/
680 EXEC SQL REPEATED SELECT phys_id INTO :phys_id FROM filesys
681 WHERE filsys_id = :id;
682 EXEC SQL REPEATED UPDATE nfsphys SET allocated = allocated - :total
683 WHERE nfsphys_id = :phys_id;
686 EXEC SQL REPEATED DELETE FROM quota WHERE filsys_id = :id;
688 EXEC SQL REPEATED DELETE FROM fsgroup WHERE filsys_id = :id;
689 EXEC SQL REPEATED DELETE FROM fsgroup WHERE group_id = :id;
690 if (ingres_errno) return(mr_errcode);
695 /* setup_dnfp: check to see that the nfs physical partition does not have
696 * any filesystems assigned to it before allowing it to be deleted.
699 setup_dnfp(q, argv, cl)
704 EXEC SQL BEGIN DECLARE SECTION;
707 EXEC SQL END DECLARE SECTION;
709 id = *(int *)argv[0];
711 EXEC SQL REPEATED SELECT fs.tid INTO :cnt FROM filesys fs, nfsphys np
712 WHERE fs.mach_id = :id AND fs.phys_id = np.nfsphys_id
713 AND np.mach_id = :id AND np.dir = :dir;
722 /* setup_dqot: Remove allocation from nfsphys before deleting quota.
723 * argv[0] = filsys_id
724 * argv[1] = type if "update_quota" or "delete_quota"
725 * argv[2 or 1] = users_id or list_id
728 setup_dqot(q, argv, cl)
733 EXEC SQL BEGIN DECLARE SECTION;
734 int quota, fs, id, physid;
736 EXEC SQL END DECLARE SECTION;
738 fs = *(int *)argv[0];
739 if (!strcmp(q->name, "update_quota") || !strcmp(q->name, "delete_quota")) {
741 id = *(int *)argv[2];
744 id = *(int *)argv[1];
747 EXEC SQL REPEATED SELECT quota INTO :quota FROM quota
748 WHERE type = :qtype AND entity_id = :id AND filsys_id = :fs;
749 EXEC SQL REPEATED SELECT phys_id INTO :physid FROM filesys
750 WHERE filsys_id = :fs;
751 EXEC SQL REPEATED UPDATE nfsphys SET allocated = allocated - :quota
752 WHERE nfsphys_id = :physid;
754 if (ingres_errno) return(mr_errcode);
759 /* setup_sshi: don't exclusive lock the machine table during
760 * set_server_host_internal.
762 /** Not allowed under (INGRES) SQL **/
763 setup_sshi(q, argv, cl)
770 EXEC SQL set lockmode session where readlock = system;
777 /* setup add_kerberos_user_mapping: add the string to the string
778 * table if necessary.
781 setup_akum(q, argv, cl)
786 EXEC SQL BEGIN DECLARE SECTION;
789 EXEC SQL END DECLARE SECTION;
792 if (name_to_id(name, "STRING", &id) != MR_SUCCESS) {
793 if (q->type != APPEND) return(MR_STRING);
795 cache_entry(name, "STRING", id);
797 if (ingres_errno) return(mr_errcode);
798 *(int *)argv[1] = id;