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