X-Git-Url: http://andersk.mit.edu/gitweb/moira.git/blobdiff_plain/ff98438b77f786f39575c20e35d2b162ba32da0f..7c95c11b0d7c14004290e14b92e799ea8bdd1eeb:/server/qsetup.pc diff --git a/server/qsetup.pc b/server/qsetup.pc index 5397d7be..040d9533 100644 --- a/server/qsetup.pc +++ b/server/qsetup.pc @@ -32,7 +32,8 @@ EXEC SQL END DECLARE SECTION; EXEC SQL WHENEVER SQLERROR DO dbmserr(); - +int hostname_check(char *name); +int hostinfo_check(char *name, int num); int prefetch_value(struct query *q, char **argv, client *cl); int check_nfs(int mach_idx, char *name, char *access); @@ -60,6 +61,20 @@ int setup_ausr(struct query *q, char *argv[], client *cl) row = 2; else row = 1; + + if (q->version > 2) + { + if (strlen(argv[row + 3]) + strlen(argv[row + 4]) + + strlen(argv[row + 5]) + 2 > USERS_FULLNAME_SIZE) + return MR_ARG_TOO_LONG; + } + else + { + if (strlen(argv[row + 2]) + strlen(argv[row + 3]) + + strlen(argv[row + 4]) + 2 > USERS_FULLNAME_SIZE) + return MR_ARG_TOO_LONG; + } + if (!strcmp(argv[row], UNIQUE_UID) || atoi(argv[row]) == -1) { if ((err = set_next_object_id("unix_uid", USERS_TABLE, 1))) @@ -76,6 +91,12 @@ int setup_ausr(struct query *q, char *argv[], client *cl) if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS) return mr_errcode; + /* If this is an UPDATE query, we're done. */ + if (row == 2) + return MR_SUCCESS; + + /* For an add query, we need to fill in the creator id. */ + sprintf(argv[q->argc + q->vcnt + 1], "%d", cl->client_id); return MR_SUCCESS; } @@ -88,17 +109,19 @@ int setup_dusr(struct query *q, char *argv[], client *cl) { EXEC SQL BEGIN DECLARE SECTION; int flag, id, cnt; + char resv[USERS_RESERVATIONS_SIZE]; EXEC SQL END DECLARE SECTION; id = *(int *)argv[0]; - /* For now, only allow users to be deleted if their status is 0 */ - EXEC SQL SELECT status INTO :flag FROM users WHERE users_id = :id; - if (flag != 0 && flag != 4) + /* For now, only allow users to be deleted if their status is 0 + * and we have no reservations about deleting them. + */ + EXEC SQL SELECT status, reservations INTO :flag, :resv + FROM users WHERE users_id = :id; + if ((flag != 0 && flag != 4) || *resv) return MR_IN_USE; - EXEC SQL DELETE FROM quota WHERE entity_id = :id AND type = 'USER'; - EXEC SQL DELETE FROM krbmap WHERE users_id = :id; EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers WHERE member_id = :id AND member_type = 'USER'; if (cnt > 0) @@ -121,31 +144,9 @@ int setup_dusr(struct query *q, char *argv[], client *cl) return MR_IN_USE; if (dbms_errno) return mr_errcode; - return MR_SUCCESS; -} - - -/* setup_spop: verify that there is already a valid POP machine_id in the - * pop_id field. Also take care of keeping track of the post office usage. - */ -int setup_spop(struct query *q, char *argv[], client *cl) -{ - EXEC SQL BEGIN DECLARE SECTION; - int id, mid; - char type[USERS_POTYPE_SIZE]; - EXEC SQL END DECLARE SECTION; - id = *(int *)argv[0]; - EXEC SQL SELECT potype, pop_id INTO :type, :mid FROM users - WHERE users_id = :id; - if (sqlca.sqlerrd[2] == 0) - return MR_MACHINE; - EXEC SQL SELECT mach_id INTO :mid FROM machine - WHERE mach_id = :mid; - if (sqlca.sqlerrd[2] == 0) - return MR_MACHINE; - if (strcmp(strtrim(type), "POP")) - set_pop_usage(mid, 1); + EXEC SQL DELETE FROM quota WHERE entity_id = :id AND type = 'USER'; + EXEC SQL DELETE FROM krbmap WHERE users_id = :id; return MR_SUCCESS; } @@ -203,15 +204,19 @@ int setup_dmac(struct query *q, char *argv[], client *cl) WHERE mach_id = :id; if (cnt > 0) return MR_IN_USE; - EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM printcap + EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM printers WHERE mach_id = :id; if (cnt > 0) return MR_IN_USE; - EXEC SQL SELECT COUNT(quotaserver) INTO :cnt FROM printcap - WHERE quotaserver = :id; + EXEC SQL SELECT COUNT(rm) INTO :cnt FROM printers + WHERE rm = :id; + if (cnt > 0) + return MR_IN_USE; + EXEC SQL SELECT COUNT(rq) INTO :cnt FROM printers + WHERE rq = :id; if (cnt > 0) return MR_IN_USE; - EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM palladium + EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM printservers WHERE mach_id = :id; if (cnt > 0) return MR_IN_USE; @@ -219,13 +224,70 @@ int setup_dmac(struct query *q, char *argv[], client *cl) WHERE mach_id = :id; if (cnt > 0) return MR_IN_USE; + EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers + WHERE member_type = 'MACHINE' and member_id = :id; + if (cnt > 0) + return MR_IN_USE; EXEC SQL DELETE FROM mcmap WHERE mach_id = :id; + if (dbms_errno) + return mr_errcode; + + EXEC SQL DELETE FROM mcntmap WHERE mach_id = :id; if (dbms_errno) return mr_errcode; return MR_SUCCESS; } +/* setup_asnt - verify that the data entered for the subnet is sane. + * In particular, make sure that the "low" and "high" addresses are + * correctly ordered, i.e., high > low. + */ + +int setup_asnt(struct query *q, char *argv[], client *cl) +{ + int high, low, row, status; + char *account_number; + + /* Check for asnt or usnt. */ + if (q->type == APPEND) + row = 0; + else + row = 1; + + low = atoi(argv[row + 7]); + high = atoi(argv[row + 8]); + status = atoi(argv[row + 2]); + account_number = argv[row + 4]; + + /* Don't allow Private subnets to be created without a valid billing + * number. + */ + if (status == SNET_STATUS_PRIVATE_10MBPS || + status == SNET_STATUS_PRIVATE_100MBPS || + status == SNET_STATUS_PRIVATE_1000MBPS) + { + EXEC SQL SELECT account_number FROM accountnumbers + WHERE account_number = :account_number; + if (sqlca.sqlcode == SQL_NO_MATCH) + return MR_ACCOUNT_NUMBER; + } + + /* Special case 0.0.0.0 and 255.255.255.255 */ + if (!(low == 0 || low == -1 || high == 0 || high == -1)) + if (low > high) + return MR_ADDRESS; + + /* If this is update_subnet, we're done. */ + if (row == 1) + return MR_SUCCESS; + + /* For an add_subnet query, allocate and fill in a new snet_id */ + if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS) + return mr_errcode; + + return MR_SUCCESS; +} /* setup_dsnt - verify that the subnet is no longer being referenced * and may safely be deleted. @@ -277,17 +339,20 @@ int setup_dclu(struct query *q, char *argv[], client *cl) * a -1 there. Remember that this is also used for ulis, with the indexes * at 6 & 7. Also check that the list name does not contain uppercase * characters, control characters, @, or :. + * + * Newlines in list descriptions do bad things to the aliases file + * moira generates, so make sure the description doesn't contain any, too. */ static int badlistchars[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */ - 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, /* 0 - ? */ + 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, /* SPACE - / */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 0 - ? */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, /* P - _ */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* P - _ */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -301,7 +366,8 @@ static int badlistchars[] = { int setup_alis(struct query *q, char *argv[], client *cl) { EXEC SQL BEGIN DECLARE SECTION; - int ngid; + int ngid, cnt; + char *name, *desc; EXEC SQL END DECLARE SECTION; unsigned char *p; int idx, err; @@ -310,13 +376,44 @@ int setup_alis(struct query *q, char *argv[], client *cl) idx = 0; else if (!strcmp(q->shortname, "ulis")) idx = 1; + name = argv[idx]; + + if (q->version == 2) + desc = argv[9 + idx]; + else if (q->version == 3) + desc = argv[10 + idx]; + else if (q->version >= 4) + desc = argv[12 + idx]; - for (p = (unsigned char *) argv[idx]; *p; p++) + if (idx == 1) + { + EXEC SQL BEGIN DECLARE SECTION; + int lid = *(int *)argv[0]; + EXEC SQL END DECLARE SECTION; + + if (acl_access_check(lid, cl)) + return MR_PERM; + } + + for (p = (unsigned char *) name; *p; p++) { if (badlistchars[*p]) return MR_BAD_CHAR; } + for (p = (unsigned char *) desc; *p; p++) + { + if (*p == '\n') + return MR_BAD_CHAR; + } + + /* Check that it doesn't conflict with a pre-existing weirdly-cased + * name. */ + EXEC SQL SELECT COUNT(name) INTO :cnt FROM list + WHERE LOWER(name) = :name AND name != :name; + if (cnt) + return MR_EXISTS; + if (!strcmp(argv[6 + idx], UNIQUE_GID) || atoi(argv[6 + idx]) == -1) { if (atoi(argv[5 + idx])) @@ -381,6 +478,11 @@ int setup_dlis(struct query *q, char *argv[], client *cl) if (cnt > 0) return MR_IN_USE; + EXEC SQL SELECT COUNT(name) INTO :cnt FROM list + WHERE memacl_id = :id AND memacl_type = 'LIST' AND list_id != :id; + if (cnt > 0) + return MR_IN_USE; + EXEC SQL SELECT COUNT(name) INTO :cnt FROM servers WHERE acl_id = :id AND acl_type = 'LIST'; if (cnt > 0) @@ -400,7 +502,29 @@ int setup_dlis(struct query *q, char *argv[], client *cl) WHERE z.xmt_type = 'LIST' AND z.xmt_id = :id OR z.sub_type = 'LIST' AND z.sub_id = :id OR z.iws_type = 'LIST' AND z.iws_id = :id - OR z.iui_type = 'LIST' AND z.iui_id = :id; + OR z.iui_type = 'LIST' AND z.iui_id = :id + OR z.owner_type = 'LIST' and z.owner_id = :id; + if (cnt > 0) + return MR_IN_USE; + + EXEC SQL SELECT COUNT(name) INTO :cnt FROM printers + WHERE lpc_acl = :id OR ac = :id; + if (cnt > 0) + return MR_IN_USE; + + EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM printservers + WHERE owner_type = 'LIST' AND owner_id = :id + OR lpc_acl = :id; + if (cnt > 0) + return MR_IN_USE; + + EXEC SQL SELECT count(name) INTO :cnt FROM containers + WHERE acl_id = :id AND acl_type = 'LIST'; + if (cnt > 0) + return MR_IN_USE; + + EXEC SQL SELECT count(name) INTO :cnt FROM containers + WHERE memacl_id = :id AND memacl_type = 'LIST'; if (cnt > 0) return MR_IN_USE; @@ -473,7 +597,7 @@ int setup_dshi(struct query *q, char *argv[], client *cl) ** Description: ** - for type = RVD: ** * allow anything - ** - for type = NFS: + ** - for type = NFS/IMAP: ** * extract directory prefix from name ** * verify mach_id/dir in nfsphys ** * verify rwaccess in {r, w, R, W} @@ -517,7 +641,7 @@ int setup_afil(struct query *q, char *argv[], client *cl) if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS) return mr_errcode; - if (!strcmp(type, "NFS")) + if (!strcmp(type, "NFS") || !strcmp(type, "IMAP")) return check_nfs(mach_id, name, rwaccess); return MR_SUCCESS; @@ -561,7 +685,7 @@ int setup_ufil(struct query *q, char *argv[], client *cl) if (dbms_errno) return mr_errcode; - if (!strcmp(type, "NFS")) + if (!strcmp(type, "NFS") || !strcmp(type, "IMAP")) { status = check_nfs(mach_id, name, access); EXEC SQL UPDATE quota SET phys_id = :_var_phys_id @@ -828,9 +952,11 @@ int setup_ahst(struct query *q, char **argv, client *cl) int value, id, ssaddr, smask, shigh, slow, cnt; unsigned int saddr, mask, high, low; EXEC SQL END DECLARE SECTION; - int row; + int row, idx; struct in_addr addr; + id = *(int *)argv[0]; + if (!strcmp(q->shortname, "uhst")) { row = 1; @@ -841,83 +967,26 @@ int setup_ahst(struct query *q, char **argv, client *cl) else row = 0; - id = *(int *)argv[0]; - - /* sanity check name: must start with a letter, contain only - * letters, numerals, and hyphen, and not end with a hyphen. - */ - if (row == 0 || strcasecmp(argv[1], oldname)) - { - char *p = argv[row]; - - if (!isalpha(*p)) - return MR_BAD_CHAR; - for (; *p; p++) - { - if ((!isalnum(*p) && *p != '-' && *p != '.') || - (*p == '-' && p[1] == '.')) - return MR_BAD_CHAR; - } - if (*(p - 1) == '-') - return MR_BAD_CHAR; - } - - /* sanity check host vendor: must start with a letter, contain only - * letters, numerals, and hyphen, and end with an alphanumeric. - */ - if (*argv[row + 1] && (row == 0 || strcasecmp(argv[2], vendor))) - { - char *p = argv[row + 1]; - - if (!isalpha(*p)) - return MR_BAD_CHAR; - for (; *p; p++) - { - if ((!isalnum(*p) && *p != '-' && *p != '.') || - (*p == '-' && p[1] == '.')) - return MR_BAD_CHAR; - } - if (!isalnum(*(p - 1))) - return MR_BAD_CHAR; - } - - /* sanity check host type: must start with a letter, contain only - * letters, numerals, and hyphen, and end with an alphanumeric. - */ - if (*argv[row + 2] && (row == 0 || strcasecmp(argv[3], model))) - { - char *p = argv[row + 2]; - - if (!isalnum(*p)) - return MR_BAD_CHAR; - for (; *p; p++) - { - if ((!isalnum(*p) && *p != '-' && *p != '.') || - (*p == '-' && p[1] == '.')) - return MR_BAD_CHAR; - } - if (!isalnum(*(p - 1))) - return MR_BAD_CHAR; - } - - /* sanity check host os: must start with a letter, contain only - * letters, numerals, and hyphen, and end with an hyphen alphanumeric. - */ - if (*argv[row + 3] && (row == 0 || strcasecmp(argv[4], os))) - { - char *p = argv[row + 3]; + if (q->version < 6) + idx = 0; + else if (q->version >= 6 && q->version < 8) + idx = 1; + else + idx = 2; - if (!isalpha(*p)) - return MR_BAD_CHAR; - for (; *p; p++) - { - if ((!isalnum(*p) && *p != '-' && *p != '.') || - (*p == '-' && p[1] == '.')) - return MR_BAD_CHAR; - } - if (!isalnum(*(p - 1))) - return MR_BAD_CHAR; - } + /* Sanity check name, vendor, model, and os. */ + if ((row == 0 || strcasecmp(argv[1], oldname)) && + !hostname_check(argv[row])) + return MR_BAD_CHAR; + if ((row == 0 || strcasecmp(argv[2], vendor)) && + !hostinfo_check(argv[row + 1], 0)) + return MR_BAD_CHAR; + if ((row == 0 || strcasecmp(argv[3], model)) && + !hostinfo_check(argv[row + 2], 1)) + return MR_BAD_CHAR; + if ((row == 0 || strcasecmp(argv[4], os)) && + !hostinfo_check(argv[row + 3], 0)) + return MR_BAD_CHAR; /* check for duplicate name */ name = argv[row]; @@ -929,18 +998,18 @@ int setup_ahst(struct query *q, char **argv, client *cl) return MR_EXISTS; /* check address */ - if (!strcmp(argv[9 + row], "unassigned")) + if (!strcmp(argv[9 + row + idx], "unassigned")) value = -1; - else if (!strcmp(argv[9 + row], "unique")) + else if (!strcmp(argv[9 + row + idx], "unique")) { - if (*(int *)argv[8 + row] == 0) + if (*(int *)argv[8 + row + idx] == 0) value = -1; else value = -2; } else { - value = ntohl(inet_addr(argv[9 + row])); + value = ntohl(inet_addr(argv[9 + row + idx])); if (value == -1) return MR_ADDRESS; } @@ -951,7 +1020,7 @@ int setup_ahst(struct query *q, char **argv, client *cl) /* * an address or unique was specified. */ - id = *(int *)argv[8 + row]; + id = *(int *)argv[8 + row + idx]; EXEC SQL SELECT saddr, mask, high, low INTO :ssaddr, :smask, :shigh, :slow FROM subnet WHERE snet_id = :id; if (dbms_errno) @@ -975,7 +1044,7 @@ int setup_ahst(struct query *q, char **argv, client *cl) * link in an inet_addr() that returns an error for * this case. */ - addr.s_addr = inet_addr(argv[9 + row]); + addr.s_addr = inet_addr(argv[9 + row + idx]); name = inet_ntoa(addr); EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine WHERE address = :name; @@ -1027,13 +1096,13 @@ int setup_ahst(struct query *q, char **argv, client *cl) * we have an address in value. Convert it to a string and store it. */ addr.s_addr = htonl(value); - strcpy(argv[9 + row], inet_ntoa(addr)); + strcpy(argv[9 + row + idx], inet_ntoa(addr)); } else - strcpy(argv[9 + row], "unassigned"); + strcpy(argv[9 + row + idx], "unassigned"); /* status checking */ - value = atoi(argv[7 + row]); + value = atoi(argv[7 + row + idx]); if (row == 0 && !(value == 1 || value == 0)) return MR_TYPE; if (row == 1) @@ -1078,16 +1147,8 @@ int setup_ahal(struct query *q, char **argv, client *cl) EXEC SQL END DECLARE SECTION; char *p; - p = name = argv[0]; - if (!isalpha(*p)) - return MR_BAD_CHAR; - for (; *p; p++) - { - if ((!isalnum(*p) && *p != '-' && *p != '.') || - (*p == '-' && p[1] == '.')) - return MR_BAD_CHAR; - } - if (*(p - 1) == '-') + name = argv[0]; + if (!hostname_check(argv[0])) return MR_BAD_CHAR; EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine WHERE @@ -1099,3 +1160,269 @@ int setup_ahal(struct query *q, char **argv, client *cl) return MR_SUCCESS; } + +/* setup_uhha(): Check characters in hwaddr, and make sure it's not + * a duplicate. + */ +int setup_uhha(struct query *q, char **argv, client *cl) +{ + EXEC SQL BEGIN DECLARE SECTION; + char *hwaddr = argv[1]; + int count; + EXEC SQL END DECLARE SECTION; + char *p; + + if (*hwaddr && strcasecmp(hwaddr, "unknown")) + { + for (p = hwaddr; *p; p++) + { + if (isupper(*p)) + *p = tolower(*p); + if (!isxdigit(*p)) + return MR_BAD_CHAR; + } + if (p != hwaddr + 12) + return MR_ADDRESS; + + EXEC SQL SELECT COUNT(hwaddr) INTO :count + FROM machine WHERE hwaddr = :hwaddr; + if (count) + return MR_NOT_UNIQUE; + } + + return MR_SUCCESS; +} + +/* setup_aprn(): Make sure name/duplexname don't conflict with + * anything. If [ANY] was specified for the spooling host, pick the + * least loaded print server that serves this kind of printer. + */ +int setup_aprn(struct query *q, char **argv, client *cl) +{ + int best = -1, row; + char *p; + EXEC SQL BEGIN DECLARE SECTION; + int mid, usage, count; + char types[STRINGS_STRING_SIZE], *hwaddr, *name, *duplexname, *oldname; + EXEC SQL END DECLARE SECTION; + + /* Check for aprn or uprn. */ + if (q->type == APPEND) + row = 0; + else + row = 1; + + name = argv[PRN_NAME + row]; + duplexname = argv[PRN_DUPLEXNAME + row]; + oldname = argv[0]; + + if (!*name) + return MR_BAD_CHAR; + else + { + if (q->type == APPEND) + { + EXEC SQL SELECT COUNT(name) INTO :count FROM printers + WHERE name = :name OR duplexname = :name; + } + else + { + EXEC SQL SELECT COUNT(name) INTO :count FROM printers + WHERE ( name = :name OR duplexname = :name ) + AND name != :oldname; + } + if (dbms_errno) + return mr_errcode; + if (count) + return MR_NOT_UNIQUE; + } + + if (*duplexname) + { + if (q->type == APPEND) + { + EXEC SQL SELECT COUNT(name) INTO :count FROM printers + WHERE name = :duplexname OR duplexname = :duplexname; + } + else + { + EXEC SQL SELECT COUNT(name) INTO :count FROM printers + WHERE ( name = :duplexname OR duplexname = :duplexname ) + AND name != :oldname; + } + + if (dbms_errno) + return mr_errcode; + if (count) + return MR_NOT_UNIQUE; + } + + if (!strcmp(name, duplexname)) + return MR_NOT_UNIQUE; + + mid = *(int *)argv[PRN_RM + row]; + if (mid == -1) + { + EXEC SQL DECLARE csr_rm CURSOR FOR + SELECT ps.mach_id, s.string FROM printservers ps, strings s + WHERE ps.mach_id IN + ( SELECT mach_id FROM serverhosts WHERE service = 'PRINT' + AND enable = 1 ) + AND ps.printer_types = s.string_id; + if (dbms_errno) + return mr_errcode; + EXEC SQL OPEN csr_rm; + if (dbms_errno) + return mr_errcode; + + while (1) + { + EXEC SQL FETCH csr_rm INTO :mid, :types; + if (sqlca.sqlcode) + break; + + for (p = strtok(types, ", "); p; p = strtok(NULL, ", ")) + { + if (!strcasecmp(argv[PRN_TYPE + row], p)) + { + EXEC SQL SELECT COUNT(name) INTO :usage + FROM printers WHERE rm = :mid; + + if (best < 0 || usage < best) + { + best = usage; + *(int *)argv[PRN_RM + row] = mid; + break; + } + } + } + } + EXEC SQL CLOSE csr_rm; + if (dbms_errno) + return mr_errcode; + + if (best == -1) + return MR_SERVICE; + } + else + { + EXEC SQL SELECT mach_id INTO :mid FROM printservers + WHERE mach_id = :mid; + if (sqlca.sqlcode) + return MR_SERVICE; + } + + return MR_SUCCESS; +} + +int setup_dpsv(struct query *q, char **argv, client *cl) +{ + int id; + EXEC SQL BEGIN DECLARE SECTION; + int cnt; + EXEC SQL END DECLARE SECTION; + + id = *(int *)argv[0]; + + EXEC SQL SELECT COUNT(rm) INTO :cnt FROM printers + WHERE rm = :id; + if (cnt > 0) + return MR_IN_USE; + + return MR_SUCCESS; +} + +int setup_dcon(struct query *q, char *argv[], client *cl) +{ + EXEC SQL BEGIN DECLARE SECTION; + int id, cnt; + char containername[CONTAINERS_NAME_SIZE]; + EXEC SQL END DECLARE SECTION; + + id = *(int *)argv[0]; + /* check to see if there are machines in this container */ + EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM mcntmap + WHERE cnt_id = :id; + if (cnt > 0) + return MR_IN_USE; + + /* check to see if there are subcontainers in this container */ + + /* get the container name */ + + EXEC SQL SELECT name INTO :containername + FROM containers + WHERE cnt_id = :id; + + /* trim off the trailing spaces */ + strcpy(containername, strtrim(containername)); + + EXEC SQL SELECT COUNT(cnt_id) INTO :cnt FROM containers + WHERE name LIKE :containername || '/' || '%'; + + if (cnt > 0) + return MR_IN_USE; + + if (dbms_errno) + return mr_errcode; + return MR_SUCCESS; +} + +/* hostname_check() + * validate the rfc1035/rfc1123-ness of a hostname + */ + +int hostname_check(char *name) +{ + char *p; + int count; + + /* Sanity check name: must contain only letters, numerals, and + * hyphen, and not start or end with a hyphen. Also make sure no + * label (the thing the .s seperate) is longer than 63 characters, + * or empty. + */ + + for (p = name, count = 0; *p; p++) + { + count++; + if ((!isalnum(*p) && *p != '-' && *p != '.') || + (*p == '-' && p[1] == '.')) + return 0; + if (*p == '.') + { + if (count == 1) + return 0; + count = 0; + } + if (count == 64) + return 0; + } + if (*(p - 1) == '-') + return 0; + return 1; +} + +int hostinfo_check(char *info, int num) +{ + char *p; + + if (!*info) + return 1; + + /* Sanity check host hostinfo: must start with a letter (or number + * if num is true), contain only letters, numerals, and hyphen, and + * not end with a hyphen. + */ + + if (!isalpha(*info) && (!num || !isdigit(*info))) + return 0; + for (p = info; *p; p++) + { + if ((!isalnum(*p) && *p != '-' && *p != '.') || + (*p == '-' && p[1] == '.')) + return 0; + } + if (!isalnum(*(p - 1))) + return 1; +}