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