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