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