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