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