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