]> andersk Git - moira.git/blame_incremental - server/qsetup.pc
oops, wrong argument.
[moira.git] / server / qsetup.pc
... / ...
CommitLineData
1/* $Id$
2 *
3 * Query setup routines
4 *
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>.
8 */
9
10#include <mit-copyright.h>
11#include "mr_server.h"
12#include "query.h"
13#include "qrtn.h"
14
15#include <arpa/inet.h>
16#include <netinet/in.h>
17
18#include <ctype.h>
19#include <stdlib.h>
20#include <string.h>
21
22EXEC SQL INCLUDE sqlca;
23
24RCSID("$Header$");
25
26extern char *whoami;
27extern int dbms_errno, mr_errcode;
28
29EXEC SQL BEGIN DECLARE SECTION;
30extern char stmt_buf[];
31EXEC SQL END DECLARE SECTION;
32
33EXEC SQL WHENEVER SQLERROR DO dbmserr();
34
35int hostname_check(char *name);
36int hostinfo_check(char *name, int num);
37int prefetch_value(struct query *q, char **argv, client *cl);
38int check_nfs(int mach_idx, char *name, char *access);
39int check_mailman_listname(char *name, const char *suffix);
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
54int setup_ausr(struct query *q, char *argv[], client *cl)
55{
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;
65
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 }
78
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>
86 * [DFS] - Magic token for DFS home directory
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]")) &&
93 (strcasecmp(argv[row + 12], "[DFS]")) &&
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]")) &&
100 (strcasecmp(argv[row + 13], "[DFS]")) &&
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
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);
114 }
115
116 if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[row]) == -1)
117 sprintf(argv[0], "#%s", argv[row]);
118
119 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
120 return mr_errcode;
121
122 /* If this is an MR_Q_UPDATE query, we're done. */
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);
128 return MR_SUCCESS;
129}
130
131
132/* setup_dusr - verify that the user is no longer being referenced
133 * and may safely be deleted.
134 */
135
136int setup_dusr(struct query *q, char *argv[], client *cl)
137{
138 EXEC SQL BEGIN DECLARE SECTION;
139 int flag, id, cnt;
140 char resv[USERS_RESERVATIONS_SIZE];
141 EXEC SQL END DECLARE SECTION;
142
143 id = *(int *)argv[0];
144
145 /* For now, only allow users to be deleted if their status is
146 * one of 0, 4, or 8 (the various registerable statuses)
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;
151 if ((flag != 0 && flag != 4 && flag != 8) || *resv)
152 return MR_IN_USE;
153
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;
176
177 EXEC SQL DELETE FROM quota WHERE entity_id = :id AND type = 'USER';
178 EXEC SQL DELETE FROM krbmap WHERE users_id = :id;
179 return MR_SUCCESS;
180}
181
182
183/* setup_dpob: Take care of keeping track of the post office usage.
184 */
185int setup_dpob(struct query *q, char *argv[], client *cl)
186{
187 EXEC SQL BEGIN DECLARE SECTION;
188 int id, user;
189 char type[USERS_POTYPE_SIZE];
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;
201}
202
203
204/* setup_dmac - verify that the machine is no longer being referenced
205 * and may safely be deleted.
206 */
207
208int setup_dmac(struct query *q, char *argv[], client *cl)
209{
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;
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;
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;
240 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM printers
241 WHERE mach_id = :id;
242 if (cnt > 0)
243 return MR_IN_USE;
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;
250 if (cnt > 0)
251 return MR_IN_USE;
252 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM printservers
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;
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;
264
265 EXEC SQL DELETE FROM mcmap WHERE mach_id = :id;
266 if (dbms_errno)
267 return mr_errcode;
268
269 EXEC SQL DELETE FROM mcntmap WHERE mach_id = :id;
270 if (dbms_errno)
271 return mr_errcode;
272 return MR_SUCCESS;
273}
274
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. */
286 if (q->type == MR_Q_APPEND)
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 */
299 if (status == SNET_STATUS_PRIVATE_10MBPS ||
300 status == SNET_STATUS_PRIVATE_100MBPS ||
301 status == SNET_STATUS_PRIVATE_1000MBPS)
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}
324
325/* setup_dsnt - verify that the subnet is no longer being referenced
326 * and may safely be deleted.
327 */
328
329int setup_dsnt(struct query *q, char *argv[], client *cl)
330{
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;
341}
342
343
344/* setup_dclu - verify that the cluster is no longer being referenced
345 * and may safely be deleted.
346 */
347
348int setup_dclu(struct query *q, char *argv[], client *cl)
349{
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;
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 :.
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.
378 */
379
380static int badlistchars[] = {
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 - ^_ */
383 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, /* SPACE - / */
384 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 0 - ? */
385 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
386 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* P - _ */
387 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
388 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
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,
397};
398
399static const char *mailman_suffixes[] = { "-admin", "-owner", "-request",
400 "-bounces", "-confirm", "-join",
401 "-leave", "-subscribe",
402 "-unsubscribe", NULL };
403
404int setup_alis(struct query *q, char *argv[], client *cl)
405{
406 EXEC SQL BEGIN DECLARE SECTION;
407 int ngid, cnt, mailman, mailman_id, lid;
408 char *name, *desc;
409 EXEC SQL END DECLARE SECTION;
410 unsigned char *p;
411 int idx, err, best = -1, usage, i;
412
413 if (!strcmp(q->shortname, "alis"))
414 idx = 0;
415 else if (!strcmp(q->shortname, "ulis"))
416 idx = 1;
417 name = argv[idx];
418
419 if (q->version == 2)
420 desc = argv[9 + idx];
421 else if (q->version == 3)
422 desc = argv[10 + idx];
423 else if (q->version == 4)
424 desc = argv[12 + idx];
425 else if (q->version >= 10)
426 desc = argv[14 + idx];
427
428 if (idx == 1)
429 {
430 lid = *(int *)argv[0];
431
432 if (acl_access_check(lid, cl))
433 return MR_PERM;
434 }
435
436 for (p = (unsigned char *) name; *p; p++)
437 {
438 if (badlistchars[*p])
439 return MR_BAD_CHAR;
440 }
441
442 for (p = (unsigned char *) desc; *p; p++)
443 {
444 if (*p == '\n')
445 return MR_BAD_CHAR;
446 }
447
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
451 WHERE LOWER(name) = :name AND name != :name;
452 if (cnt)
453 return MR_EXISTS;
454
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);
466 }
467 else
468 strcpy(argv[6 + idx], "-1");
469 }
470
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 */
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 }
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 }
532 else
533 {
534 /* Client too old to know about the mailman code.
535 * Use existing value of mailman boolean in the table.
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.
539 */
540 if (idx == 1)
541 {
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 }
551 }
552 }
553
554 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
555 return mr_errcode;
556
557 return MR_SUCCESS;
558}
559
560
561/* setup_dlis - verify that the list is no longer being referenced
562 * and may safely be deleted.
563 */
564
565int setup_dlis(struct query *q, char *argv[], client *cl)
566{
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
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
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
626 OR z.iui_type = 'LIST' AND z.iui_id = :id
627 OR z.owner_type = 'LIST' and z.owner_id = :id;
628 if (cnt > 0)
629 return MR_IN_USE;
630
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
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
652 return MR_SUCCESS;
653}
654
655
656/* setup_dsin - verify that the service is no longer being referenced
657 * and may safely be deleted.
658 */
659
660int setup_dsin(struct query *q, char *argv[], client *cl)
661{
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;
681}
682
683
684/* setup_dshi - verify that the service-host is no longer being referenced
685 * and may safely be deleted.
686 */
687
688int setup_dshi(struct query *q, char *argv[], client *cl)
689{
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;
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
716 ** argv[5] - rwaccess
717 **
718 ** Description:
719 ** - for type = RVD:
720 ** * allow anything
721 ** - for type = NFS/IMAP:
722 ** * extract directory prefix from name
723 ** * verify mach_id/dir in nfsphys
724 ** * verify rwaccess in {r, w, R, W}
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
739int setup_afil(struct query *q, char *argv[], client *cl)
740{
741 char *type, *name;
742 int mach_id;
743 EXEC SQL BEGIN DECLARE SECTION;
744 int ok;
745 char ftype[FILESYS_TYPE_SIZE + 10], *rwaccess;
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
765 if (!strcmp(type, "NFS") || !strcmp(type, "IMAP"))
766 return check_nfs(mach_id, name, rwaccess);
767
768 return MR_SUCCESS;
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
777int setup_ufil(struct query *q, char *argv[], client *cl)
778{
779 int mach_id, status;
780 char *type, *name;
781 EXEC SQL BEGIN DECLARE SECTION;
782 int fid, total, who, ok;
783 char *entity, ftype[FILESYS_TYPE_SIZE + 10], *access;
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
809 if (!strcmp(type, "NFS") || !strcmp(type, "IMAP"))
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;
835 }
836 }
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;
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
853int check_nfs(int mach_id, char *name, char *access)
854{
855 EXEC SQL BEGIN DECLARE SECTION;
856 char dir[NFSPHYS_DIR_SIZE];
857 int mid = mach_id;
858 EXEC SQL END DECLARE SECTION;
859 int status;
860 char *cp1;
861 char *cp2;
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)
883 break;
884 cp2++;
885 }
886 if (!*cp2)
887 {
888 status = MR_SUCCESS;
889 break;
890 }
891 }
892 EXEC SQL CLOSE csr101;
893 if (dbms_errno)
894 return mr_errcode;
895 return status;
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
903int setup_dfil(struct query *q, char **argv, client *cl)
904{
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;
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
937int setup_dnfp(struct query *q, char **argv, client *cl)
938{
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;
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
963int setup_dqot(struct query *q, char **argv, client *cl)
964{
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];
980 }
981
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;
988
989 if (dbms_errno)
990 return mr_errcode;
991 return MR_SUCCESS;
992}
993
994
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 *
1000 * It is called from the query table as (*v->pre_rtn)(q, Argv, cl) or
1001 * from within a setup_...() routine with the appropriate arguments.
1002 *
1003 * Correct functioning of this routine may depend on the assumption
1004 * that this query is an MR_Q_APPEND.
1005 */
1006
1007int prefetch_value(struct query *q, char **argv, client *cl)
1008{
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
1030 argc = q->argc + q->vcnt; /* end of Argv for MR_Q_APPENDs */
1031 sprintf(argv[argc], "%d", value);
1032
1033 return MR_SUCCESS;
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 */
1045int prefetch_filesys(struct query *q, char **argv, client *cl)
1046{
1047 EXEC SQL BEGIN DECLARE SECTION;
1048 int fid, phid;
1049 EXEC SQL END DECLARE SECTION;
1050 int argc;
1051
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;
1056
1057 argc = q->argc + q->vcnt;
1058 sprintf(argv[argc++], "%d", phid);
1059 sprintf(argv[argc], "%d", fid);
1060
1061 return MR_SUCCESS;
1062}
1063
1064
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
1077/* setup_ahst():
1078 */
1079
1080int setup_ahst(struct query *q, char **argv, client *cl)
1081{
1082 EXEC SQL BEGIN DECLARE SECTION;
1083 char *name, oldname[MACHINE_NAME_SIZE], vendor[MACHINE_VENDOR_SIZE];
1084 char model[MACHINE_MODEL_SIZE], os[MACHINE_OS_SIZE];
1085 int value, id, ssaddr, smask, shigh, slow, cnt;
1086 unsigned int saddr, mask, high, low;
1087 EXEC SQL END DECLARE SECTION;
1088 int row, idx;
1089 struct in_addr addr;
1090
1091 id = *(int *)argv[0];
1092
1093 if (!strcmp(q->shortname, "uhst"))
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 }
1100 else
1101 row = 0;
1102
1103 if (q->version < 6)
1104 idx = 0;
1105 else if (q->version >= 6 && q->version < 8)
1106 idx = 1;
1107 else
1108 idx = 2;
1109
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)) &&
1115 !hostinfo_check(argv[row + 1], 0))
1116 return MR_BAD_CHAR;
1117 if ((row == 0 || strcasecmp(argv[3], model)) &&
1118 !hostinfo_check(argv[row + 2], 1))
1119 return MR_BAD_CHAR;
1120 if ((row == 0 || strcasecmp(argv[4], os)) &&
1121 !hostinfo_check(argv[row + 3], 0))
1122 return MR_BAD_CHAR;
1123
1124 /* check for duplicate name */
1125 name = argv[row];
1126 EXEC SQL SELECT count(mach_id) INTO :cnt FROM hostalias
1127 WHERE name = UPPER(:name);
1128 if (dbms_errno)
1129 return mr_errcode;
1130 if (cnt != 0)
1131 return MR_EXISTS;
1132
1133 /* check address */
1134 if (!strcmp(argv[9 + row + idx], "unassigned"))
1135 value = -1;
1136 else if (!strcmp(argv[9 + row + idx], "unique"))
1137 {
1138 if (*(int *)argv[8 + row + idx] == 0)
1139 value = -1;
1140 else
1141 value = -2;
1142 }
1143 else
1144 {
1145 value = ntohl(inet_addr(argv[9 + row + idx]));
1146 if (value == -1)
1147 return MR_ADDRESS;
1148 }
1149 if (value == 0)
1150 return MR_ADDRESS;
1151 if (value != -1)
1152 {
1153 /*
1154 * an address or unique was specified.
1155 */
1156 id = *(int *)argv[8 + row + idx];
1157 EXEC SQL SELECT saddr, mask, high, low INTO :ssaddr, :smask,
1158 :shigh, :slow FROM subnet WHERE snet_id = :id;
1159 if (dbms_errno)
1160 return mr_errcode;
1161 saddr = (unsigned) ssaddr;
1162 mask = (unsigned) smask;
1163 high = (unsigned) shigh;
1164 low = (unsigned) slow;
1165 if (value != -2)
1166 {
1167 /*
1168 * someone specified an IP address for the host record
1169 */
1170 if ((value & mask) != saddr || value < low || value > high)
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 */
1180 addr.s_addr = inet_addr(argv[9 + row + idx]);
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 */
1192 if (row == 0 || (row == 1 && cnt > 1))
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;
1200 }
1201 }
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);
1215 name = inet_ntoa(addr);
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;
1222 }
1223 if (cnt != 0)
1224 return MR_NO_ID;
1225 else
1226 value = htonl(id);
1227 }
1228 /*
1229 * we have an address in value. Convert it to a string and store it.
1230 */
1231 addr.s_addr = htonl(value);
1232 strcpy(argv[9 + row + idx], inet_ntoa(addr));
1233 }
1234 else
1235 strcpy(argv[9 + row + idx], "unassigned");
1236
1237 /* status checking */
1238 value = atoi(argv[7 + row + idx]);
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;
1251 }
1252 }
1253
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;
1269}
1270
1271
1272/* setup_ahal():
1273 */
1274
1275int setup_ahal(struct query *q, char **argv, client *cl)
1276{
1277 EXEC SQL BEGIN DECLARE SECTION;
1278 char *name;
1279 int cnt;
1280 EXEC SQL END DECLARE SECTION;
1281 char *p;
1282
1283 name = argv[0];
1284 if (!hostname_check(argv[0]))
1285 return MR_BAD_CHAR;
1286
1287 EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine WHERE
1288 name = UPPER(:name);
1289 if (dbms_errno)
1290 return mr_errcode;
1291 if (cnt > 0)
1292 return MR_EXISTS;
1293
1294 return MR_SUCCESS;
1295}
1296
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{
1335 int best = -1, row;
1336 char *p;
1337 EXEC SQL BEGIN DECLARE SECTION;
1338 int mid, usage, count;
1339 char types[STRINGS_STRING_SIZE], *hwaddr, *name, *duplexname, *oldname;
1340 EXEC SQL END DECLARE SECTION;
1341
1342 /* Check for aprn or uprn. */
1343 if (q->type == MR_Q_APPEND)
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
1352 if (!*name)
1353 return MR_BAD_CHAR;
1354 else
1355 {
1356 if (q->type == MR_Q_APPEND)
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 }
1367 if (dbms_errno)
1368 return mr_errcode;
1369 if (count)
1370 return MR_NOT_UNIQUE;
1371 }
1372
1373 if (*duplexname)
1374 {
1375 if (q->type == MR_Q_APPEND)
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
1387 if (dbms_errno)
1388 return mr_errcode;
1389 if (count)
1390 return MR_NOT_UNIQUE;
1391 }
1392
1393 if (!strcmp(name, duplexname))
1394 return MR_NOT_UNIQUE;
1395
1396 mid = *(int *)argv[PRN_RM + row];
1397 if (mid == -1)
1398 {
1399 EXEC SQL DECLARE csr_rm CURSOR FOR
1400 SELECT ps.mach_id, s.string FROM printservers ps, strings s
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;
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 {
1413 EXEC SQL FETCH csr_rm INTO :mid, :types;
1414 if (sqlca.sqlcode)
1415 break;
1416
1417 for (p = strtok(types, ", "); p; p = strtok(NULL, ", "))
1418 {
1419 if (!strcasecmp(argv[PRN_TYPE + row], p))
1420 {
1421 EXEC SQL SELECT COUNT(name) INTO :usage
1422 FROM printers WHERE rm = :mid;
1423
1424 if (best < 0 || usage < best)
1425 {
1426 best = usage;
1427 *(int *)argv[PRN_RM + row] = mid;
1428 break;
1429 }
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 }
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 }
1447
1448 return MR_SUCCESS;
1449}
1450
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
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
1494 WHERE LOWER(name) LIKE LOWER(:containername || '/' || '%');
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
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
1523/* hostname_check()
1524 * validate the rfc1035/rfc1123-ness of a hostname
1525 */
1526
1527int hostname_check(char *name)
1528{
1529 char *p;
1530 int count;
1531
1532 /* Sanity check name: must contain only letters, numerals, and
1533 * hyphen, and not start or end with a hyphen. Also make sure no
1534 * label (the thing the .s seperate) is longer than 63 characters,
1535 * or empty.
1536 */
1537
1538 for (p = name, count = 0; *p; p++)
1539 {
1540 count++;
1541 if ((!isalnum(*p) && *p != '-' && *p != '.') ||
1542 (*p == '-' && p[1] == '.'))
1543 return 0;
1544 if (*p == '.')
1545 {
1546 if (count == 1)
1547 return 0;
1548 count = 0;
1549 }
1550 if (count == 64)
1551 return 0;
1552 }
1553 if (*(p - 1) == '-')
1554 return 0;
1555 return 1;
1556}
1557
1558int hostinfo_check(char *info, int num)
1559{
1560 char *p;
1561
1562 if (!*info)
1563 return 1;
1564
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.
1568 */
1569
1570 if (!isalpha(*info) && (!num || !isdigit(*info)))
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}
1581
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
1596 label = :name;
1597 if (cnt > 0)
1598 return MR_EXISTS;
1599
1600 return MR_SUCCESS;
1601}
1602
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}
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.049478 seconds and 5 git commands to generate.