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