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