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