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>
17 #include "mr_server.h"
20 #include <arpa/inet.h>
21 EXEC SQL INCLUDE sqlca;
24 extern char *whoami, *strsave();
25 extern int dbms_errno, mr_errcode;
27 EXEC SQL BEGIN DECLARE SECTION;
28 extern char stmt_buf[];
29 EXEC SQL END DECLARE SECTION;
31 EXEC SQL WHENEVER SQLERROR DO dbmserr();
34 int prefetch_value(struct query *q, char **argv, client *cl);
35 int check_nfs(int mach_idx, char *name, char *access);
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 int setup_ausr(struct query *q, char *argv[], client *cl)
53 EXEC SQL BEGIN DECLARE SECTION;
55 EXEC SQL END DECLARE SECTION;
57 if (!strcmp(q->shortname, "uusr") || !strcmp(q->shortname, "uuac"))
61 if (!strcmp(argv[row], UNIQUE_UID) || atoi(argv[row]) == -1)
63 if ((err = set_next_object_id("unix_uid", USERS_TABLE, 1)))
65 EXEC SQL SELECT value INTO :nuid FROM numvalues WHERE name = 'unix_uid';
66 if (sqlca.sqlerrd[2] != 1)
68 sprintf(argv[row], "%d", nuid);
71 if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[row]) == -1)
72 sprintf(argv[0], "#%s", argv[row]);
74 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
81 /* setup_dusr - verify that the user is no longer being referenced
82 * and may safely be deleted.
85 int setup_dusr(struct query *q, char **argv)
87 EXEC SQL BEGIN DECLARE SECTION;
89 EXEC SQL END DECLARE SECTION;
93 /* For now, only allow users to be deleted if their status is 0 */
94 EXEC SQL SELECT status INTO :flag FROM users WHERE users_id = :id;
95 if (flag != 0 && flag != 4)
98 EXEC SQL DELETE FROM quota WHERE entity_id = :id AND type = 'USER';
99 EXEC SQL DELETE FROM krbmap WHERE users_id = :id;
100 EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
101 WHERE member_id = :id AND member_type = 'USER';
104 EXEC SQL SELECT COUNT(label) INTO :cnt FROM filesys
108 EXEC SQL SELECT COUNT(name) INTO :cnt FROM list
109 WHERE acl_id = :id AND acl_type = 'USER';
112 EXEC SQL SELECT COUNT(name) INTO :cnt FROM servers
113 WHERE acl_id = :id AND acl_type = 'USER';
116 EXEC SQL SELECT COUNT(acl_id) INTO :cnt FROM hostaccess
117 WHERE acl_id = :id AND acl_type = 'USER';
126 /* setup_spop: verify that there is already a valid POP machine_id in the
127 * pop_id field. Also take care of keeping track of the post office usage.
129 int setup_spop(struct query *q, char **argv)
131 EXEC SQL BEGIN DECLARE SECTION;
134 EXEC SQL END DECLARE SECTION;
136 id = *(int *)argv[0];
137 EXEC SQL SELECT potype, pop_id INTO :type, :mid FROM users
138 WHERE users_id = :id;
139 if (sqlca.sqlerrd[2] = 0)
141 EXEC SQL SELECT mach_id INTO :mid FROM machine
142 WHERE mach_id = :mid;
143 if (sqlca.sqlerrd[2] = 0)
145 if (strcmp(strtrim(type), "POP"))
146 set_pop_usage(mid, 1);
151 /* setup_dpob: Take care of keeping track of the post office usage.
153 int setup_dpob(struct query *q, char **argv)
155 EXEC SQL BEGIN DECLARE SECTION;
158 EXEC SQL END DECLARE SECTION;
160 user = *(int *)argv[0];
161 EXEC SQL SELECT potype, pop_id INTO :type, :id FROM users
162 WHERE users_id = :user;
166 if (!strcmp(strtrim(type), "POP"))
167 set_pop_usage(id, -1);
172 /* setup_dmac - verify that the machine is no longer being referenced
173 * and may safely be deleted.
176 int setup_dmac(struct query *q, char **argv)
178 EXEC SQL BEGIN DECLARE SECTION;
180 EXEC SQL END DECLARE SECTION;
182 id = *(int *)argv[0];
184 EXEC SQL SELECT status INTO :flag FROM machine
188 EXEC SQL SELECT COUNT(login) INTO :cnt FROM users
189 WHERE potype = 'POP' AND pop_id = :id;
192 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM serverhosts
196 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM nfsphys
200 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM hostaccess
204 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM printcap
208 EXEC SQL SELECT COUNT(quotaserver) INTO :cnt FROM printcap
209 WHERE quotaserver = :id;
212 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM palladium
216 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM hostalias
221 EXEC SQL DELETE FROM mcmap WHERE mach_id = :id;
228 /* setup_dsnt - verify that the subnet is no longer being referenced
229 * and may safely be deleted.
232 int setup_dsnt(struct query *q, char **argv)
234 EXEC SQL BEGIN DECLARE SECTION;
236 EXEC SQL END DECLARE SECTION;
238 id = *(int *)argv[0];
239 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM machine
247 /* setup_dclu - verify that the cluster is no longer being referenced
248 * and may safely be deleted.
251 int setup_dclu(struct query *q, char **argv)
253 EXEC SQL BEGIN DECLARE SECTION;
255 EXEC SQL END DECLARE SECTION;
257 id = *(int *)argv[0];
258 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM mcmap
262 EXEC SQL SELECT COUNT(clu_id) INTO :cnt FROM svc
272 /* setup_alis - if argv[5] is non-zero and argv[6] is UNIQUE_ID, then allocate
273 * a new gid and put it in argv[6]. Otherwise if argv[6] is UNIQUE_ID but
274 * argv[5] is not, then remember that UNIQUE_ID is being stored by putting
275 * a -1 there. Remember that this is also used for ulis, with the indexes
276 * at 6 & 7. Also check that the list name does not contain uppercase
277 * characters, control characters, @, or :.
280 static int badlistchars[] = {
281 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
282 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
283 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
284 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, /* 0 - ? */
285 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
286 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, /* P - _ */
287 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
288 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
289 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
290 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
291 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
292 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
293 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
294 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
295 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
296 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
299 int setup_alis(struct query *q, char *argv[], client *cl)
301 EXEC SQL BEGIN DECLARE SECTION;
303 EXEC SQL END DECLARE SECTION;
307 if (!strcmp(q->shortname, "alis"))
309 else if (!strcmp(q->shortname, "ulis"))
312 for (p = (unsigned char *) argv[idx]; *p; p++)
314 if (badlistchars[*p])
318 if (!strcmp(argv[6 + idx], UNIQUE_GID) || atoi(argv[6 + idx]) == -1)
320 if (atoi(argv[5 + idx]))
322 if ((err = set_next_object_id("gid", LIST_TABLE, 1)))
324 EXEC SQL SELECT value INTO :ngid FROM numvalues
328 sprintf(argv[6 + idx], "%d", ngid);
331 strcpy(argv[6 + idx], "-1");
334 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
341 /* setup_dlis - verify that the list is no longer being referenced
342 * and may safely be deleted.
345 int setup_dlis(struct query *q, char **argv)
348 EXEC SQL BEGIN DECLARE SECTION;
350 EXEC SQL END DECLARE SECTION;
352 id = *(int *)argv[0];
354 EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
355 WHERE member_id = :id AND member_type = 'LIST';
359 EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
360 WHERE member_id = :id AND member_type = 'LIST';
364 EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
369 EXEC SQL SELECT COUNT(label) INTO :cnt FROM filesys WHERE owners = :id;
373 EXEC SQL SELECT COUNT(tag) INTO :cnt FROM capacls WHERE list_id = :id;
377 EXEC SQL SELECT COUNT(name) INTO :cnt FROM list
378 WHERE acl_id = :id AND acl_type = 'LIST' AND list_id != :id;
382 EXEC SQL SELECT COUNT(name) INTO :cnt FROM servers
383 WHERE acl_id = :id AND acl_type = 'LIST';
387 EXEC SQL SELECT COUNT(entity_id) INTO :cnt FROM quota
388 WHERE entity_id = :id AND type = 'GROUP';
392 EXEC SQL SELECT COUNT(acl_id) INTO :cnt FROM hostaccess
393 WHERE acl_id = :id AND acl_type = 'LIST';
397 EXEC SQL SELECT COUNT(class) INTO :cnt FROM zephyr z
398 WHERE z.xmt_type = 'LIST' AND z.xmt_id = :id
399 OR z.sub_type = 'LIST' AND z.sub_id = :id
400 OR z.iws_type = 'LIST' AND z.iws_id = :id
401 OR z.iui_type = 'LIST' AND z.iui_id = :id;
409 /* setup_dsin - verify that the service is no longer being referenced
410 * and may safely be deleted.
413 int setup_dsin(struct query *q, char **argv)
415 EXEC SQL BEGIN DECLARE SECTION;
418 EXEC SQL END DECLARE SECTION;
421 EXEC SQL SELECT COUNT(service) INTO :cnt FROM serverhosts
422 WHERE service = UPPER(:svrname);
426 EXEC SQL SELECT inprogress INTO :ec FROM servers
427 WHERE name = UPPER(:svrname);
437 /* setup_dshi - verify that the service-host is no longer being referenced
438 * and may safely be deleted.
441 int setup_dshi(struct query *q, char **argv)
443 EXEC SQL BEGIN DECLARE SECTION;
446 EXEC SQL END DECLARE SECTION;
449 id = *(int *)argv[1];
451 EXEC SQL SELECT inprogress INTO :ec FROM serverhosts
452 WHERE service = UPPER(:svrname) AND mach_id = :id;
463 ** setup_add_filesys - verify existance of referenced file systems
469 ** argv[5] - rwaccess
475 ** * extract directory prefix from name
476 ** * verify mach_id/dir in nfsphys
477 ** * verify rwaccess in {r, w, R, W}
479 ** Side effect: sets variable _var_phys_id to the ID of the physical
480 ** filesystem (nfsphys_id for NFS, 0 for RVD)
483 ** MR_NFS - specified directory not exported
484 ** MR_FILESYS_ACCESS - invalid filesys access
488 EXEC SQL BEGIN DECLARE SECTION;
490 EXEC SQL END DECLARE SECTION;
492 int setup_afil(struct query *q, char *argv[], client *cl)
496 EXEC SQL BEGIN DECLARE SECTION;
498 char ftype[32], *rwaccess;
499 EXEC SQL END DECLARE SECTION;
502 mach_id = *(int *)argv[2];
507 sprintf(ftype, "fs_access_%s", type);
508 EXEC SQL SELECT COUNT(trans) INTO :ok FROM alias
509 WHERE name = :ftype AND type = 'TYPE' and trans = :rwaccess;
513 return MR_FILESYS_ACCESS;
515 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
518 if (!strcmp(type, "NFS"))
519 return check_nfs(mach_id, name, rwaccess);
525 /* Verify the arguments, depending on the FStype. Also, if this is an
526 * NFS filesystem, then update any quotas for that filesystem to reflect
530 int setup_ufil(struct query *q, char *argv[], client *cl)
534 EXEC SQL BEGIN DECLARE SECTION;
535 int fid, total, who, ok;
536 char *entity, ftype[32], *access;
537 short int total_null;
538 EXEC SQL END DECLARE SECTION;
542 mach_id = *(int *)argv[3];
545 fid = *(int *)argv[0];
549 sprintf(ftype, "fs_access_%s", type);
550 EXEC SQL SELECT COUNT(trans) INTO :ok FROM alias
551 WHERE name = :ftype AND type = 'TYPE' AND trans = :access;
555 return MR_FILESYS_ACCESS;
557 EXEC SQL SELECT type INTO :ftype FROM filesys
558 WHERE filsys_id = :fid;
562 if (!strcmp(type, "NFS"))
564 status = check_nfs(mach_id, name, access);
565 EXEC SQL UPDATE quota SET phys_id = :_var_phys_id
566 WHERE filsys_id = :fid;
571 else if (!strcmp(type, "AFS") && strcmp(strtrim(ftype), "AFS")
572 && strcmp(strtrim(ftype), "ERR"))
575 EXEC SQL DELETE FROM quota
576 WHERE type = 'ANY' AND filsys_id = :fid;
577 EXEC SQL SELECT SUM (quota) INTO :total:total_null FROM quota
578 WHERE filsys_id = :fid AND phys_id != 0;
581 if (!total_null && (total != 0))
583 EXEC SQL INSERT INTO quota (quota, filsys_id, phys_id, entity_id,
584 type, modtime, modby, modwith)
585 VALUES (:total, :fid, 0, 0, 'ANY', SYSDATE, :who, :entity);
592 EXEC SQL UPDATE quota SET phys_id = 0 WHERE filsys_id = :fid;
600 /* Find the NFS physical partition that the named directory is on.
601 * This is done by comparing the dir against the mount point of the
602 * partition. To make sure we get the correct match when there is
603 * more than one, we sort the query in reverse order by dir name.
606 int check_nfs(int mach_id, char *name, char *access)
608 EXEC SQL BEGIN DECLARE SECTION;
611 EXEC SQL END DECLARE SECTION;
617 EXEC SQL DECLARE csr101 CURSOR FOR
618 SELECT nfsphys_id, dir FROM nfsphys
623 EXEC SQL OPEN csr101;
628 EXEC SQL FETCH csr101 INTO :_var_phys_id, :dir;
645 EXEC SQL CLOSE csr101;
652 /* setup_dfil: free any quota records and fsgroup info associated with
653 * a filesystem when it is deleted. Also adjust the allocation numbers.
656 int setup_dfil(struct query *q, char **argv, client *cl)
658 EXEC SQL BEGIN DECLARE SECTION;
659 int id, total, phys_id;
661 EXEC SQL END DECLARE SECTION;
663 id = *(int *)argv[0];
664 EXEC SQL SELECT SUM (quota) INTO :total:none FROM quota
665 WHERE filsys_id = :id;
670 /** What if there are multiple phys_id's per f/s? (bad data) **/
671 EXEC SQL SELECT phys_id INTO :phys_id FROM filesys
672 WHERE filsys_id = :id;
673 EXEC SQL UPDATE nfsphys SET allocated = allocated - :total
674 WHERE nfsphys_id = :phys_id;
677 EXEC SQL DELETE FROM quota WHERE filsys_id = :id;
678 EXEC SQL DELETE FROM fsgroup WHERE filsys_id = :id;
679 EXEC SQL DELETE FROM fsgroup WHERE group_id = :id;
686 /* setup_dnfp: check to see that the nfs physical partition does not have
687 * any filesystems assigned to it before allowing it to be deleted.
690 int setup_dnfp(struct query *q, char **argv, client *cl)
692 EXEC SQL BEGIN DECLARE SECTION;
695 EXEC SQL END DECLARE SECTION;
697 id = *(int *)argv[0];
699 EXEC SQL SELECT count(fs.rowid) INTO :cnt FROM filesys fs, nfsphys np
700 WHERE fs.mach_id = :id AND fs.phys_id = np.nfsphys_id
701 AND np.mach_id = :id AND np.dir = :dir;
710 /* setup_dqot: Remove allocation from nfsphys before deleting quota.
711 * argv[0] = filsys_id
712 * argv[1] = type if "update_quota" or "delete_quota"
713 * argv[2 or 1] = users_id or list_id
716 int setup_dqot(struct query *q, char **argv, client *cl)
718 EXEC SQL BEGIN DECLARE SECTION;
719 int quota, fs, id, physid;
721 EXEC SQL END DECLARE SECTION;
723 fs = *(int *)argv[0];
724 if (!strcmp(q->name, "update_quota") || !strcmp(q->name, "delete_quota"))
727 id = *(int *)argv[2];
732 id = *(int *)argv[1];
735 EXEC SQL SELECT quota INTO :quota FROM quota
736 WHERE type = :qtype AND entity_id = :id AND filsys_id = :fs;
737 EXEC SQL SELECT phys_id INTO :physid FROM filesys
738 WHERE filsys_id = :fs;
739 EXEC SQL UPDATE nfsphys SET allocated = allocated - :quota
740 WHERE nfsphys_id = :physid;
748 /* setup add_kerberos_user_mapping: add the string to the string
749 * table if necessary.
752 int setup_akum(struct query *q, char **argv, client *cl)
754 EXEC SQL BEGIN DECLARE SECTION;
757 EXEC SQL END DECLARE SECTION;
760 if (name_to_id(name, STRINGS_TABLE, &id) != MR_SUCCESS)
762 if (q->type != APPEND)
764 id = add_string(name);
765 cache_entry(name, STRINGS_TABLE, id);
769 *(int *)argv[1] = id;
775 * This routine fetches an appropriate value from the numvalues table.
776 * It is a little hack to get around the fact that SQL doesn't let you
777 * do something like INSERT INTO table (foo) VALUES (other_table.bar).
779 * It is called from the query table as (*v->pre_rtn)(q, Argv, cl) or
780 * from within a setup_...() routine with the appropriate arguments.
782 * Correct functioning of this routine may depend on the assumption
783 * that this query is an APPEND.
786 int prefetch_value(struct query *q, char **argv, client *cl)
788 EXEC SQL BEGIN DECLARE SECTION;
789 char *name = q->validate->object_id;
791 EXEC SQL END DECLARE SECTION;
792 int status, limit, argc;
794 /* set next object id, limiting it if necessary */
795 if (!strcmp(name, "unix_uid") || !strcmp(name, "gid"))
796 limit = 1; /* So far as I know, this isn't needed. Just CMA. */
799 if ((status = set_next_object_id(name, q->rtable, limit)) != MR_SUCCESS)
802 /* fetch object id */
803 EXEC SQL SELECT value INTO :value FROM numvalues WHERE name = :name;
806 if (sqlca.sqlerrd[2] != 1)
809 argc = q->argc + q->vcnt; /* end of Argv for APPENDs */
810 sprintf(argv[argc], "%d", value);
815 /* prefetch_filesys():
816 * Fetches the phys_id from filesys based on the filsys_id in argv[0].
817 * Appends the filsys_id and the phys_id to the argv so they can be
818 * referenced in an INSERT into a table other than filesys. Also
819 * see comments at prefetch_value().
821 * Assumes the existence of a row where filsys_id = argv[0], since a
822 * filesys label has already been resolved to a filsys_id.
824 int prefetch_filesys(struct query *q, char **argv, client *cl)
826 EXEC SQL BEGIN DECLARE SECTION;
828 EXEC SQL END DECLARE SECTION;
831 fid = *(int *)argv[0];
832 EXEC SQL SELECT phys_id INTO :phid FROM filesys WHERE filsys_id = :fid;
836 argc = q->argc + q->vcnt;
837 sprintf(argv[argc++], "%d", phid);
838 sprintf(argv[argc], "%d", fid);
847 int setup_ahst(struct query *q, char **argv, client *cl)
849 EXEC SQL BEGIN DECLARE SECTION;
851 int value, id, saddr, mask, high, low, cnt;
852 EXEC SQL END DECLARE SECTION;
855 extern int host_access_level, privileged;
857 if (!strcmp(q->shortname, "uhst"))
862 /* sanity check name: must start with a letter, contain only
863 * letters, numerals, and hyphen, and not end with a hyphen.
865 if (row == 0 || strcmp(argv[1], cl->args->mr_argv[1]))
873 if ((!isalnum(*p) && *p != '-' && *p != '.') ||
874 (*p == '-' && p[1] == '.'))
881 /* sanity check host vendor: must start with a letter, contain only
882 * letters, numerals, and hyphen, and end with an alphanumeric.
884 if (*argv[row + 1] && (row == 0 || strcmp(argv[2], cl->args->mr_argv[2])))
886 char *p = argv[row + 1];
892 if ((!isalnum(*p) && *p != '-' && *p != '.') ||
893 (*p == '-' && p[1] == '.'))
896 if (!isalnum(*(p - 1)))
900 /* sanity check host type: must start with a letter, contain only
901 * letters, numerals, and hyphen, and end with an alphanumeric.
903 if (*argv[row + 2] && (row == 0 || strcmp(argv[3], cl->args->mr_argv[3])))
905 char *p = argv[row + 2];
911 if ((!isalnum(*p) && *p != '-' && *p != '.') ||
912 (*p == '-' && p[1] == '.'))
915 if (!isalnum(*(p - 1)))
919 /* sanity check host vendor: must start with a letter, contain only
920 * letters, numerals, and hyphen, and end with an hyphen alphanumeric.
922 if (*argv[row + 3] && (row == 0 || strcmp(argv[4], cl->args->mr_argv[4])))
924 char *p = argv[row + 3];
930 if ((!isalnum(*p) && *p != '-' && *p != '.') ||
931 (*p == '-' && p[1] == '.'))
934 if (!isalnum(*(p - 1)))
938 /* check for duplicate name */
940 EXEC SQL SELECT count(mach_id) INTO :cnt FROM hostalias
948 if (!strcmp(argv[9 + row], "unassigned"))
950 else if (!strcmp(argv[9 + row], "unique"))
952 if (*(int *)argv[8 + row] == 0)
959 value = ntohl(inet_addr(argv[9 + row]));
968 * an address or unique was specified.
970 id = *(int *)argv[8 + row];
971 EXEC SQL SELECT saddr, mask, high, low INTO :saddr, :mask, :high, :low
972 FROM subnet WHERE snet_id = :id;
978 * someone specified an IP address for the host record
980 if ((value & mask) != saddr)
983 * run the address argument through inet_addr(). This
984 * has the effect that any out of bounds host addrs will
985 * be converted to a valid host addr. We do this now
986 * so that the uniqueness check works. We should also
987 * link in an inet_addr() that returns an error for
990 addr.s_addr = inet_addr(argv[9 + row]);
991 name = inet_ntoa(addr);
992 EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine
993 WHERE address = :name;
999 * make IP address is unique. If this a modify request
1000 * (row == 1), then we expect one record to exist.
1002 if (row == 0 || row == 1 && cnt > 1)
1004 if (row == 1 && cnt == 1)
1006 EXEC SQL SELECT mach_id INTO :id FROM machine
1007 WHERE address = :name;
1008 if (id != *(int *)argv[0])
1016 * a "unique" address was specified. Walk through the
1017 * range specified in the network record, return
1018 * error if no room left.
1020 for (id = low; id <= high; id++)
1022 if (((id & 0xff) == 0) || ((id & 0xff) == 255))
1024 addr.s_addr = htonl(id);
1025 name = (char *)inet_ntoa(addr);
1026 EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine
1027 WHERE address = :name;
1039 * we have an address in value. Convert it to a string and store it.
1041 addr.s_addr = htonl(value);
1042 strcpy(argv[9 + row], inet_ntoa(addr));
1045 strcpy(argv[9 + row], "unassigned");
1047 /* status checking */
1048 value = atoi(argv[7 + row]);
1049 if (row == 0 && !(value == 1 || value == 0))
1053 id = *(int *)argv[0];
1054 EXEC SQL SELECT status INTO :cnt FROM machine WHERE mach_id = :id;
1059 EXEC SQL UPDATE machine SET statuschange = SYSDATE
1060 WHERE mach_id = :id;
1064 if (row == 0 && !privileged)
1066 /* subnet owner is adding a host */
1067 /* Non-query owner must set use to zero */
1068 if (atoi(argv[6]) != 0)
1071 else if (row == 1 && !privileged)
1073 EXEC SQL BEGIN DECLARE SECTION;
1074 int i8, i12, i13, i7, i9, i14;
1075 char s6[33], s10[33], s11[9];
1076 EXEC SQL END DECLARE SECTION;
1077 /* Non-query owner is restricted in changes that can be made */
1078 id = *(int *)argv[0];
1079 EXEC SQL SELECT contact, status, address, owner_type, owner_id,
1080 acomment, use, snet_id, ocomment INTO :s6, :i8, :s10, :s11,
1081 :i12, :i13, :i7, :i9, :i14 FROM machine WHERE mach_id = :id;
1084 /* subnet owner cannot change use, comment, or network */
1085 if ((i7 != atoi(argv[7])) || (i14 != *(int *)argv[14]) ||
1086 (i9 != *(int *)argv[9]))
1088 /* host owner cannot change contact, status, address, owner_type,
1089 * owner_id, acomment, or subnet */
1090 if (host_access_level == 2 &&
1091 (strcmp(argv[6], strtrim(s6)) || (i8 != atoi(argv[8])) ||
1092 strcmp(argv[10], strtrim(s10)) || strcmp(argv[11], strtrim(s11)) ||
1093 (i12 != *(int *)argv[12]) || (i13 != *(int *)argv[13]) ||
1094 (i9 != *(int *)argv[9])))
1099 * If this is an update_host query, we're done.
1105 * For an add_host query, allocate and fill in a new machine id,
1106 * and then insert the creator id.
1108 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
1111 sprintf(argv[q->argc + q->vcnt + 1], "%d", cl->client_id);
1119 int setup_ahal(struct query *q, char **argv, client *cl)
1121 EXEC SQL BEGIN DECLARE SECTION;
1124 EXEC SQL END DECLARE SECTION;
1132 if ((!isalnum(*p) && *p != '-' && *p != '.') ||
1133 (*p == '-' && p[1] == '.'))
1136 if (*(p - 1) == '-')
1139 EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine WHERE