5 * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology
6 * For copying and distribution information, please see the file
10 #include <mit-copyright.h>
11 #include "mr_server.h"
15 #include <arpa/inet.h>
16 #include <netinet/in.h>
22 EXEC SQL INCLUDE sqlca;
27 extern int dbms_errno, mr_errcode;
29 EXEC SQL BEGIN DECLARE SECTION;
30 extern char stmt_buf[];
31 EXEC SQL END DECLARE SECTION;
33 EXEC SQL WHENEVER SQLERROR DO dbmserr();
35 int hostname_check(char *name);
36 int hostinfo_check(char *name, int num);
37 int prefetch_value(struct query *q, char **argv, client *cl);
38 int check_nfs(int mach_idx, char *name, char *access);
42 /* Setup routine for add_user
44 * Inputs: argv[0] - login
49 * - if argv[1] == UNIQUE_UID then set argv[1] = next(uid)
50 * - if argv[0] == UNIQUE_LOGIN then set argv[0] = "#<uid>"
53 int setup_ausr(struct query *q, char *argv[], client *cl)
56 EXEC SQL BEGIN DECLARE SECTION;
58 EXEC SQL END DECLARE SECTION;
60 if (!strcmp(q->shortname, "uusr") || !strcmp(q->shortname, "uuac"))
67 if (strlen(argv[row + 3]) + strlen(argv[row + 4]) +
68 strlen(argv[row + 5]) + 2 > USERS_FULLNAME_SIZE)
69 return MR_ARG_TOO_LONG;
73 if (strlen(argv[row + 2]) + strlen(argv[row + 3]) +
74 strlen(argv[row + 4]) + 2 > USERS_FULLNAME_SIZE)
75 return MR_ARG_TOO_LONG;
78 if (!strcmp(argv[row], UNIQUE_UID) || atoi(argv[row]) == -1)
80 if ((err = set_next_object_id("unix_uid", USERS_TABLE, 1)))
82 EXEC SQL SELECT value INTO :nuid FROM numvalues WHERE name = 'unix_uid';
83 if (sqlca.sqlerrd[2] != 1)
85 sprintf(argv[row], "%d", nuid);
88 if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[row]) == -1)
89 sprintf(argv[0], "#%s", argv[row]);
91 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
98 /* setup_dusr - verify that the user is no longer being referenced
99 * and may safely be deleted.
102 int setup_dusr(struct query *q, char *argv[], client *cl)
104 EXEC SQL BEGIN DECLARE SECTION;
106 char resv[USERS_RESERVATIONS_SIZE];
107 EXEC SQL END DECLARE SECTION;
109 id = *(int *)argv[0];
111 /* For now, only allow users to be deleted if their status is 0
112 * and we have no reservations about deleting them.
114 EXEC SQL SELECT status, reservations INTO :flag, :resv
115 FROM users WHERE users_id = :id;
116 if ((flag != 0 && flag != 4) || *resv)
119 EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
120 WHERE member_id = :id AND member_type = 'USER';
123 EXEC SQL SELECT COUNT(label) INTO :cnt FROM filesys
127 EXEC SQL SELECT COUNT(name) INTO :cnt FROM list
128 WHERE acl_id = :id AND acl_type = 'USER';
131 EXEC SQL SELECT COUNT(name) INTO :cnt FROM servers
132 WHERE acl_id = :id AND acl_type = 'USER';
135 EXEC SQL SELECT COUNT(acl_id) INTO :cnt FROM hostaccess
136 WHERE acl_id = :id AND acl_type = 'USER';
142 EXEC SQL DELETE FROM quota WHERE entity_id = :id AND type = 'USER';
143 EXEC SQL DELETE FROM krbmap WHERE users_id = :id;
148 /* setup_dpob: Take care of keeping track of the post office usage.
150 int setup_dpob(struct query *q, char *argv[], client *cl)
152 EXEC SQL BEGIN DECLARE SECTION;
154 char type[USERS_POTYPE_SIZE];
155 EXEC SQL END DECLARE SECTION;
157 user = *(int *)argv[0];
158 EXEC SQL SELECT potype, pop_id INTO :type, :id FROM users
159 WHERE users_id = :user;
163 if (!strcmp(strtrim(type), "POP"))
164 set_pop_usage(id, -1);
169 /* setup_dmac - verify that the machine is no longer being referenced
170 * and may safely be deleted.
173 int setup_dmac(struct query *q, char *argv[], client *cl)
175 EXEC SQL BEGIN DECLARE SECTION;
177 EXEC SQL END DECLARE SECTION;
179 id = *(int *)argv[0];
181 EXEC SQL SELECT status INTO :flag FROM machine
185 EXEC SQL SELECT COUNT(login) INTO :cnt FROM users
186 WHERE potype = 'POP' AND pop_id = :id;
189 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM serverhosts
193 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM nfsphys
197 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM hostaccess
201 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM printers
205 EXEC SQL SELECT COUNT(rm) INTO :cnt FROM printers
209 EXEC SQL SELECT COUNT(rq) INTO :cnt FROM printers
213 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM printservers
217 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM hostalias
222 EXEC SQL DELETE FROM mcmap WHERE mach_id = :id;
229 /* setup_dsnt - verify that the subnet is no longer being referenced
230 * and may safely be deleted.
233 int setup_dsnt(struct query *q, char *argv[], client *cl)
235 EXEC SQL BEGIN DECLARE SECTION;
237 EXEC SQL END DECLARE SECTION;
239 id = *(int *)argv[0];
240 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM machine
248 /* setup_dclu - verify that the cluster is no longer being referenced
249 * and may safely be deleted.
252 int setup_dclu(struct query *q, char *argv[], client *cl)
254 EXEC SQL BEGIN DECLARE SECTION;
256 EXEC SQL END DECLARE SECTION;
258 id = *(int *)argv[0];
259 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM mcmap
263 EXEC SQL SELECT COUNT(clu_id) INTO :cnt FROM svc
273 /* setup_alis - if argv[5] is non-zero and argv[6] is UNIQUE_ID, then allocate
274 * a new gid and put it in argv[6]. Otherwise if argv[6] is UNIQUE_ID but
275 * argv[5] is not, then remember that UNIQUE_ID is being stored by putting
276 * a -1 there. Remember that this is also used for ulis, with the indexes
277 * at 6 & 7. Also check that the list name does not contain uppercase
278 * characters, control characters, @, or :.
280 * Newlines in list descriptions do bad things to the aliases file
281 * moira generates, so make sure the description doesn't contain any, too.
284 static int badlistchars[] = {
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, 1, 1, /* ^P - ^_ */
287 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, /* SPACE - / */
288 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 0 - ? */
289 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
290 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* P - _ */
291 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
292 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
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,
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,
303 int setup_alis(struct query *q, char *argv[], client *cl)
305 EXEC SQL BEGIN DECLARE SECTION;
308 EXEC SQL END DECLARE SECTION;
312 if (!strcmp(q->shortname, "alis"))
314 else if (!strcmp(q->shortname, "ulis"))
317 desc = argv[10 + idx];
321 EXEC SQL BEGIN DECLARE SECTION;
322 int lid = *(int *)argv[0];
323 EXEC SQL END DECLARE SECTION;
325 if (acl_access_check(lid, cl))
329 for (p = (unsigned char *) name; *p; p++)
331 if (badlistchars[*p])
335 for (p = (unsigned char *) desc; *p; p++)
341 /* Check that it doesn't conflict with a pre-existing weirdly-cased
343 EXEC SQL SELECT COUNT(name) INTO :cnt FROM list
344 WHERE LOWER(name) = :name AND name != :name;
348 if (!strcmp(argv[6 + idx], UNIQUE_GID) || atoi(argv[6 + idx]) == -1)
350 if (atoi(argv[5 + idx]))
352 if ((err = set_next_object_id("gid", LIST_TABLE, 1)))
354 EXEC SQL SELECT value INTO :ngid FROM numvalues
358 sprintf(argv[6 + idx], "%d", ngid);
361 strcpy(argv[6 + idx], "-1");
364 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
371 /* setup_dlis - verify that the list is no longer being referenced
372 * and may safely be deleted.
375 int setup_dlis(struct query *q, char *argv[], client *cl)
378 EXEC SQL BEGIN DECLARE SECTION;
380 EXEC SQL END DECLARE SECTION;
382 id = *(int *)argv[0];
384 EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
385 WHERE member_id = :id AND member_type = 'LIST';
389 EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
390 WHERE member_id = :id AND member_type = 'LIST';
394 EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
399 EXEC SQL SELECT COUNT(label) INTO :cnt FROM filesys WHERE owners = :id;
403 EXEC SQL SELECT COUNT(tag) INTO :cnt FROM capacls WHERE list_id = :id;
407 EXEC SQL SELECT COUNT(name) INTO :cnt FROM list
408 WHERE acl_id = :id AND acl_type = 'LIST' AND list_id != :id;
412 EXEC SQL SELECT COUNT(name) INTO :cnt FROM list
413 WHERE memacl_id = :id AND memacl_type = 'LIST' AND list_id != :id;
417 EXEC SQL SELECT COUNT(name) INTO :cnt FROM servers
418 WHERE acl_id = :id AND acl_type = 'LIST';
422 EXEC SQL SELECT COUNT(entity_id) INTO :cnt FROM quota
423 WHERE entity_id = :id AND type = 'GROUP';
427 EXEC SQL SELECT COUNT(acl_id) INTO :cnt FROM hostaccess
428 WHERE acl_id = :id AND acl_type = 'LIST';
432 EXEC SQL SELECT COUNT(class) INTO :cnt FROM zephyr z
433 WHERE z.xmt_type = 'LIST' AND z.xmt_id = :id
434 OR z.sub_type = 'LIST' AND z.sub_id = :id
435 OR z.iws_type = 'LIST' AND z.iws_id = :id
436 OR z.iui_type = 'LIST' AND z.iui_id = :id
437 OR z.owner_type = 'LIST' and z.owner_id = :id;
441 EXEC SQL SELECT COUNT(name) INTO :cnt FROM printers
442 WHERE lpc_acl = :id OR ac = :id;
446 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM printservers
447 WHERE owner_type = 'LIST' AND owner_id = :id
456 /* setup_dsin - verify that the service is no longer being referenced
457 * and may safely be deleted.
460 int setup_dsin(struct query *q, char *argv[], client *cl)
462 EXEC SQL BEGIN DECLARE SECTION;
465 EXEC SQL END DECLARE SECTION;
468 EXEC SQL SELECT COUNT(service) INTO :cnt FROM serverhosts
469 WHERE service = UPPER(:svrname);
473 EXEC SQL SELECT inprogress INTO :ec FROM servers
474 WHERE name = UPPER(:svrname);
484 /* setup_dshi - verify that the service-host is no longer being referenced
485 * and may safely be deleted.
488 int setup_dshi(struct query *q, char *argv[], client *cl)
490 EXEC SQL BEGIN DECLARE SECTION;
493 EXEC SQL END DECLARE SECTION;
496 id = *(int *)argv[1];
498 EXEC SQL SELECT inprogress INTO :ec FROM serverhosts
499 WHERE service = UPPER(:svrname) AND mach_id = :id;
510 ** setup_add_filesys - verify existance of referenced file systems
516 ** argv[5] - rwaccess
521 ** - for type = NFS/IMAP:
522 ** * extract directory prefix from name
523 ** * verify mach_id/dir in nfsphys
524 ** * verify rwaccess in {r, w, R, W}
526 ** Side effect: sets variable _var_phys_id to the ID of the physical
527 ** filesystem (nfsphys_id for NFS, 0 for RVD)
530 ** MR_NFS - specified directory not exported
531 ** MR_FILESYS_ACCESS - invalid filesys access
535 EXEC SQL BEGIN DECLARE SECTION;
537 EXEC SQL END DECLARE SECTION;
539 int setup_afil(struct query *q, char *argv[], client *cl)
543 EXEC SQL BEGIN DECLARE SECTION;
545 char ftype[FILESYS_TYPE_SIZE + 10], *rwaccess;
546 EXEC SQL END DECLARE SECTION;
549 mach_id = *(int *)argv[2];
554 sprintf(ftype, "fs_access_%s", type);
555 EXEC SQL SELECT COUNT(trans) INTO :ok FROM alias
556 WHERE name = :ftype AND type = 'TYPE' and trans = :rwaccess;
560 return MR_FILESYS_ACCESS;
562 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
565 if (!strcmp(type, "NFS") || !strcmp(type, "IMAP"))
566 return check_nfs(mach_id, name, rwaccess);
572 /* Verify the arguments, depending on the FStype. Also, if this is an
573 * NFS filesystem, then update any quotas for that filesystem to reflect
577 int setup_ufil(struct query *q, char *argv[], client *cl)
581 EXEC SQL BEGIN DECLARE SECTION;
582 int fid, total, who, ok;
583 char *entity, ftype[FILESYS_TYPE_SIZE + 10], *access;
584 short int total_null;
585 EXEC SQL END DECLARE SECTION;
589 mach_id = *(int *)argv[3];
592 fid = *(int *)argv[0];
596 sprintf(ftype, "fs_access_%s", type);
597 EXEC SQL SELECT COUNT(trans) INTO :ok FROM alias
598 WHERE name = :ftype AND type = 'TYPE' AND trans = :access;
602 return MR_FILESYS_ACCESS;
604 EXEC SQL SELECT type INTO :ftype FROM filesys
605 WHERE filsys_id = :fid;
609 if (!strcmp(type, "NFS") || !strcmp(type, "IMAP"))
611 status = check_nfs(mach_id, name, access);
612 EXEC SQL UPDATE quota SET phys_id = :_var_phys_id
613 WHERE filsys_id = :fid;
618 else if (!strcmp(type, "AFS") && strcmp(strtrim(ftype), "AFS")
619 && strcmp(strtrim(ftype), "ERR"))
622 EXEC SQL DELETE FROM quota
623 WHERE type = 'ANY' AND filsys_id = :fid;
624 EXEC SQL SELECT SUM (quota) INTO :total:total_null FROM quota
625 WHERE filsys_id = :fid AND phys_id != 0;
628 if (!total_null && (total != 0))
630 EXEC SQL INSERT INTO quota (quota, filsys_id, phys_id, entity_id,
631 type, modtime, modby, modwith)
632 VALUES (:total, :fid, 0, 0, 'ANY', SYSDATE, :who, :entity);
639 EXEC SQL UPDATE quota SET phys_id = 0 WHERE filsys_id = :fid;
647 /* Find the NFS physical partition that the named directory is on.
648 * This is done by comparing the dir against the mount point of the
649 * partition. To make sure we get the correct match when there is
650 * more than one, we sort the query in reverse order by dir name.
653 int check_nfs(int mach_id, char *name, char *access)
655 EXEC SQL BEGIN DECLARE SECTION;
656 char dir[NFSPHYS_DIR_SIZE];
658 EXEC SQL END DECLARE SECTION;
664 EXEC SQL DECLARE csr101 CURSOR FOR
665 SELECT nfsphys_id, dir FROM nfsphys
670 EXEC SQL OPEN csr101;
675 EXEC SQL FETCH csr101 INTO :_var_phys_id, :dir;
692 EXEC SQL CLOSE csr101;
699 /* setup_dfil: free any quota records and fsgroup info associated with
700 * a filesystem when it is deleted. Also adjust the allocation numbers.
703 int setup_dfil(struct query *q, char **argv, client *cl)
705 EXEC SQL BEGIN DECLARE SECTION;
706 int id, total, phys_id;
708 EXEC SQL END DECLARE SECTION;
710 id = *(int *)argv[0];
711 EXEC SQL SELECT SUM (quota) INTO :total:none FROM quota
712 WHERE filsys_id = :id;
717 /** What if there are multiple phys_id's per f/s? (bad data) **/
718 EXEC SQL SELECT phys_id INTO :phys_id FROM filesys
719 WHERE filsys_id = :id;
720 EXEC SQL UPDATE nfsphys SET allocated = allocated - :total
721 WHERE nfsphys_id = :phys_id;
724 EXEC SQL DELETE FROM quota WHERE filsys_id = :id;
725 EXEC SQL DELETE FROM fsgroup WHERE filsys_id = :id;
726 EXEC SQL DELETE FROM fsgroup WHERE group_id = :id;
733 /* setup_dnfp: check to see that the nfs physical partition does not have
734 * any filesystems assigned to it before allowing it to be deleted.
737 int setup_dnfp(struct query *q, char **argv, client *cl)
739 EXEC SQL BEGIN DECLARE SECTION;
742 EXEC SQL END DECLARE SECTION;
744 id = *(int *)argv[0];
746 EXEC SQL SELECT count(fs.rowid) INTO :cnt FROM filesys fs, nfsphys np
747 WHERE fs.mach_id = :id AND fs.phys_id = np.nfsphys_id
748 AND np.mach_id = :id AND np.dir = :dir;
757 /* setup_dqot: Remove allocation from nfsphys before deleting quota.
758 * argv[0] = filsys_id
759 * argv[1] = type if "update_quota" or "delete_quota"
760 * argv[2 or 1] = users_id or list_id
763 int setup_dqot(struct query *q, char **argv, client *cl)
765 EXEC SQL BEGIN DECLARE SECTION;
766 int quota, fs, id, physid;
768 EXEC SQL END DECLARE SECTION;
770 fs = *(int *)argv[0];
771 if (!strcmp(q->name, "update_quota") || !strcmp(q->name, "delete_quota"))
774 id = *(int *)argv[2];
779 id = *(int *)argv[1];
782 EXEC SQL SELECT quota INTO :quota FROM quota
783 WHERE type = :qtype AND entity_id = :id AND filsys_id = :fs;
784 EXEC SQL SELECT phys_id INTO :physid FROM filesys
785 WHERE filsys_id = :fs;
786 EXEC SQL UPDATE nfsphys SET allocated = allocated - :quota
787 WHERE nfsphys_id = :physid;
796 * This routine fetches an appropriate value from the numvalues table.
797 * It is a little hack to get around the fact that SQL doesn't let you
798 * do something like INSERT INTO table (foo) VALUES (other_table.bar).
800 * It is called from the query table as (*v->pre_rtn)(q, Argv, cl) or
801 * from within a setup_...() routine with the appropriate arguments.
803 * Correct functioning of this routine may depend on the assumption
804 * that this query is an APPEND.
807 int prefetch_value(struct query *q, char **argv, client *cl)
809 EXEC SQL BEGIN DECLARE SECTION;
810 char *name = q->validate->object_id;
812 EXEC SQL END DECLARE SECTION;
813 int status, limit, argc;
815 /* set next object id, limiting it if necessary */
816 if (!strcmp(name, "unix_uid") || !strcmp(name, "gid"))
817 limit = 1; /* So far as I know, this isn't needed. Just CMA. */
820 if ((status = set_next_object_id(name, q->rtable, limit)) != MR_SUCCESS)
823 /* fetch object id */
824 EXEC SQL SELECT value INTO :value FROM numvalues WHERE name = :name;
827 if (sqlca.sqlerrd[2] != 1)
830 argc = q->argc + q->vcnt; /* end of Argv for APPENDs */
831 sprintf(argv[argc], "%d", value);
836 /* prefetch_filesys():
837 * Fetches the phys_id from filesys based on the filsys_id in argv[0].
838 * Appends the filsys_id and the phys_id to the argv so they can be
839 * referenced in an INSERT into a table other than filesys. Also
840 * see comments at prefetch_value().
842 * Assumes the existence of a row where filsys_id = argv[0], since a
843 * filesys label has already been resolved to a filsys_id.
845 int prefetch_filesys(struct query *q, char **argv, client *cl)
847 EXEC SQL BEGIN DECLARE SECTION;
849 EXEC SQL END DECLARE SECTION;
852 fid = *(int *)argv[0];
853 EXEC SQL SELECT phys_id INTO :phid FROM filesys WHERE filsys_id = :fid;
857 argc = q->argc + q->vcnt;
858 sprintf(argv[argc++], "%d", phid);
859 sprintf(argv[argc], "%d", fid);
868 int setup_ahst(struct query *q, char **argv, client *cl)
870 EXEC SQL BEGIN DECLARE SECTION;
871 char *name, oldname[MACHINE_NAME_SIZE], vendor[MACHINE_VENDOR_SIZE];
872 char model[MACHINE_MODEL_SIZE], os[MACHINE_OS_SIZE];
873 int value, id, ssaddr, smask, shigh, slow, cnt;
874 unsigned int saddr, mask, high, low;
875 EXEC SQL END DECLARE SECTION;
879 id = *(int *)argv[0];
881 if (!strcmp(q->shortname, "uhst"))
884 EXEC SQL SELECT name, vendor, model, os
885 INTO :oldname, :vendor, :model, :os
886 FROM machine WHERE mach_id = :id;
891 /* Sanity check name, vendor, model, and os. */
892 if ((row == 0 || strcasecmp(argv[1], oldname)) &&
893 !hostname_check(argv[row]))
895 if ((row == 0 || strcasecmp(argv[2], vendor)) &&
896 !hostinfo_check(argv[row + 1], 0))
898 if ((row == 0 || strcasecmp(argv[3], model)) &&
899 !hostinfo_check(argv[row + 2], 1))
901 if ((row == 0 || strcasecmp(argv[4], os)) &&
902 !hostinfo_check(argv[row + 3], 0))
905 /* check for duplicate name */
907 EXEC SQL SELECT count(mach_id) INTO :cnt FROM hostalias
908 WHERE name = UPPER(:name);
915 if (!strcmp(argv[9 + row], "unassigned"))
917 else if (!strcmp(argv[9 + row], "unique"))
919 if (*(int *)argv[8 + row] == 0)
926 value = ntohl(inet_addr(argv[9 + row]));
935 * an address or unique was specified.
937 id = *(int *)argv[8 + row];
938 EXEC SQL SELECT saddr, mask, high, low INTO :ssaddr, :smask,
939 :shigh, :slow FROM subnet WHERE snet_id = :id;
942 saddr = (unsigned) ssaddr;
943 mask = (unsigned) smask;
944 high = (unsigned) shigh;
945 low = (unsigned) slow;
949 * someone specified an IP address for the host record
951 if ((value & mask) != saddr || value < low || value > high)
954 * run the address argument through inet_addr(). This
955 * has the effect that any out of bounds host addrs will
956 * be converted to a valid host addr. We do this now
957 * so that the uniqueness check works. We should also
958 * link in an inet_addr() that returns an error for
961 addr.s_addr = inet_addr(argv[9 + row]);
962 name = inet_ntoa(addr);
963 EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine
964 WHERE address = :name;
970 * make IP address is unique. If this a modify request
971 * (row == 1), then we expect one record to exist.
973 if (row == 0 || (row == 1 && cnt > 1))
975 if (row == 1 && cnt == 1)
977 EXEC SQL SELECT mach_id INTO :id FROM machine
978 WHERE address = :name;
979 if (id != *(int *)argv[0])
987 * a "unique" address was specified. Walk through the
988 * range specified in the network record, return
989 * error if no room left.
991 for (id = low; id <= high; id++)
993 if (((id & 0xff) == 0) || ((id & 0xff) == 255))
995 addr.s_addr = htonl(id);
996 name = inet_ntoa(addr);
997 EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine
998 WHERE address = :name;
1010 * we have an address in value. Convert it to a string and store it.
1012 addr.s_addr = htonl(value);
1013 strcpy(argv[9 + row], inet_ntoa(addr));
1016 strcpy(argv[9 + row], "unassigned");
1018 /* status checking */
1019 value = atoi(argv[7 + row]);
1020 if (row == 0 && !(value == 1 || value == 0))
1024 id = *(int *)argv[0];
1025 EXEC SQL SELECT status INTO :cnt FROM machine WHERE mach_id = :id;
1030 EXEC SQL UPDATE machine SET statuschange = SYSDATE
1031 WHERE mach_id = :id;
1036 * If this is an update_host query, we're done.
1042 * For an add_host query, allocate and fill in a new machine id,
1043 * and then insert the creator id.
1045 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
1048 sprintf(argv[q->argc + q->vcnt + 1], "%d", cl->client_id);
1056 int setup_ahal(struct query *q, char **argv, client *cl)
1058 EXEC SQL BEGIN DECLARE SECTION;
1061 EXEC SQL END DECLARE SECTION;
1065 if (!hostname_check(argv[0]))
1068 EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine WHERE
1069 name = UPPER(:name);
1078 /* setup_uhha(): Check characters in hwaddr, and make sure it's not
1081 int setup_uhha(struct query *q, char **argv, client *cl)
1083 EXEC SQL BEGIN DECLARE SECTION;
1084 char *hwaddr = argv[1];
1086 EXEC SQL END DECLARE SECTION;
1089 if (*hwaddr && strcasecmp(hwaddr, "unknown"))
1091 for (p = hwaddr; *p; p++)
1098 if (p != hwaddr + 12)
1101 EXEC SQL SELECT COUNT(hwaddr) INTO :count
1102 FROM machine WHERE hwaddr = :hwaddr;
1104 return MR_NOT_UNIQUE;
1110 /* setup_aprn(): Make sure name/duplexname don't conflict with
1111 * anything. If [ANY] was specified for the spooling host, pick the
1112 * least loaded print server that serves this kind of printer.
1114 int setup_aprn(struct query *q, char **argv, client *cl)
1118 EXEC SQL BEGIN DECLARE SECTION;
1119 int mid, usage, count;
1120 char types[STRINGS_STRING_SIZE], *hwaddr, *name, *duplexname, *oldname;
1121 EXEC SQL END DECLARE SECTION;
1123 /* Check for aprn or uprn. */
1124 if (q->type == APPEND)
1129 name = argv[PRN_NAME + row];
1130 duplexname = argv[PRN_DUPLEXNAME + row];
1137 if (q->type == APPEND)
1139 EXEC SQL SELECT COUNT(name) INTO :count FROM printers
1140 WHERE name = :name OR duplexname = :name;
1144 EXEC SQL SELECT COUNT(name) INTO :count FROM printers
1145 WHERE ( name = :name OR duplexname = :name )
1146 AND name != :oldname;
1151 return MR_NOT_UNIQUE;
1156 if (q->type == APPEND)
1158 EXEC SQL SELECT COUNT(name) INTO :count FROM printers
1159 WHERE name = :duplexname OR duplexname = :duplexname;
1163 EXEC SQL SELECT COUNT(name) INTO :count FROM printers
1164 WHERE ( name = :duplexname OR duplexname = :duplexname )
1165 AND name != :oldname;
1171 return MR_NOT_UNIQUE;
1174 if (!strcmp(name, duplexname))
1175 return MR_NOT_UNIQUE;
1177 mid = *(int *)argv[PRN_RM + row];
1180 EXEC SQL DECLARE csr_rm CURSOR FOR
1181 SELECT ps.mach_id, s.string FROM printservers ps, strings s
1183 ( SELECT mach_id FROM serverhosts WHERE service = 'PRINT'
1185 AND ps.printer_types = s.string_id;
1188 EXEC SQL OPEN csr_rm;
1194 EXEC SQL FETCH csr_rm INTO :mid, :types;
1198 for (p = strtok(types, ", "); p; p = strtok(NULL, ", "))
1200 if (!strcasecmp(argv[PRN_TYPE + row], p))
1202 EXEC SQL SELECT COUNT(name) INTO :usage
1203 FROM printers WHERE rm = :mid;
1205 if (best < 0 || usage < best)
1208 *(int *)argv[PRN_RM + row] = mid;
1214 EXEC SQL CLOSE csr_rm;
1223 EXEC SQL SELECT mach_id INTO :mid FROM printservers
1224 WHERE mach_id = :mid;
1232 int setup_dpsv(struct query *q, char **argv, client *cl)
1235 EXEC SQL BEGIN DECLARE SECTION;
1237 EXEC SQL END DECLARE SECTION;
1239 id = *(int *)argv[0];
1241 EXEC SQL SELECT COUNT(rm) INTO :cnt FROM printers
1250 * validate the rfc1035/rfc1123-ness of a hostname
1253 int hostname_check(char *name)
1258 /* Sanity check name: must contain only letters, numerals, and
1259 * hyphen, and not start or end with a hyphen. Also make sure no
1260 * label (the thing the .s seperate) is longer than 63 characters,
1264 for (p = name, count = 0; *p; p++)
1267 if ((!isalnum(*p) && *p != '-' && *p != '.') ||
1268 (*p == '-' && p[1] == '.'))
1279 if (*(p - 1) == '-')
1284 int hostinfo_check(char *info, int num)
1291 /* Sanity check host hostinfo: must start with a letter (or number
1292 * if num is true), contain only letters, numerals, and hyphen, and
1293 * not end with a hyphen.
1296 if (!isalpha(*info) && (!num || !isdigit(*info)))
1298 for (p = info; *p; p++)
1300 if ((!isalnum(*p) && *p != '-' && *p != '.') ||
1301 (*p == '-' && p[1] == '.'))
1304 if (!isalnum(*(p - 1)))