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