]> andersk Git - moira.git/blame - server/qsetup.pc
oops, wrong argument.
[moira.git] / server / qsetup.pc
CommitLineData
7ac48069 1/* $Id$
73cf66ba 2 *
7ac48069 3 * Query setup routines
73cf66ba 4 *
7ac48069 5 * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology
6 * For copying and distribution information, please see the file
7 * <mit-copyright.h>.
73cf66ba 8 */
9
73cf66ba 10#include <mit-copyright.h>
73cf66ba 11#include "mr_server.h"
03c05291 12#include "query.h"
7ac48069 13#include "qrtn.h"
14
03c05291 15#include <arpa/inet.h>
7ac48069 16#include <netinet/in.h>
17
18#include <ctype.h>
19#include <stdlib.h>
20#include <string.h>
21
73cf66ba 22EXEC SQL INCLUDE sqlca;
73cf66ba 23
7ac48069 24RCSID("$Header$");
25
26extern char *whoami;
03c05291 27extern int dbms_errno, mr_errcode;
73cf66ba 28
29EXEC SQL BEGIN DECLARE SECTION;
30extern char stmt_buf[];
31EXEC SQL END DECLARE SECTION;
32
03c05291 33EXEC SQL WHENEVER SQLERROR DO dbmserr();
34
17f585b5 35int hostname_check(char *name);
36int hostinfo_check(char *name, int num);
03c05291 37int prefetch_value(struct query *q, char **argv, client *cl);
38int check_nfs(int mach_idx, char *name, char *access);
8e3761a2 39int check_mailman_listname(char *name, const char *suffix);
73cf66ba 40
41/* Setup Routines */
42
43/* Setup routine for add_user
44 *
45 * Inputs: argv[0] - login
46 * argv[1] - uid
47 *
48 * Description:
49 *
50 * - if argv[1] == UNIQUE_UID then set argv[1] = next(uid)
51 * - if argv[0] == UNIQUE_LOGIN then set argv[0] = "#<uid>"
52 */
53
5eaef520 54int setup_ausr(struct query *q, char *argv[], client *cl)
73cf66ba 55{
5eaef520 56 int row, err;
57 EXEC SQL BEGIN DECLARE SECTION;
58 int nuid;
59 EXEC SQL END DECLARE SECTION;
60
61 if (!strcmp(q->shortname, "uusr") || !strcmp(q->shortname, "uuac"))
62 row = 2;
63 else
64 row = 1;
cca8e7ef 65
186dd63b 66 if (q->version > 2)
67 {
68 if (strlen(argv[row + 3]) + strlen(argv[row + 4]) +
69 strlen(argv[row + 5]) + 2 > USERS_FULLNAME_SIZE)
70 return MR_ARG_TOO_LONG;
71 }
72 else
73 {
74 if (strlen(argv[row + 2]) + strlen(argv[row + 3]) +
75 strlen(argv[row + 4]) + 2 > USERS_FULLNAME_SIZE)
76 return MR_ARG_TOO_LONG;
77 }
cca8e7ef 78
aec7d432 79 if (q->version > 10)
80 {
81 /* For both winhomedir and winprofiledir, we allow values of the
82 * following forms:
83 *
84 * [AFS] - Magic token for AFS home directory.
85 * [LOCAL] - Magic token for AD default local values, i.e. C:\<mumble>
6710f1fa 86 * [DFS] - Magic token for DFS home directory
aec7d432 87 * UNC pathname - \\<something>
88 * local pathname - <drive letter>:<something>
89 */
90
91 if ((strcasecmp(argv[row + 12], "[AFS]")) &&
92 (strcasecmp(argv[row + 12], "[LOCAL]")) &&
6710f1fa 93 (strcasecmp(argv[row + 12], "[DFS]")) &&
aec7d432 94 (!(argv[row + 12][0] == '\\' && argv[row + 12][1] == '\\')) &&
95 (!(isalpha(*argv[row + 12]) && (argv[row + 12][1] == ':'))))
96 return MR_BAD_CHAR;
97
98 if ((strcasecmp(argv[row + 13], "[AFS]")) &&
99 (strcasecmp(argv[row + 13], "[LOCAL]")) &&
6710f1fa 100 (strcasecmp(argv[row + 13], "[DFS]")) &&
aec7d432 101 (!(argv[row + 13][0] == '\\' && argv[row + 13][1] == '\\')) &&
102 (!(isalpha(*argv[row + 13]) && (argv[row + 13][1] == ':'))))
103 return MR_BAD_CHAR;
104 }
105
5eaef520 106 if (!strcmp(argv[row], UNIQUE_UID) || atoi(argv[row]) == -1)
107 {
108 if ((err = set_next_object_id("unix_uid", USERS_TABLE, 1)))
109 return err;
110 EXEC SQL SELECT value INTO :nuid FROM numvalues WHERE name = 'unix_uid';
111 if (sqlca.sqlerrd[2] != 1)
112 return MR_INTERNAL;
113 sprintf(argv[row], "%d", nuid);
73cf66ba 114 }
115
5eaef520 116 if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[row]) == -1)
117 sprintf(argv[0], "#%s", argv[row]);
73cf66ba 118
5eaef520 119 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
120 return mr_errcode;
73cf66ba 121
b9f9ab1c 122 /* If this is an MR_Q_UPDATE query, we're done. */
3b634eb3 123 if (row == 2)
124 return MR_SUCCESS;
125
126 /* For an add query, we need to fill in the creator id. */
127 sprintf(argv[q->argc + q->vcnt + 1], "%d", cl->client_id);
5eaef520 128 return MR_SUCCESS;
73cf66ba 129}
130
131
132/* setup_dusr - verify that the user is no longer being referenced
133 * and may safely be deleted.
134 */
135
7ac48069 136int setup_dusr(struct query *q, char *argv[], client *cl)
73cf66ba 137{
5eaef520 138 EXEC SQL BEGIN DECLARE SECTION;
139 int flag, id, cnt;
00c3d0fe 140 char resv[USERS_RESERVATIONS_SIZE];
5eaef520 141 EXEC SQL END DECLARE SECTION;
142
143 id = *(int *)argv[0];
144
ec761008 145 /* For now, only allow users to be deleted if their status is
146 * one of 0, 4, or 8 (the various registerable statuses)
00c3d0fe 147 * and we have no reservations about deleting them.
148 */
149 EXEC SQL SELECT status, reservations INTO :flag, :resv
150 FROM users WHERE users_id = :id;
ec761008 151 if ((flag != 0 && flag != 4 && flag != 8) || *resv)
5eaef520 152 return MR_IN_USE;
153
5eaef520 154 EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
155 WHERE member_id = :id AND member_type = 'USER';
156 if (cnt > 0)
157 return MR_IN_USE;
158 EXEC SQL SELECT COUNT(label) INTO :cnt FROM filesys
159 WHERE owner = :id;
160 if (cnt > 0)
161 return MR_IN_USE;
162 EXEC SQL SELECT COUNT(name) INTO :cnt FROM list
163 WHERE acl_id = :id AND acl_type = 'USER';
164 if (cnt > 0)
165 return MR_IN_USE;
166 EXEC SQL SELECT COUNT(name) INTO :cnt FROM servers
167 WHERE acl_id = :id AND acl_type = 'USER';
168 if (cnt > 0)
169 return MR_IN_USE;
170 EXEC SQL SELECT COUNT(acl_id) INTO :cnt FROM hostaccess
171 WHERE acl_id = :id AND acl_type = 'USER';
172 if (cnt > 0)
173 return MR_IN_USE;
174 if (dbms_errno)
175 return mr_errcode;
00c3d0fe 176
177 EXEC SQL DELETE FROM quota WHERE entity_id = :id AND type = 'USER';
178 EXEC SQL DELETE FROM krbmap WHERE users_id = :id;
5eaef520 179 return MR_SUCCESS;
73cf66ba 180}
181
182
73cf66ba 183/* setup_dpob: Take care of keeping track of the post office usage.
184 */
7ac48069 185int setup_dpob(struct query *q, char *argv[], client *cl)
73cf66ba 186{
5eaef520 187 EXEC SQL BEGIN DECLARE SECTION;
188 int id, user;
e688520a 189 char type[USERS_POTYPE_SIZE];
5eaef520 190 EXEC SQL END DECLARE SECTION;
191
192 user = *(int *)argv[0];
193 EXEC SQL SELECT potype, pop_id INTO :type, :id FROM users
194 WHERE users_id = :user;
195 if (dbms_errno)
196 return mr_errcode;
197
198 if (!strcmp(strtrim(type), "POP"))
199 set_pop_usage(id, -1);
200 return MR_SUCCESS;
73cf66ba 201}
202
203
204/* setup_dmac - verify that the machine is no longer being referenced
205 * and may safely be deleted.
206 */
207
7ac48069 208int setup_dmac(struct query *q, char *argv[], client *cl)
73cf66ba 209{
5eaef520 210 EXEC SQL BEGIN DECLARE SECTION;
211 int flag, id, cnt;
212 EXEC SQL END DECLARE SECTION;
213
214 id = *(int *)argv[0];
215
216 EXEC SQL SELECT status INTO :flag FROM machine
217 WHERE mach_id = :id;
218 if (flag != 3)
219 return MR_IN_USE;
220 EXEC SQL SELECT COUNT(login) INTO :cnt FROM users
221 WHERE potype = 'POP' AND pop_id = :id;
222 if (cnt > 0)
223 return MR_IN_USE;
22bbb6f0 224 EXEC SQL SELECT COUNT(login) INTO :cnt FROM users
225 WHERE potype = 'EXCHANGE' and exchange_id = :id;
226 if (cnt > 0)
227 return MR_IN_USE;
5eaef520 228 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM serverhosts
229 WHERE mach_id = :id;
230 if (cnt > 0)
231 return MR_IN_USE;
232 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM nfsphys
233 WHERE mach_id = :id;
234 if (cnt > 0)
235 return MR_IN_USE;
236 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM hostaccess
237 WHERE mach_id = :id;
238 if (cnt > 0)
239 return MR_IN_USE;
2884200f 240 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM printers
5eaef520 241 WHERE mach_id = :id;
242 if (cnt > 0)
243 return MR_IN_USE;
2884200f 244 EXEC SQL SELECT COUNT(rm) INTO :cnt FROM printers
245 WHERE rm = :id;
246 if (cnt > 0)
247 return MR_IN_USE;
248 EXEC SQL SELECT COUNT(rq) INTO :cnt FROM printers
249 WHERE rq = :id;
5eaef520 250 if (cnt > 0)
251 return MR_IN_USE;
1a9a0a59 252 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM printservers
5eaef520 253 WHERE mach_id = :id;
254 if (cnt > 0)
255 return MR_IN_USE;
256 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM hostalias
257 WHERE mach_id = :id;
258 if (cnt > 0)
259 return MR_IN_USE;
5f7b0741 260 EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
261 WHERE member_type = 'MACHINE' and member_id = :id;
262 if (cnt > 0)
263 return MR_IN_USE;
5eaef520 264
265 EXEC SQL DELETE FROM mcmap WHERE mach_id = :id;
2fb668b0 266 if (dbms_errno)
267 return mr_errcode;
268
269 EXEC SQL DELETE FROM mcntmap WHERE mach_id = :id;
5eaef520 270 if (dbms_errno)
271 return mr_errcode;
272 return MR_SUCCESS;
73cf66ba 273}
274
4f6b1a05 275/* setup_asnt - verify that the data entered for the subnet is sane.
276 * In particular, make sure that the "low" and "high" addresses are
277 * correctly ordered, i.e., high > low.
278 */
279
280int setup_asnt(struct query *q, char *argv[], client *cl)
281{
282 int high, low, row, status;
283 char *account_number;
284
285 /* Check for asnt or usnt. */
b9f9ab1c 286 if (q->type == MR_Q_APPEND)
4f6b1a05 287 row = 0;
288 else
289 row = 1;
290
291 low = atoi(argv[row + 7]);
292 high = atoi(argv[row + 8]);
293 status = atoi(argv[row + 2]);
294 account_number = argv[row + 4];
295
296 /* Don't allow Private subnets to be created without a valid billing
297 * number.
298 */
79f30489 299 if (status == SNET_STATUS_PRIVATE_10MBPS ||
4425deab 300 status == SNET_STATUS_PRIVATE_100MBPS ||
301 status == SNET_STATUS_PRIVATE_1000MBPS)
4f6b1a05 302 {
303 EXEC SQL SELECT account_number FROM accountnumbers
304 WHERE account_number = :account_number;
305 if (sqlca.sqlcode == SQL_NO_MATCH)
306 return MR_ACCOUNT_NUMBER;
307 }
308
309 /* Special case 0.0.0.0 and 255.255.255.255 */
310 if (!(low == 0 || low == -1 || high == 0 || high == -1))
311 if (low > high)
312 return MR_ADDRESS;
313
314 /* If this is update_subnet, we're done. */
315 if (row == 1)
316 return MR_SUCCESS;
317
318 /* For an add_subnet query, allocate and fill in a new snet_id */
319 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
320 return mr_errcode;
321
322 return MR_SUCCESS;
323}
73cf66ba 324
325/* setup_dsnt - verify that the subnet is no longer being referenced
326 * and may safely be deleted.
327 */
328
7ac48069 329int setup_dsnt(struct query *q, char *argv[], client *cl)
73cf66ba 330{
5eaef520 331 EXEC SQL BEGIN DECLARE SECTION;
332 int id, cnt = 0;
333 EXEC SQL END DECLARE SECTION;
334
335 id = *(int *)argv[0];
336 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM machine
337 WHERE snet_id = :id;
338 if (cnt > 0)
339 return MR_IN_USE;
340 return MR_SUCCESS;
73cf66ba 341}
342
343
344/* setup_dclu - verify that the cluster is no longer being referenced
345 * and may safely be deleted.
346 */
347
7ac48069 348int setup_dclu(struct query *q, char *argv[], client *cl)
73cf66ba 349{
5eaef520 350 EXEC SQL BEGIN DECLARE SECTION;
351 int id, cnt;
352 EXEC SQL END DECLARE SECTION;
353
354 id = *(int *)argv[0];
355 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM mcmap
356 WHERE clu_id = :id;
357 if (cnt > 0)
358 return MR_IN_USE;
359 EXEC SQL SELECT COUNT(clu_id) INTO :cnt FROM svc
360 WHERE clu_id = :id;
361 if (cnt > 0)
362 return MR_IN_USE;
363 if (dbms_errno)
364 return mr_errcode;
365 return MR_SUCCESS;
73cf66ba 366}
367
368
369/* setup_alis - if argv[5] is non-zero and argv[6] is UNIQUE_ID, then allocate
370 * a new gid and put it in argv[6]. Otherwise if argv[6] is UNIQUE_ID but
371 * argv[5] is not, then remember that UNIQUE_ID is being stored by putting
372 * a -1 there. Remember that this is also used for ulis, with the indexes
373 * at 6 & 7. Also check that the list name does not contain uppercase
374 * characters, control characters, @, or :.
8e45963f 375 *
376 * Newlines in list descriptions do bad things to the aliases file
377 * moira generates, so make sure the description doesn't contain any, too.
73cf66ba 378 */
379
380static int badlistchars[] = {
5eaef520 381 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
382 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
771397b1 383 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, /* SPACE - / */
0b452293 384 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 0 - ? */
5eaef520 385 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
0b452293 386 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* P - _ */
5eaef520 387 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
0b452293 388 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
5eaef520 389 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
390 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
391 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
392 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
393 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
394 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
395 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
396 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
73cf66ba 397};
398
514054a9 399static const char *mailman_suffixes[] = { "-admin", "-owner", "-request",
400 "-bounces", "-confirm", "-join",
401 "-leave", "-subscribe",
402 "-unsubscribe", NULL };
403
5eaef520 404int setup_alis(struct query *q, char *argv[], client *cl)
73cf66ba 405{
5eaef520 406 EXEC SQL BEGIN DECLARE SECTION;
c034b756 407 int ngid, cnt, mailman, mailman_id, lid;
8e45963f 408 char *name, *desc;
5eaef520 409 EXEC SQL END DECLARE SECTION;
410 unsigned char *p;
514054a9 411 int idx, err, best = -1, usage, i;
5eaef520 412
413 if (!strcmp(q->shortname, "alis"))
414 idx = 0;
415 else if (!strcmp(q->shortname, "ulis"))
416 idx = 1;
17f585b5 417 name = argv[idx];
771397b1 418
419 if (q->version == 2)
420 desc = argv[9 + idx];
421 else if (q->version == 3)
422 desc = argv[10 + idx];
8e3761a2 423 else if (q->version == 4)
771397b1 424 desc = argv[12 + idx];
8e3761a2 425 else if (q->version >= 10)
426 desc = argv[14 + idx];
5eaef520 427
5a22fdf5 428 if (idx == 1)
429 {
c034b756 430 lid = *(int *)argv[0];
5a22fdf5 431
432 if (acl_access_check(lid, cl))
433 return MR_PERM;
434 }
435
17f585b5 436 for (p = (unsigned char *) name; *p; p++)
5eaef520 437 {
73cf66ba 438 if (badlistchars[*p])
5eaef520 439 return MR_BAD_CHAR;
440 }
441
8e45963f 442 for (p = (unsigned char *) desc; *p; p++)
443 {
444 if (*p == '\n')
445 return MR_BAD_CHAR;
446 }
447
17f585b5 448 /* Check that it doesn't conflict with a pre-existing weirdly-cased
449 * name. */
450 EXEC SQL SELECT COUNT(name) INTO :cnt FROM list
20315440 451 WHERE LOWER(name) = :name AND name != :name;
17f585b5 452 if (cnt)
453 return MR_EXISTS;
454
5eaef520 455 if (!strcmp(argv[6 + idx], UNIQUE_GID) || atoi(argv[6 + idx]) == -1)
456 {
457 if (atoi(argv[5 + idx]))
458 {
459 if ((err = set_next_object_id("gid", LIST_TABLE, 1)))
460 return err;
461 EXEC SQL SELECT value INTO :ngid FROM numvalues
462 WHERE name = 'gid';
463 if (dbms_errno)
464 return mr_errcode;
465 sprintf(argv[6 + idx], "%d", ngid);
73cf66ba 466 }
5eaef520 467 else
468 strcpy(argv[6 + idx], "-1");
73cf66ba 469 }
470
8e3761a2 471 /* Don't let someone rename a list to one of the magic mailman names
472 * (foo-admin, etc) if foo already exists as a mailman list.
473 */
514054a9 474 for (i = 0; mailman_suffixes[i]; i++)
475 {
476 if ((err = check_mailman_listname(name, mailman_suffixes[i]))
477 != MR_SUCCESS)
478 return err;
479 }
8e3761a2 480
481 if (q->version >= 10)
482 {
483 /* Don't let them take this name for a mailman list if we can't
484 * reserve the -admin, -owner, and -request names.
485 */
486 if (atoi(argv[8 + idx]))
487 {
488 EXEC SQL SELECT COUNT(name) INTO :cnt FROM list
489 WHERE (name = :name || '-admin' OR name = :name || '-owner' OR
490 name = :name || '-request');
491 if (cnt)
492 return MR_EXISTS;
493 }
494
495 /* Handle the [ANY] case for mailman server. */
496 mailman_id = *(int *)argv[9 + idx];
497 if (mailman_id == -1)
498 {
499 EXEC SQL DECLARE csr_mailman CURSOR FOR
500 SELECT mach_id FROM serverhosts WHERE service = 'MAILMAN'
501 AND enable = 1;
502 if (dbms_errno)
503 return mr_errcode;
504 EXEC SQL OPEN csr_mailman;
505 if (dbms_errno)
506 return mr_errcode;
507
508 while (1)
509 {
510 EXEC SQL FETCH csr_mailman INTO :mailman_id;
511 if (sqlca.sqlcode)
512 break;
513
514 EXEC SQL SELECT COUNT(name) INTO :usage FROM list
515 WHERE mailman_id = :mailman_id;
516
517 if (best < 0 || usage < best)
518 {
519 best = usage;
520 *(int *)argv[9 + idx] = mailman_id;
521 break;
522 }
523 }
524 EXEC SQL CLOSE csr_mailman;
525 if (dbms_errno)
526 return mr_errcode;
527
528 if (best == -1)
529 return MR_SERVICE;
530 }
531 }
4656d650 532 else
533 {
534 /* Client too old to know about the mailman code.
535 * Use existing value of mailman boolean in the table.
c034b756 536 * Don't do this for add_list from an old client, since the row
537 * they're creating won't exist yet, and there's no way for them to
538 * create a list with the mailman bit set, anyway.
4656d650 539 */
c034b756 540 if (idx == 1)
4656d650 541 {
c034b756 542 EXEC SQL SELECT mailman INTO :mailman FROM list WHERE list_id = :lid;
543 if (mailman)
544 {
545 EXEC SQL SELECT COUNT(name) INTO :cnt FROM list
546 WHERE (name = :name || '-admin' OR name = :name || '-owner' OR
547 name = :name || '-request');
548 if (cnt)
549 return MR_EXISTS;
550 }
4656d650 551 }
552 }
8e3761a2 553
5eaef520 554 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
555 return mr_errcode;
73cf66ba 556
5eaef520 557 return MR_SUCCESS;
73cf66ba 558}
559
560
561/* setup_dlis - verify that the list is no longer being referenced
562 * and may safely be deleted.
563 */
564
7ac48069 565int setup_dlis(struct query *q, char *argv[], client *cl)
73cf66ba 566{
5eaef520 567 int id;
568 EXEC SQL BEGIN DECLARE SECTION;
569 int cnt;
570 EXEC SQL END DECLARE SECTION;
571
572 id = *(int *)argv[0];
573
574 EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
575 WHERE member_id = :id AND member_type = 'LIST';
576 if (cnt > 0)
577 return MR_IN_USE;
578
579 EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
580 WHERE member_id = :id AND member_type = 'LIST';
581 if (cnt > 0)
582 return MR_IN_USE;
583
584 EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
585 WHERE list_id = :id;
586 if (cnt > 0)
587 return MR_IN_USE;
588
589 EXEC SQL SELECT COUNT(label) INTO :cnt FROM filesys WHERE owners = :id;
590 if (cnt > 0)
591 return MR_IN_USE;
592
593 EXEC SQL SELECT COUNT(tag) INTO :cnt FROM capacls WHERE list_id = :id;
594 if (cnt > 0)
595 return MR_IN_USE;
596
597 EXEC SQL SELECT COUNT(name) INTO :cnt FROM list
598 WHERE acl_id = :id AND acl_type = 'LIST' AND list_id != :id;
599 if (cnt > 0)
600 return MR_IN_USE;
601
40a6abf9 602 EXEC SQL SELECT COUNT(name) INTO :cnt FROM list
603 WHERE memacl_id = :id AND memacl_type = 'LIST' AND list_id != :id;
604 if (cnt > 0)
605 return MR_IN_USE;
606
5eaef520 607 EXEC SQL SELECT COUNT(name) INTO :cnt FROM servers
608 WHERE acl_id = :id AND acl_type = 'LIST';
609 if (cnt > 0)
610 return MR_IN_USE;
611
612 EXEC SQL SELECT COUNT(entity_id) INTO :cnt FROM quota
613 WHERE entity_id = :id AND type = 'GROUP';
614 if (cnt > 0)
615 return MR_IN_USE;
616
617 EXEC SQL SELECT COUNT(acl_id) INTO :cnt FROM hostaccess
618 WHERE acl_id = :id AND acl_type = 'LIST';
619 if (cnt > 0)
620 return MR_IN_USE;
621
622 EXEC SQL SELECT COUNT(class) INTO :cnt FROM zephyr z
623 WHERE z.xmt_type = 'LIST' AND z.xmt_id = :id
624 OR z.sub_type = 'LIST' AND z.sub_id = :id
625 OR z.iws_type = 'LIST' AND z.iws_id = :id
34463187 626 OR z.iui_type = 'LIST' AND z.iui_id = :id
627 OR z.owner_type = 'LIST' and z.owner_id = :id;
5eaef520 628 if (cnt > 0)
629 return MR_IN_USE;
630
1a9a0a59 631 EXEC SQL SELECT COUNT(name) INTO :cnt FROM printers
632 WHERE lpc_acl = :id OR ac = :id;
633 if (cnt > 0)
634 return MR_IN_USE;
635
636 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM printservers
637 WHERE owner_type = 'LIST' AND owner_id = :id
638 OR lpc_acl = :id;
639 if (cnt > 0)
640 return MR_IN_USE;
641
b68ef115 642 EXEC SQL SELECT count(name) INTO :cnt FROM containers
643 WHERE acl_id = :id AND acl_type = 'LIST';
644 if (cnt > 0)
645 return MR_IN_USE;
646
647 EXEC SQL SELECT count(name) INTO :cnt FROM containers
648 WHERE memacl_id = :id AND memacl_type = 'LIST';
649 if (cnt > 0)
650 return MR_IN_USE;
651
5eaef520 652 return MR_SUCCESS;
73cf66ba 653}
654
655
656/* setup_dsin - verify that the service is no longer being referenced
657 * and may safely be deleted.
658 */
659
7ac48069 660int setup_dsin(struct query *q, char *argv[], client *cl)
73cf66ba 661{
5eaef520 662 EXEC SQL BEGIN DECLARE SECTION;
663 int ec, cnt;
664 char *svrname;
665 EXEC SQL END DECLARE SECTION;
666
667 svrname = argv[0];
668 EXEC SQL SELECT COUNT(service) INTO :cnt FROM serverhosts
669 WHERE service = UPPER(:svrname);
670 if (cnt > 0)
671 return MR_IN_USE;
672
673 EXEC SQL SELECT inprogress INTO :ec FROM servers
674 WHERE name = UPPER(:svrname);
675 if (dbms_errno)
676 return mr_errcode;
677 if (ec)
678 return MR_IN_USE;
679
680 return MR_SUCCESS;
73cf66ba 681}
682
683
684/* setup_dshi - verify that the service-host is no longer being referenced
685 * and may safely be deleted.
686 */
687
7ac48069 688int setup_dshi(struct query *q, char *argv[], client *cl)
73cf66ba 689{
5eaef520 690 EXEC SQL BEGIN DECLARE SECTION;
691 int id, ec;
692 char *svrname;
693 EXEC SQL END DECLARE SECTION;
694
695 svrname = argv[0];
696 id = *(int *)argv[1];
697
698 EXEC SQL SELECT inprogress INTO :ec FROM serverhosts
699 WHERE service = UPPER(:svrname) AND mach_id = :id;
700 if (dbms_errno)
701 return mr_errcode;
702 if (ec)
703 return MR_IN_USE;
704
705 return MR_SUCCESS;
73cf66ba 706}
707
708
709/**
710 ** setup_add_filesys - verify existance of referenced file systems
711 **
712 ** Inputs: Add
713 ** argv[1] - type
714 ** argv[2] - mach_id
715 ** argv[3] - name
03c05291 716 ** argv[5] - rwaccess
73cf66ba 717 **
718 ** Description:
719 ** - for type = RVD:
720 ** * allow anything
cc1bca5c 721 ** - for type = NFS/IMAP:
73cf66ba 722 ** * extract directory prefix from name
723 ** * verify mach_id/dir in nfsphys
03c05291 724 ** * verify rwaccess in {r, w, R, W}
73cf66ba 725 **
726 ** Side effect: sets variable _var_phys_id to the ID of the physical
727 ** filesystem (nfsphys_id for NFS, 0 for RVD)
728 **
729 ** Errors:
730 ** MR_NFS - specified directory not exported
731 ** MR_FILESYS_ACCESS - invalid filesys access
732 **
733 **/
734
735EXEC SQL BEGIN DECLARE SECTION;
736int _var_phys_id;
737EXEC SQL END DECLARE SECTION;
738
5eaef520 739int setup_afil(struct query *q, char *argv[], client *cl)
73cf66ba 740{
5eaef520 741 char *type, *name;
742 int mach_id;
743 EXEC SQL BEGIN DECLARE SECTION;
744 int ok;
e688520a 745 char ftype[FILESYS_TYPE_SIZE + 10], *rwaccess;
5eaef520 746 EXEC SQL END DECLARE SECTION;
747
748 type = argv[1];
749 mach_id = *(int *)argv[2];
750 name = argv[3];
751 rwaccess = argv[5];
752 _var_phys_id = 0;
753
754 sprintf(ftype, "fs_access_%s", type);
755 EXEC SQL SELECT COUNT(trans) INTO :ok FROM alias
756 WHERE name = :ftype AND type = 'TYPE' and trans = :rwaccess;
757 if (dbms_errno)
758 return mr_errcode;
759 if (ok == 0)
760 return MR_FILESYS_ACCESS;
761
762 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
763 return mr_errcode;
764
cc1bca5c 765 if (!strcmp(type, "NFS") || !strcmp(type, "IMAP"))
5eaef520 766 return check_nfs(mach_id, name, rwaccess);
767
768 return MR_SUCCESS;
73cf66ba 769}
770
771
772/* Verify the arguments, depending on the FStype. Also, if this is an
773 * NFS filesystem, then update any quotas for that filesystem to reflect
774 * the new phys_id.
775 */
776
5eaef520 777int setup_ufil(struct query *q, char *argv[], client *cl)
73cf66ba 778{
5eaef520 779 int mach_id, status;
780 char *type, *name;
781 EXEC SQL BEGIN DECLARE SECTION;
782 int fid, total, who, ok;
e688520a 783 char *entity, ftype[FILESYS_TYPE_SIZE + 10], *access;
5eaef520 784 short int total_null;
785 EXEC SQL END DECLARE SECTION;
786
787 _var_phys_id = 0;
788 type = argv[2];
789 mach_id = *(int *)argv[3];
790 name = argv[4];
791 access = argv[6];
792 fid = *(int *)argv[0];
793 who = cl->client_id;
794 entity = cl->entity;
795
796 sprintf(ftype, "fs_access_%s", type);
797 EXEC SQL SELECT COUNT(trans) INTO :ok FROM alias
798 WHERE name = :ftype AND type = 'TYPE' AND trans = :access;
799 if (dbms_errno)
800 return mr_errcode;
801 if (ok == 0)
802 return MR_FILESYS_ACCESS;
803
804 EXEC SQL SELECT type INTO :ftype FROM filesys
805 WHERE filsys_id = :fid;
806 if (dbms_errno)
807 return mr_errcode;
808
cc1bca5c 809 if (!strcmp(type, "NFS") || !strcmp(type, "IMAP"))
5eaef520 810 {
811 status = check_nfs(mach_id, name, access);
812 EXEC SQL UPDATE quota SET phys_id = :_var_phys_id
813 WHERE filsys_id = :fid;
814 if (dbms_errno)
815 return mr_errcode;
816 return status;
817 }
818 else if (!strcmp(type, "AFS") && strcmp(strtrim(ftype), "AFS")
819 && strcmp(strtrim(ftype), "ERR"))
820 {
821 total = 0;
822 EXEC SQL DELETE FROM quota
823 WHERE type = 'ANY' AND filsys_id = :fid;
824 EXEC SQL SELECT SUM (quota) INTO :total:total_null FROM quota
825 WHERE filsys_id = :fid AND phys_id != 0;
826 if (dbms_errno)
827 return mr_errcode;
828 if (!total_null && (total != 0))
829 {
830 EXEC SQL INSERT INTO quota (quota, filsys_id, phys_id, entity_id,
831 type, modtime, modby, modwith)
832 VALUES (:total, :fid, 0, 0, 'ANY', SYSDATE, :who, :entity);
833 if (dbms_errno)
834 return mr_errcode;
73cf66ba 835 }
73cf66ba 836 }
5eaef520 837 else
838 {
839 EXEC SQL UPDATE quota SET phys_id = 0 WHERE filsys_id = :fid;
840 if (dbms_errno)
841 return mr_errcode;
842 }
843 return MR_SUCCESS;
73cf66ba 844}
845
846
847/* Find the NFS physical partition that the named directory is on.
848 * This is done by comparing the dir against the mount point of the
849 * partition. To make sure we get the correct match when there is
850 * more than one, we sort the query in reverse order by dir name.
851 */
852
5eaef520 853int check_nfs(int mach_id, char *name, char *access)
73cf66ba 854{
5eaef520 855 EXEC SQL BEGIN DECLARE SECTION;
e688520a 856 char dir[NFSPHYS_DIR_SIZE];
5eaef520 857 int mid = mach_id;
858 EXEC SQL END DECLARE SECTION;
44d12d58 859 int status;
860 char *cp1;
861 char *cp2;
5eaef520 862
863 status = MR_NFS;
864 EXEC SQL DECLARE csr101 CURSOR FOR
865 SELECT nfsphys_id, dir FROM nfsphys
866 WHERE mach_id = :mid
867 ORDER BY 2 DESC;
868 if (dbms_errno)
869 return mr_errcode;
870 EXEC SQL OPEN csr101;
871 if (dbms_errno)
872 return mr_errcode;
873 while (1)
874 {
875 EXEC SQL FETCH csr101 INTO :_var_phys_id, :dir;
876 if (sqlca.sqlcode)
877 break;
878 cp1 = name;
879 cp2 = strtrim(dir);
880 while (*cp2)
881 {
882 if (*cp1++ != *cp2)
73cf66ba 883 break;
5eaef520 884 cp2++;
885 }
886 if (!*cp2)
887 {
888 status = MR_SUCCESS;
889 break;
73cf66ba 890 }
891 }
5eaef520 892 EXEC SQL CLOSE csr101;
893 if (dbms_errno)
894 return mr_errcode;
895 return status;
73cf66ba 896}
897
898
899/* setup_dfil: free any quota records and fsgroup info associated with
900 * a filesystem when it is deleted. Also adjust the allocation numbers.
901 */
902
5eaef520 903int setup_dfil(struct query *q, char **argv, client *cl)
73cf66ba 904{
5eaef520 905 EXEC SQL BEGIN DECLARE SECTION;
906 int id, total, phys_id;
907 short int none;
908 EXEC SQL END DECLARE SECTION;
909
910 id = *(int *)argv[0];
911 EXEC SQL SELECT SUM (quota) INTO :total:none FROM quota
912 WHERE filsys_id = :id;
913
914 if (none)
915 total = 0;
916
917 /** What if there are multiple phys_id's per f/s? (bad data) **/
918 EXEC SQL SELECT phys_id INTO :phys_id FROM filesys
919 WHERE filsys_id = :id;
920 EXEC SQL UPDATE nfsphys SET allocated = allocated - :total
921 WHERE nfsphys_id = :phys_id;
922
923 if (!none)
924 EXEC SQL DELETE FROM quota WHERE filsys_id = :id;
925 EXEC SQL DELETE FROM fsgroup WHERE filsys_id = :id;
926 EXEC SQL DELETE FROM fsgroup WHERE group_id = :id;
927 if (dbms_errno)
928 return mr_errcode;
929 return MR_SUCCESS;
73cf66ba 930}
931
932
933/* setup_dnfp: check to see that the nfs physical partition does not have
934 * any filesystems assigned to it before allowing it to be deleted.
935 */
936
5eaef520 937int setup_dnfp(struct query *q, char **argv, client *cl)
73cf66ba 938{
5eaef520 939 EXEC SQL BEGIN DECLARE SECTION;
940 int id, cnt;
941 char *dir;
942 EXEC SQL END DECLARE SECTION;
943
944 id = *(int *)argv[0];
945 dir = argv[1];
946 EXEC SQL SELECT count(fs.rowid) INTO :cnt FROM filesys fs, nfsphys np
947 WHERE fs.mach_id = :id AND fs.phys_id = np.nfsphys_id
948 AND np.mach_id = :id AND np.dir = :dir;
949 if (cnt > 0)
950 return MR_IN_USE;
951 if (dbms_errno)
952 return mr_errcode;
953 return MR_SUCCESS;
73cf66ba 954}
955
956
957/* setup_dqot: Remove allocation from nfsphys before deleting quota.
958 * argv[0] = filsys_id
959 * argv[1] = type if "update_quota" or "delete_quota"
960 * argv[2 or 1] = users_id or list_id
961 */
962
5eaef520 963int setup_dqot(struct query *q, char **argv, client *cl)
73cf66ba 964{
5eaef520 965 EXEC SQL BEGIN DECLARE SECTION;
966 int quota, fs, id, physid;
967 char *qtype;
968 EXEC SQL END DECLARE SECTION;
969
970 fs = *(int *)argv[0];
971 if (!strcmp(q->name, "update_quota") || !strcmp(q->name, "delete_quota"))
972 {
973 qtype = argv[1];
974 id = *(int *)argv[2];
975 }
976 else
977 {
978 qtype = "USER";
979 id = *(int *)argv[1];
73cf66ba 980 }
981
5eaef520 982 EXEC SQL SELECT quota INTO :quota FROM quota
983 WHERE type = :qtype AND entity_id = :id AND filsys_id = :fs;
984 EXEC SQL SELECT phys_id INTO :physid FROM filesys
985 WHERE filsys_id = :fs;
986 EXEC SQL UPDATE nfsphys SET allocated = allocated - :quota
987 WHERE nfsphys_id = :physid;
73cf66ba 988
5eaef520 989 if (dbms_errno)
990 return mr_errcode;
991 return MR_SUCCESS;
73cf66ba 992}
993
994
7f426981 995/* prefetch_value():
996 * This routine fetches an appropriate value from the numvalues table.
997 * It is a little hack to get around the fact that SQL doesn't let you
998 * do something like INSERT INTO table (foo) VALUES (other_table.bar).
999 *
5eaef520 1000 * It is called from the query table as (*v->pre_rtn)(q, Argv, cl) or
7f426981 1001 * from within a setup_...() routine with the appropriate arguments.
1002 *
1003 * Correct functioning of this routine may depend on the assumption
b9f9ab1c 1004 * that this query is an MR_Q_APPEND.
7f426981 1005 */
1006
5eaef520 1007int prefetch_value(struct query *q, char **argv, client *cl)
7f426981 1008{
5eaef520 1009 EXEC SQL BEGIN DECLARE SECTION;
1010 char *name = q->validate->object_id;
1011 int value;
1012 EXEC SQL END DECLARE SECTION;
1013 int status, limit, argc;
1014
1015 /* set next object id, limiting it if necessary */
1016 if (!strcmp(name, "unix_uid") || !strcmp(name, "gid"))
1017 limit = 1; /* So far as I know, this isn't needed. Just CMA. */
1018 else
1019 limit = 0;
1020 if ((status = set_next_object_id(name, q->rtable, limit)) != MR_SUCCESS)
1021 return status;
1022
1023 /* fetch object id */
1024 EXEC SQL SELECT value INTO :value FROM numvalues WHERE name = :name;
1025 if (dbms_errno)
1026 return mr_errcode;
1027 if (sqlca.sqlerrd[2] != 1)
1028 return MR_INTERNAL;
1029
b9f9ab1c 1030 argc = q->argc + q->vcnt; /* end of Argv for MR_Q_APPENDs */
5eaef520 1031 sprintf(argv[argc], "%d", value);
1032
1033 return MR_SUCCESS;
7f426981 1034}
1035
1036/* prefetch_filesys():
1037 * Fetches the phys_id from filesys based on the filsys_id in argv[0].
1038 * Appends the filsys_id and the phys_id to the argv so they can be
1039 * referenced in an INSERT into a table other than filesys. Also
1040 * see comments at prefetch_value().
1041 *
1042 * Assumes the existence of a row where filsys_id = argv[0], since a
1043 * filesys label has already been resolved to a filsys_id.
1044 */
5eaef520 1045int prefetch_filesys(struct query *q, char **argv, client *cl)
7f426981 1046{
5eaef520 1047 EXEC SQL BEGIN DECLARE SECTION;
1048 int fid, phid;
1049 EXEC SQL END DECLARE SECTION;
1050 int argc;
7f426981 1051
5eaef520 1052 fid = *(int *)argv[0];
1053 EXEC SQL SELECT phys_id INTO :phid FROM filesys WHERE filsys_id = :fid;
1054 if (dbms_errno)
1055 return mr_errcode;
7f426981 1056
5eaef520 1057 argc = q->argc + q->vcnt;
1058 sprintf(argv[argc++], "%d", phid);
1059 sprintf(argv[argc], "%d", fid);
7f426981 1060
5eaef520 1061 return MR_SUCCESS;
7f426981 1062}
1063
1064
c1fe2b12 1065/* setup_ghst():
1066 */
1067
1068int setup_ghst(struct query *q, char **argv, client *cl)
1069{
1070 if (strcmp(argv[0], "*") || strcmp(argv[1], "*") ||
1071 strcmp(argv[2], "*") || strcmp(argv[3], "*"))
1072 return MR_SUCCESS;
1073 else
1074 return MR_PERM;
1075}
1076
7f426981 1077/* setup_ahst():
1078 */
1079
5eaef520 1080int setup_ahst(struct query *q, char **argv, client *cl)
7f426981 1081{
5eaef520 1082 EXEC SQL BEGIN DECLARE SECTION;
e688520a 1083 char *name, oldname[MACHINE_NAME_SIZE], vendor[MACHINE_VENDOR_SIZE];
db9491c6 1084 char model[MACHINE_MODEL_SIZE], os[MACHINE_OS_SIZE];
ff98438b 1085 int value, id, ssaddr, smask, shigh, slow, cnt;
1086 unsigned int saddr, mask, high, low;
5eaef520 1087 EXEC SQL END DECLARE SECTION;
e4ae0190 1088 int row, idx;
5eaef520 1089 struct in_addr addr;
5eaef520 1090
fde09f2c 1091 id = *(int *)argv[0];
1092
5eaef520 1093 if (!strcmp(q->shortname, "uhst"))
85330553 1094 {
1095 row = 1;
1096 EXEC SQL SELECT name, vendor, model, os
1097 INTO :oldname, :vendor, :model, :os
1098 FROM machine WHERE mach_id = :id;
1099 }
5eaef520 1100 else
1101 row = 0;
1102
e4ae0190 1103 if (q->version < 6)
1104 idx = 0;
4f6b1a05 1105 else if (q->version >= 6 && q->version < 8)
e4ae0190 1106 idx = 1;
4f6b1a05 1107 else
1108 idx = 2;
e4ae0190 1109
9e252e6f 1110 /* Sanity check name, vendor, model, and os. */
1111 if ((row == 0 || strcasecmp(argv[1], oldname)) &&
1112 !hostname_check(argv[row]))
1113 return MR_BAD_CHAR;
1114 if ((row == 0 || strcasecmp(argv[2], vendor)) &&
17f585b5 1115 !hostinfo_check(argv[row + 1], 0))
9e252e6f 1116 return MR_BAD_CHAR;
1117 if ((row == 0 || strcasecmp(argv[3], model)) &&
17f585b5 1118 !hostinfo_check(argv[row + 2], 1))
9e252e6f 1119 return MR_BAD_CHAR;
1120 if ((row == 0 || strcasecmp(argv[4], os)) &&
17f585b5 1121 !hostinfo_check(argv[row + 3], 0))
9e252e6f 1122 return MR_BAD_CHAR;
8ca3e341 1123
5eaef520 1124 /* check for duplicate name */
1125 name = argv[row];
1126 EXEC SQL SELECT count(mach_id) INTO :cnt FROM hostalias
ad06a10e 1127 WHERE name = UPPER(:name);
5eaef520 1128 if (dbms_errno)
1129 return mr_errcode;
1130 if (cnt != 0)
1131 return MR_EXISTS;
1132
1133 /* check address */
e4ae0190 1134 if (!strcmp(argv[9 + row + idx], "unassigned"))
5eaef520 1135 value = -1;
e4ae0190 1136 else if (!strcmp(argv[9 + row + idx], "unique"))
5eaef520 1137 {
e4ae0190 1138 if (*(int *)argv[8 + row + idx] == 0)
5eaef520 1139 value = -1;
1140 else
1141 value = -2;
1142 }
1143 else
1144 {
e4ae0190 1145 value = ntohl(inet_addr(argv[9 + row + idx]));
5eaef520 1146 if (value == -1)
1147 return MR_ADDRESS;
5482f508 1148 }
5eaef520 1149 if (value == 0)
1150 return MR_ADDRESS;
1151 if (value != -1)
1152 {
1153 /*
1154 * an address or unique was specified.
1155 */
e4ae0190 1156 id = *(int *)argv[8 + row + idx];
ff98438b 1157 EXEC SQL SELECT saddr, mask, high, low INTO :ssaddr, :smask,
1158 :shigh, :slow FROM subnet WHERE snet_id = :id;
5eaef520 1159 if (dbms_errno)
1160 return mr_errcode;
ff98438b 1161 saddr = (unsigned) ssaddr;
1162 mask = (unsigned) smask;
1163 high = (unsigned) shigh;
1164 low = (unsigned) slow;
5eaef520 1165 if (value != -2)
1166 {
1167 /*
1168 * someone specified an IP address for the host record
1169 */
082466aa 1170 if ((value & mask) != saddr || value < low || value > high)
5eaef520 1171 return MR_ADDRESS;
1172 /*
1173 * run the address argument through inet_addr(). This
1174 * has the effect that any out of bounds host addrs will
1175 * be converted to a valid host addr. We do this now
1176 * so that the uniqueness check works. We should also
1177 * link in an inet_addr() that returns an error for
1178 * this case.
1179 */
e4ae0190 1180 addr.s_addr = inet_addr(argv[9 + row + idx]);
5eaef520 1181 name = inet_ntoa(addr);
1182 EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine
1183 WHERE address = :name;
1184 if (dbms_errno)
1185 return mr_errcode;
1186 if (cnt > 0)
1187 {
1188 /*
1189 * make IP address is unique. If this a modify request
1190 * (row == 1), then we expect one record to exist.
1191 */
7ac48069 1192 if (row == 0 || (row == 1 && cnt > 1))
5eaef520 1193 return MR_ADDRESS;
1194 if (row == 1 && cnt == 1)
1195 {
1196 EXEC SQL SELECT mach_id INTO :id FROM machine
1197 WHERE address = :name;
1198 if (id != *(int *)argv[0])
1199 return MR_ADDRESS;
7f426981 1200 }
1201 }
5eaef520 1202 }
1203 else
1204 {
1205 /*
1206 * a "unique" address was specified. Walk through the
1207 * range specified in the network record, return
1208 * error if no room left.
1209 */
1210 for (id = low; id <= high; id++)
1211 {
1212 if (((id & 0xff) == 0) || ((id & 0xff) == 255))
1213 continue;
1214 addr.s_addr = htonl(id);
7ac48069 1215 name = inet_ntoa(addr);
5eaef520 1216 EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine
1217 WHERE address = :name;
1218 if (dbms_errno)
1219 return mr_errcode;
1220 if (cnt == 0)
1221 break;
7f426981 1222 }
5eaef520 1223 if (cnt != 0)
6715bac2 1224 return MR_NO_ID;
5eaef520 1225 else
1226 value = htonl(id);
7f426981 1227 }
5eaef520 1228 /*
1229 * we have an address in value. Convert it to a string and store it.
1230 */
1231 addr.s_addr = htonl(value);
e4ae0190 1232 strcpy(argv[9 + row + idx], inet_ntoa(addr));
7f426981 1233 }
5eaef520 1234 else
e4ae0190 1235 strcpy(argv[9 + row + idx], "unassigned");
5eaef520 1236
1237 /* status checking */
e4ae0190 1238 value = atoi(argv[7 + row + idx]);
5eaef520 1239 if (row == 0 && !(value == 1 || value == 0))
1240 return MR_TYPE;
1241 if (row == 1)
1242 {
1243 id = *(int *)argv[0];
1244 EXEC SQL SELECT status INTO :cnt FROM machine WHERE mach_id = :id;
1245 if (dbms_errno)
1246 return mr_errcode;
1247 if (value != cnt)
1248 {
1249 EXEC SQL UPDATE machine SET statuschange = SYSDATE
1250 WHERE mach_id = :id;
7f426981 1251 }
1252 }
1253
5eaef520 1254 /*
1255 * If this is an update_host query, we're done.
1256 */
1257 if (row == 1)
1258 return MR_SUCCESS;
1259
1260 /*
1261 * For an add_host query, allocate and fill in a new machine id,
1262 * and then insert the creator id.
1263 */
1264 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
1265 return mr_errcode;
1266
1267 sprintf(argv[q->argc + q->vcnt + 1], "%d", cl->client_id);
1268 return MR_SUCCESS;
7f426981 1269}
1270
1271
1272/* setup_ahal():
1273 */
1274
5eaef520 1275int setup_ahal(struct query *q, char **argv, client *cl)
7f426981 1276{
5eaef520 1277 EXEC SQL BEGIN DECLARE SECTION;
1278 char *name;
1279 int cnt;
1280 EXEC SQL END DECLARE SECTION;
1281 char *p;
1282
84f3d463 1283 name = argv[0];
1284 if (!hostname_check(argv[0]))
5eaef520 1285 return MR_BAD_CHAR;
7f426981 1286
5eaef520 1287 EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine WHERE
ad06a10e 1288 name = UPPER(:name);
5eaef520 1289 if (dbms_errno)
1290 return mr_errcode;
1291 if (cnt > 0)
1292 return MR_EXISTS;
7f426981 1293
5eaef520 1294 return MR_SUCCESS;
7f426981 1295}
84f3d463 1296
2884200f 1297/* setup_uhha(): Check characters in hwaddr, and make sure it's not
1298 * a duplicate.
1299 */
1300int setup_uhha(struct query *q, char **argv, client *cl)
1301{
1302 EXEC SQL BEGIN DECLARE SECTION;
1303 char *hwaddr = argv[1];
1304 int count;
1305 EXEC SQL END DECLARE SECTION;
1306 char *p;
1307
1308 if (*hwaddr && strcasecmp(hwaddr, "unknown"))
1309 {
1310 for (p = hwaddr; *p; p++)
1311 {
1312 if (isupper(*p))
1313 *p = tolower(*p);
1314 if (!isxdigit(*p))
1315 return MR_BAD_CHAR;
1316 }
1317 if (p != hwaddr + 12)
1318 return MR_ADDRESS;
1319
1320 EXEC SQL SELECT COUNT(hwaddr) INTO :count
1321 FROM machine WHERE hwaddr = :hwaddr;
1322 if (count)
1323 return MR_NOT_UNIQUE;
1324 }
1325
1326 return MR_SUCCESS;
1327}
1328
1329/* setup_aprn(): Make sure name/duplexname don't conflict with
1330 * anything. If [ANY] was specified for the spooling host, pick the
1331 * least loaded print server that serves this kind of printer.
1332 */
1333int setup_aprn(struct query *q, char **argv, client *cl)
1334{
1a9a0a59 1335 int best = -1, row;
2884200f 1336 char *p;
1337 EXEC SQL BEGIN DECLARE SECTION;
1338 int mid, usage, count;
1a9a0a59 1339 char types[STRINGS_STRING_SIZE], *hwaddr, *name, *duplexname, *oldname;
2884200f 1340 EXEC SQL END DECLARE SECTION;
1341
1a9a0a59 1342 /* Check for aprn or uprn. */
b9f9ab1c 1343 if (q->type == MR_Q_APPEND)
1a9a0a59 1344 row = 0;
1345 else
1346 row = 1;
1347
1348 name = argv[PRN_NAME + row];
1349 duplexname = argv[PRN_DUPLEXNAME + row];
1350 oldname = argv[0];
1351
2884200f 1352 if (!*name)
1353 return MR_BAD_CHAR;
1354 else
1355 {
b9f9ab1c 1356 if (q->type == MR_Q_APPEND)
1a9a0a59 1357 {
1358 EXEC SQL SELECT COUNT(name) INTO :count FROM printers
1359 WHERE name = :name OR duplexname = :name;
1360 }
1361 else
1362 {
1363 EXEC SQL SELECT COUNT(name) INTO :count FROM printers
1364 WHERE ( name = :name OR duplexname = :name )
1365 AND name != :oldname;
1366 }
2884200f 1367 if (dbms_errno)
1368 return mr_errcode;
1369 if (count)
1370 return MR_NOT_UNIQUE;
1371 }
1372
1a9a0a59 1373 if (*duplexname)
2884200f 1374 {
b9f9ab1c 1375 if (q->type == MR_Q_APPEND)
1a9a0a59 1376 {
1377 EXEC SQL SELECT COUNT(name) INTO :count FROM printers
1378 WHERE name = :duplexname OR duplexname = :duplexname;
1379 }
1380 else
1381 {
1382 EXEC SQL SELECT COUNT(name) INTO :count FROM printers
1383 WHERE ( name = :duplexname OR duplexname = :duplexname )
1384 AND name != :oldname;
1385 }
1386
2884200f 1387 if (dbms_errno)
1388 return mr_errcode;
1389 if (count)
1390 return MR_NOT_UNIQUE;
1391 }
1392
1a9a0a59 1393 if (!strcmp(name, duplexname))
1394 return MR_NOT_UNIQUE;
1395
1396 mid = *(int *)argv[PRN_RM + row];
1397 if (mid == -1)
2884200f 1398 {
1399 EXEC SQL DECLARE csr_rm CURSOR FOR
1a9a0a59 1400 SELECT ps.mach_id, s.string FROM printservers ps, strings s
b3e26217 1401 WHERE ps.mach_id IN
1402 ( SELECT mach_id FROM serverhosts WHERE service = 'PRINT'
1403 AND enable = 1 )
1404 AND ps.printer_types = s.string_id;
2884200f 1405 if (dbms_errno)
1406 return mr_errcode;
1407 EXEC SQL OPEN csr_rm;
1408 if (dbms_errno)
1409 return mr_errcode;
1410
1411 while (1)
1412 {
1a9a0a59 1413 EXEC SQL FETCH csr_rm INTO :mid, :types;
2884200f 1414 if (sqlca.sqlcode)
1415 break;
1416
2884200f 1417 for (p = strtok(types, ", "); p; p = strtok(NULL, ", "))
1418 {
1a9a0a59 1419 if (!strcasecmp(argv[PRN_TYPE + row], p))
2884200f 1420 {
1a9a0a59 1421 EXEC SQL SELECT COUNT(name) INTO :usage
cc0ea77e 1422 FROM printers WHERE rm = :mid;
1a9a0a59 1423
119230bb 1424 if (best < 0 || usage < best)
1a9a0a59 1425 {
1426 best = usage;
1427 *(int *)argv[PRN_RM + row] = mid;
1428 break;
1429 }
2884200f 1430 }
1431 }
1432 }
1433 EXEC SQL CLOSE csr_rm;
1434 if (dbms_errno)
1435 return mr_errcode;
1436
1437 if (best == -1)
1438 return MR_SERVICE;
1439 }
2681538c 1440 else
1441 {
1442 EXEC SQL SELECT mach_id INTO :mid FROM printservers
1443 WHERE mach_id = :mid;
1444 if (sqlca.sqlcode)
1445 return MR_SERVICE;
1446 }
2884200f 1447
1448 return MR_SUCCESS;
1449}
1450
1a9a0a59 1451int setup_dpsv(struct query *q, char **argv, client *cl)
1452{
1453 int id;
1454 EXEC SQL BEGIN DECLARE SECTION;
1455 int cnt;
1456 EXEC SQL END DECLARE SECTION;
1457
1458 id = *(int *)argv[0];
1459
1460 EXEC SQL SELECT COUNT(rm) INTO :cnt FROM printers
1461 WHERE rm = :id;
1462 if (cnt > 0)
1463 return MR_IN_USE;
1464
1465 return MR_SUCCESS;
1466}
1467
2fb668b0 1468int setup_dcon(struct query *q, char *argv[], client *cl)
1469{
1470 EXEC SQL BEGIN DECLARE SECTION;
1471 int id, cnt;
1472 char containername[CONTAINERS_NAME_SIZE];
1473 EXEC SQL END DECLARE SECTION;
1474
1475 id = *(int *)argv[0];
1476 /* check to see if there are machines in this container */
1477 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM mcntmap
1478 WHERE cnt_id = :id;
1479 if (cnt > 0)
1480 return MR_IN_USE;
1481
1482 /* check to see if there are subcontainers in this container */
1483
1484 /* get the container name */
1485
1486 EXEC SQL SELECT name INTO :containername
1487 FROM containers
1488 WHERE cnt_id = :id;
1489
1490 /* trim off the trailing spaces */
1491 strcpy(containername, strtrim(containername));
1492
1493 EXEC SQL SELECT COUNT(cnt_id) INTO :cnt FROM containers
73155abd 1494 WHERE LOWER(name) LIKE LOWER(:containername || '/' || '%');
2fb668b0 1495
1496 if (cnt > 0)
1497 return MR_IN_USE;
1498
1499 if (dbms_errno)
1500 return mr_errcode;
1501 return MR_SUCCESS;
1502}
1503
73155abd 1504int setup_scli(struct query *q, char *argv[], client *cl)
1505{
1506 EXEC SQL BEGIN DECLARE SECTION;
1507 int cnt_id, list_id;
1508 EXEC SQL END DECLARE SECTION;
1509
1510 cnt_id = *(int *)argv[0];
1511 /* Check if someone has already set the list for this container */
1512 EXEC SQL SELECT list_id INTO :list_id FROM containers
1513 WHERE cnt_id = :cnt_id;
1514 if (list_id != 0)
1515 return MR_EXISTS;
1516
1517 if (dbms_errno)
1518 return mr_errcode;
1519
1520 return MR_SUCCESS;
1521}
1522
84f3d463 1523/* hostname_check()
9e252e6f 1524 * validate the rfc1035/rfc1123-ness of a hostname
84f3d463 1525 */
1526
1527int hostname_check(char *name)
1528{
1529 char *p;
1530 int count;
1531
9e252e6f 1532 /* Sanity check name: must contain only letters, numerals, and
1533 * hyphen, and not start or end with a hyphen. Also make sure no
16affa56 1534 * label (the thing the .s seperate) is longer than 63 characters,
1535 * or empty.
84f3d463 1536 */
1537
9e252e6f 1538 for (p = name, count = 0; *p; p++)
84f3d463 1539 {
1540 count++;
1541 if ((!isalnum(*p) && *p != '-' && *p != '.') ||
1542 (*p == '-' && p[1] == '.'))
1543 return 0;
1544 if (*p == '.')
16affa56 1545 {
1546 if (count == 1)
1547 return 0;
1548 count = 0;
1549 }
84f3d463 1550 if (count == 64)
1551 return 0;
1552 }
1553 if (*(p - 1) == '-')
1554 return 0;
1555 return 1;
1556}
9e252e6f 1557
17f585b5 1558int hostinfo_check(char *info, int num)
9e252e6f 1559{
1560 char *p;
1561
1562 if (!*info)
1563 return 1;
1564
17f585b5 1565 /* Sanity check host hostinfo: must start with a letter (or number
1566 * if num is true), contain only letters, numerals, and hyphen, and
1567 * not end with a hyphen.
9e252e6f 1568 */
1569
17f585b5 1570 if (!isalpha(*info) && (!num || !isdigit(*info)))
9e252e6f 1571 return 0;
1572 for (p = info; *p; p++)
1573 {
1574 if ((!isalnum(*p) && *p != '-' && *p != '.') ||
1575 (*p == '-' && p[1] == '.'))
1576 return 0;
1577 }
1578 if (!isalnum(*(p - 1)))
1579 return 1;
1580}
73155abd 1581
9910965a 1582int setup_aali(struct query *q, char *argv[], client *cl)
1583{
1584 EXEC SQL BEGIN DECLARE SECTION;
1585 int cnt;
1586 char *name, *type, *trans;
1587 EXEC SQL END DECLARE SECTION;
1588 name = argv[0];
1589 type = argv[1];
1590 trans = argv[2];
1591
1592 if (strcmp(strtrim(type), "FILESYS"))
1593 return MR_SUCCESS;
1594
1595 EXEC SQL SELECT count(label) INTO :cnt FROM filesys WHERE
bd069390 1596 label = :name;
9910965a 1597 if (cnt > 0)
1598 return MR_EXISTS;
1599
1600 return MR_SUCCESS;
1601}
1602
73155abd 1603int setup_acon(struct query *q, char *argv[], client *cl)
1604{
1605 EXEC SQL BEGIN DECLARE SECTION;
1606 char containername[CONTAINERS_NAME_SIZE];
1607 EXEC SQL END DECLARE SECTION;
1608
1609 char* ptr;
1610
1611 memset(containername, 0, sizeof(containername));
1612 strcpy(containername, argv[0]);
1613 ptr = strrchr(containername, '/');
1614 /* sub container, check for parents */
1615 if (ptr)
1616 {
1617 *ptr = '\0';
1618 EXEC SQL SELECT * FROM containers
1619 WHERE lower(name) = lower(:containername);
1620 if (sqlca.sqlerrd[2] != 1)
1621 return MR_CONTAINER_NO_PARENT;
1622 }
1623
1624 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
1625 return mr_errcode;
1626
1627 return MR_SUCCESS;
1628}
8e3761a2 1629
1630int check_mailman_listname(char *name, const char *suffix)
1631{
1632 char *p;
1633 EXEC SQL BEGIN DECLARE SECTION;
1634 int i, cnt;
1635 EXEC SQL END DECLARE SECTION;
1636
1637 p = strstr(name, suffix);
1638 if (p)
1639 {
1640 if (strlen(name) == (p - name + strlen(suffix)))
1641 {
1642 /* list is of the form "name-suffix" */
1643 i = (p - name);
1644 EXEC SQL SELECT COUNT(name) INTO :cnt FROM list
1645 WHERE name = SUBSTR(:name, 1, :i) AND mailman = 1;
1646 if (cnt > 0)
1647 return MR_EXISTS;
1648 }
1649 }
1650
1651 return MR_SUCCESS;
1652}
This page took 0.355 seconds and 5 git commands to generate.