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