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];
195 EXEC SQL REPEATED SELECT status INTO :flag FROM machine
199 EXEC SQL REPEATED SELECT COUNT(login) INTO :cnt FROM users
200 WHERE potype='POP' AND pop_id = :id;
203 EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM serverhosts
207 EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM nfsphys
211 EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM hostaccess
215 EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM printcap
219 EXEC SQL REPEATED SELECT COUNT(quotaserver) INTO :cnt FROM printcap
220 WHERE quotaserver = :id;
223 EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM palladium
228 EXEC SQL REPEATED DELETE FROM mcmap WHERE mach_id = :id;
229 if (ingres_errno) return(mr_errcode);
234 /* setup_dsnt - verify that the subnet is no longer being referenced
235 * and may safely be deleted.
238 int setup_dsnt(q, argv)
242 EXEC SQL BEGIN DECLARE SECTION;
243 int flag, id, cnt = 0;
244 EXEC SQL END DECLARE SECTION;
246 id = *(int *)argv[0];
247 EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM machine
255 /* setup_dclu - verify that the cluster is no longer being referenced
256 * and may safely be deleted.
259 int setup_dclu(q, argv)
263 EXEC SQL BEGIN DECLARE SECTION;
265 EXEC SQL END DECLARE SECTION;
267 id = *(int *)argv[0];
268 EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM mcmap
272 EXEC SQL REPEATED SELECT COUNT(clu_id) INTO :cnt FROM svc
282 /* setup_alis - if argv[5] is non-zero and argv[6] is UNIQUE_ID, then allocate
283 * a new gid and put it in argv[6]. Otherwise if argv[6] is UNIQUE_ID but
284 * argv[5] is not, then remember that UNIQUE_ID is being stored by putting
285 * a -1 there. Remember that this is also used for ulis, with the indexes
286 * at 6 & 7. Also check that the list name does not contain uppercase
287 * characters, control characters, @, or :.
290 static int badlistchars[] = {
291 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
292 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
293 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
294 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, /* 0 - ? */
295 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
296 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, /* P - _ */
297 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
298 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
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,
304 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
305 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
306 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
309 int setup_alis(q, argv, cl)
314 EXEC SQL BEGIN DECLARE SECTION;
316 EXEC SQL END DECLARE SECTION;
321 if (!strcmp(q->shortname, "alis"))
323 else if (!strcmp(q->shortname, "ulis"))
326 for (p = (unsigned char *) argv[idx]; *p; p++)
327 if (badlistchars[*p])
330 if (!strcmp(argv[6 + idx], UNIQUE_GID) || atoi(argv[6 + idx]) == -1) {
331 if (atoi(argv[5 + idx])) {
332 if (set_next_object_id("gid", "list", 1))
333 return(MR_INGRES_ERR);
334 EXEC SQL REPEATED SELECT value INTO :ngid FROM numvalues
336 if (ingres_errno) return(mr_errcode);
337 sprintf(argv[6 + idx], "%d", ngid);
339 strcpy(argv[6 + idx], "-1");
343 if((mr_errcode=prefetch_value(q,argv,cl))!=MR_SUCCESS)
350 /* setup_dlis - verify that the list is no longer being referenced
351 * and may safely be deleted.
354 int setup_dlis(q, argv)
360 id = *(int *)argv[0];
361 sprintf(stmt_buf,"SELECT member_id FROM imembers WHERE member_id = %d AND member_type='LIST'",id);
362 if(ec=mr_select_any(stmt_buf)) {
363 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
366 sprintf(stmt_buf,"SELECT member_id FROM imembers WHERE list_id = %d",id);
367 if(ec=mr_select_any(stmt_buf)) {
368 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
371 sprintf(stmt_buf,"SELECT label FROM filesys WHERE owners = %d",id);
372 if(ec=mr_select_any(stmt_buf)) {
373 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
376 sprintf(stmt_buf,"SELECT tag FROM capacls WHERE list_id = %d",id);
377 if(ec=mr_select_any(stmt_buf)) {
378 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
381 sprintf(stmt_buf,"SELECT name FROM list WHERE acl_id = %d AND acl_type='LIST' AND list_id != %d",id,id);
382 if(ec=mr_select_any(stmt_buf)) {
383 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
386 sprintf(stmt_buf,"SELECT name FROM servers WHERE acl_id = %d AND acl_type='LIST'",id);
387 if(ec=mr_select_any(stmt_buf)) {
388 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
391 sprintf(stmt_buf,"SELECT entity_id FROM quota WHERE entity_id = %d AND type='GROUP'",id);
392 if(ec=mr_select_any(stmt_buf)) {
393 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
396 sprintf(stmt_buf,"SELECT acl_id FROM hostaccess WHERE acl_id = %d AND acl_type='LIST'",id);
397 if(ec=mr_select_any(stmt_buf)) {
398 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
401 sprintf(stmt_buf,"SELECT class FROM zephyr z \
402 WHERE z.xmt_type = 'LIST' AND z.xmt_id = %d \
403 OR z.sub_type = 'LIST' AND z.sub_id = %d \
404 OR z.iws_type = 'LIST' AND z.iws_id = %d \
405 OR z.iui_type = 'LIST' AND z.iui_id = %d",id,id,id,id);
406 if(ec=mr_select_any(stmt_buf)) {
407 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
414 /* setup_dsin - verify that the service is no longer being referenced
415 * and may safely be deleted.
418 int setup_dsin(q, argv)
422 EXEC SQL BEGIN DECLARE SECTION;
425 EXEC SQL END DECLARE SECTION;
427 sprintf(stmt_buf,"SELECT service FROM serverhosts WHERE service = UPPERCASE('%s')",argv[0]);
428 if(ec=mr_select_any(stmt_buf)) {
436 EXEC SQL SELECT inprogress INTO :ec FROM servers
437 WHERE name=UPPERCASE(:svrname);
447 /* setup_dshi - verify that the service-host is no longer being referenced
448 * and may safely be deleted.
451 int setup_dshi(q, argv)
455 EXEC SQL BEGIN DECLARE SECTION;
458 EXEC SQL END DECLARE SECTION;
461 id = *(int *)argv[1];
463 EXEC SQL SELECT inprogress INTO :ec FROM serverhosts
464 WHERE service=UPPERCASE(:svrname) AND mach_id = :id;
476 ** setup_add_filesys - verify existance of referenced file systems
488 ** * extract directory prefix from name
489 ** * verify mach_id/dir in nfsphys
490 ** * verify access in {r, w, R, W}
492 ** Side effect: sets variable _var_phys_id to the ID of the physical
493 ** filesystem (nfsphys_id for NFS, 0 for RVD)
496 ** MR_NFS - specified directory not exported
497 ** MR_FILESYS_ACCESS - invalid filesys access
501 EXEC SQL BEGIN DECLARE SECTION;
503 EXEC SQL END DECLARE SECTION;
505 setup_afil(q, argv, cl)
512 EXEC SQL BEGIN DECLARE SECTION;
514 char ftype[32], *access;
515 EXEC SQL END DECLARE SECTION;
518 mach_id = *(int *)argv[2];
523 sprintf(ftype, "fs_access_%s", type);
524 EXEC SQL SELECT COUNT(trans) INTO :ok FROM alias
525 WHERE name = :ftype AND type = 'TYPE' and trans = :access;
526 if (ingres_errno) return(mr_errcode);
527 if (ok == 0) return(MR_FILESYS_ACCESS);
529 if((mr_errcode=prefetch_value(q,argv,cl))!=MR_SUCCESS)
532 if (!strcmp(type, "NFS"))
533 return (check_nfs(mach_id, name, access));
539 /* Verify the arguments, depending on the FStype. Also, if this is an
540 * NFS filesystem, then update any quotas for that filesystem to reflect
544 setup_ufil(q, argv, cl)
551 EXEC SQL BEGIN DECLARE SECTION;
552 int fid, total, who, ok;
553 char *entity, ftype[32], *access;
554 short int total_null;
555 EXEC SQL END DECLARE SECTION;
559 mach_id = *(int *)argv[3];
562 fid = *(int *)argv[0];
566 sprintf(ftype, "fs_access_%s", type);
567 EXEC SQL SELECT COUNT(trans) INTO :ok FROM alias
568 WHERE name = :ftype AND type='TYPE' AND trans = :access;
569 if (ingres_errno) return(mr_errcode);
570 if (ok == 0) return(MR_FILESYS_ACCESS);
572 EXEC SQL SELECT type INTO :ftype FROM filesys
573 WHERE filsys_id = :fid;
575 if (ingres_errno) return(mr_errcode);
577 if (!strcmp(type, "NFS")) {
578 status = check_nfs(mach_id, name, access);
579 EXEC SQL UPDATE quota SET phys_id = :_var_phys_id
580 WHERE filsys_id = :fid;
581 if (ingres_errno) return(mr_errcode);
583 } else if (!strcmp(type, "AFS") && strcmp(ftype, "AFS")) {
585 EXEC SQL REPEATED DELETE FROM quota
586 WHERE type = 'ANY' AND filsys_id = :fid;
587 EXEC SQL SELECT SUM (quota) INTO :total:total_null FROM quota
588 WHERE filsys_id = :fid AND phys_id != 0;
589 if (ingres_errno) return(mr_errcode);
590 if (!total_null && (total != 0)) {
592 * append quota (quota = total, filsys_id = fid,
593 * phys_id = 0, entity_id = 0, type = "ANY",
594 * modtime = "now", modby = who, modwith = entity)
596 EXEC SQL INSERT INTO quota (quota, filsys_id, phys_id, entity_id,
597 type, modtime, modby, modwith)
598 VALUES (:total, :fid, 0, 0,
599 'ANY', 'now', :who, :entity) ;
600 if (ingres_errno) return(mr_errcode);
603 EXEC SQL UPDATE quota SET phys_id = 0 WHERE filsys_id = :fid;
604 if (ingres_errno) return(mr_errcode);
610 /* Find the NFS physical partition that the named directory is on.
611 * This is done by comparing the dir against the mount point of the
612 * partition. To make sure we get the correct match when there is
613 * more than one, we sort the query in reverse order by dir name.
616 check_nfs(mach_id, name, access)
617 EXEC SQL BEGIN DECLARE SECTION;
619 EXEC SQL END DECLARE SECTION;
623 EXEC SQL BEGIN DECLARE SECTION;
625 EXEC SQL END DECLARE SECTION;
632 EXEC SQL DECLARE csr101 CURSOR FOR
633 SELECT nfsphys_id, TRIM (dir) FROM nfsphys
634 WHERE mach_id = :mach_id
638 EXEC SQL OPEN csr101;
642 EXEC SQL FETCH csr101 INTO :_var_phys_id, :dir;
643 if(sqlca.sqlcode != 0) break;
647 if (*cp1++ != *cp2) break;
655 EXEC SQL CLOSE csr101;
662 /* setup_dfil: free any quota records and fsgroup info associated with
663 * a filesystem when it is deleted. Also adjust the allocation numbers.
666 setup_dfil(q, argv, cl)
671 EXEC SQL BEGIN DECLARE SECTION;
672 int id, total, phys_id;
674 EXEC SQL END DECLARE SECTION;
676 id = *(int *)argv[0];
677 EXEC SQL REPEATED SELECT SUM (quota) INTO :total:none FROM quota
678 WHERE filsys_id = :id;
682 /** What if there are multiple phys_id's per f/s? (bad data) **/
683 EXEC SQL REPEATED SELECT phys_id INTO :phys_id FROM filesys
684 WHERE filsys_id = :id;
685 EXEC SQL REPEATED UPDATE nfsphys SET allocated = allocated - :total
686 WHERE nfsphys_id = :phys_id;
689 EXEC SQL REPEATED DELETE FROM quota WHERE filsys_id = :id;
691 EXEC SQL REPEATED DELETE FROM fsgroup WHERE filsys_id = :id;
692 EXEC SQL REPEATED DELETE FROM fsgroup WHERE group_id = :id;
693 if (ingres_errno) return(mr_errcode);
698 /* setup_dnfp: check to see that the nfs physical partition does not have
699 * any filesystems assigned to it before allowing it to be deleted.
702 setup_dnfp(q, argv, cl)
707 EXEC SQL BEGIN DECLARE SECTION;
710 EXEC SQL END DECLARE SECTION;
712 id = *(int *)argv[0];
714 EXEC SQL REPEATED SELECT count(fs.tid) INTO :cnt FROM filesys fs, nfsphys np
715 WHERE fs.mach_id = :id AND fs.phys_id = np.nfsphys_id
716 AND np.mach_id = :id AND np.dir = :dir;
725 /* setup_dqot: Remove allocation from nfsphys before deleting quota.
726 * argv[0] = filsys_id
727 * argv[1] = type if "update_quota" or "delete_quota"
728 * argv[2 or 1] = users_id or list_id
731 setup_dqot(q, argv, cl)
736 EXEC SQL BEGIN DECLARE SECTION;
737 int quota, fs, id, physid;
739 EXEC SQL END DECLARE SECTION;
741 fs = *(int *)argv[0];
742 if (!strcmp(q->name, "update_quota") || !strcmp(q->name, "delete_quota")) {
744 id = *(int *)argv[2];
747 id = *(int *)argv[1];
750 EXEC SQL REPEATED SELECT quota INTO :quota FROM quota
751 WHERE type = :qtype AND entity_id = :id AND filsys_id = :fs;
752 EXEC SQL REPEATED SELECT phys_id INTO :physid FROM filesys
753 WHERE filsys_id = :fs;
754 EXEC SQL REPEATED UPDATE nfsphys SET allocated = allocated - :quota
755 WHERE nfsphys_id = :physid;
757 if (ingres_errno) return(mr_errcode);
762 /* setup_sshi: don't exclusive lock the machine table during
763 * set_server_host_internal.
765 /** Not allowed under (INGRES) SQL **/
766 setup_sshi(q, argv, cl)
773 EXEC SQL set lockmode session where readlock = system;
780 /* setup add_kerberos_user_mapping: add the string to the string
781 * table if necessary.
784 setup_akum(q, argv, cl)
789 EXEC SQL BEGIN DECLARE SECTION;
792 EXEC SQL END DECLARE SECTION;
795 if (name_to_id(name, "STRING", &id) != MR_SUCCESS) {
796 if (q->type != APPEND) return(MR_STRING);
798 cache_entry(name, "STRING", id);
800 if (ingres_errno) return(mr_errcode);
801 *(int *)argv[1] = id;
807 * This routine fetches an appropriate value from the numvalues table.
808 * It is a little hack to get around the fact that SQL doesn't let you
809 * do something like INSERT INTO table (foo) VALUES (other_table.bar).
811 * It is called from the query table as (*v->pre_rtn)(q,Argv,cl) or
812 * from within a setup_...() routine with the appropriate arguments.
814 * Correct functioning of this routine may depend on the assumption
815 * that this query is an APPEND.
818 prefetch_value(q,argv,cl)
823 EXEC SQL BEGIN DECLARE SECTION;
824 char *name = q->validate->object_id;
826 EXEC SQL END DECLARE SECTION;
827 int status, limit, argc;
829 /* set next object id, limiting it if necessary */
830 if(!strcmp(name, "uid") || !strcmp(name, "gid"))
831 limit = 1; /* So far as I know, this isn't needed. Just CMA. */
834 if((status = set_next_object_id(name, q->rtable, limit)) != MR_SUCCESS)
837 /* fetch object id */
838 EXEC SQL SELECT value INTO :value FROM numvalues WHERE name=:name;
839 if(ingres_errno) return(mr_errcode);
840 if(sqlca.sqlerrd[2] != 1) return(MR_INTERNAL);
842 argc = q->argc + q->vcnt; /* end of Argv for APPENDs */
843 sprintf(argv[argc],"%d",value); /** Could save this step by changing tlist from %s to %d **/
848 /* prefetch_filesys():
849 * Fetches the phys_id from filesys based on the filsys_id in argv[0].
850 * Appends the filsys_id and the phys_id to the argv so they can be
851 * referenced in an INSERT into a table other than filesys. Also
852 * see comments at prefetch_value().
854 * Assumes the existence of a row where filsys_id = argv[0], since a
855 * filesys label has already been resolved to a filsys_id.
857 prefetch_filesys(q,argv,cl)
862 EXEC SQL BEGIN DECLARE SECTION;
864 EXEC SQL END DECLARE SECTION;
867 fid = *(int *)argv[0];
868 EXEC SQL SELECT phys_id INTO :phid FROM filesys WHERE filsys_id = :fid;
869 if(ingres_errno) return(mr_errcode);
871 argc=q->argc+q->vcnt;
872 sprintf(argv[argc++],"%d",phid);
873 sprintf(argv[argc],"%d",fid);
882 setup_ahst(q,argv,cl)
887 EXEC SQL BEGIN DECLARE SECTION;
889 int value, id, addr, mask, high, low, cnt;
890 EXEC SQL END DECLARE SECTION;
893 extern int host_access_level, privileged;
895 if (!strcmp(q->shortname, "uhst"))
900 /* sanity check name: must start with a letter, contain only
901 * letters, numerals, and hyphen, and not end with a hyphen.
903 if (row == 0 || strcmp(argv[1], cl->args->mr_argv[1])) {
906 if (!isalpha(*p)) return(MR_BAD_CHAR);
908 if ((!isalnum(*p) && *p != '-' && *p != '.') ||
909 (*p == '-' && p[1] == '.'))
912 if (*(p-1) == '-') return(MR_BAD_CHAR);
915 /* check for duplicate name */
917 EXEC SQL SELECT count(mach_id) INTO :cnt FROM hostalias
919 if (ingres_errno) return(mr_errcode);
920 if (cnt != 0) return(MR_EXISTS);
923 if (!strcmp(argv[9+row], "unassigned"))
925 else if (!strcmp(argv[9+row], "unique")) {
926 if (*(int *)argv[8+row] == 0)
931 value = ntohl(inet_addr(argv[9+row]));
932 if (value == -1) return(MR_ADDRESS);
934 if (value == 0) return(MR_ADDRESS);
936 id = *(int *)argv[8+row];
937 EXEC SQL SELECT saddr, mask, high, low INTO :addr, :mask, :high, :low
938 FROM subnet WHERE snet_id = :id;
939 if (ingres_errno) return(mr_errcode);
941 if ((value & mask) != addr) return(MR_ADDRESS);
943 EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine
944 WHERE address = :name;
945 if (ingres_errno) return(mr_errcode);
947 if (row == 0 || row == 1 && cnt > 1) return(MR_ADDRESS);
948 if (row == 1 && cnt == 1) {
949 EXEC SQL SELECT mach_id INTO :id FROM machine
950 WHERE address = :name;
951 if (id != *(int *)argv[0]) return(MR_ADDRESS);
955 for (id = low; id <= high; id++) {
956 if (((id & 0xff) == 0) ||
957 ((id & 0xff) == 255))
960 name = (char *)inet_ntoa(value);
961 EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine
962 WHERE address = :name;
963 if (ingres_errno) return(mr_errcode);
969 value = htonl(value);
971 value = htonl(value);
972 argv[9+row] = strsave(inet_ntoa(value));
974 argv[9+row] = strsave("unassigned");
977 /* status checking */
978 value = atoi(argv[7+row]);
979 if (row == 0 && !(value == 1 || value == 3))
982 id = *(int *)argv[0];
983 EXEC SQL SELECT status INTO :cnt FROM machine WHERE mach_id = :id;
984 if (ingres_errno) return(mr_errcode);
986 EXEC SQL UPDATE machine SET statuschange = date('now');
990 if (row == 0 && !privileged) {
991 /* subnet owner is adding a host */
992 /* Non-query owner must set use to zero */
993 if (atoi(argv[6]) != 0) return(MR_PERM);
994 } else if (row == 1 && !privileged) {
995 EXEC SQL BEGIN DECLARE SECTION;
996 int i8, i12, i13, i7, i9, i14;
997 char s6[33], s10[33], s11[9];
998 EXEC SQL END DECLARE SECTION;
999 /* Non-query owner is restricted in changes that can be made */
1000 id = *(int *)argv[0];
1001 EXEC SQL SELECT contact, status, address, owner_type, owner_id,
1002 acomment, use, snet_id, ocomment INTO :s6, :i8, :s10, :s11, :i12,
1003 :i13, :i7, :i9, :i14 FROM machine WHERE mach_id = :id;
1004 if (ingres_errno) return(mr_errcode);
1005 /* subnet owner cannot change use or ocomment */
1006 if ((i7 != atoi(argv[7])) || (i14 != *(int *)argv[14]))
1008 /* host owner cannot change contact, status, address, owner_type,
1009 * owner_id, acomment, or subnet */
1010 if (host_access_level == 2 &&
1011 (strcmp(argv[6], strtrim(s6)) || (i8 != atoi(argv[8])) ||
1012 strcmp(argv[10], strtrim(s10)) || strcmp(argv[11], strtrim(s11)) ||
1013 (i12 != *(int *)argv[12]) || (i13 != *(int *)argv[13]) ||
1014 (i9 = *(int *)argv[9])))
1018 if ((mr_errcode = prefetch_value(q,argv,cl)) != MR_SUCCESS)
1021 row = q->argc + q->vcnt + 1;
1022 sprintf(buf, "%d",cl->client_id);
1023 argv[row] = strsave(buf);
1032 setup_ahal(q,argv,cl)
1037 EXEC SQL BEGIN DECLARE SECTION;
1040 EXEC SQL END DECLARE SECTION;
1044 if (!isalpha(*p)) return(MR_BAD_CHAR);
1046 if ((!isalnum(*p) && *p != '-' && *p != '.') ||
1047 (*p == '-' && p[1] == '.'))
1048 return(MR_BAD_CHAR);
1050 if (*(p-1) == '-') return(MR_BAD_CHAR);
1052 EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine WHERE
1054 if (ingres_errno) return(mr_errcode);
1055 if (cnt > 0) return(MR_EXISTS);