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