]> andersk Git - moira.git/blame - server/qsetup.pc
replace printcap and palladium query indexes with printer query indexes
[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
65 if (strlen(argv[row + 2]) + strlen(argv[row + 3]) +
66 strlen(argv[row + 4]) + 2 > USERS_FULLNAME_SIZE)
67 return MR_ARG_TOO_LONG;
68
5eaef520 69 if (!strcmp(argv[row], UNIQUE_UID) || atoi(argv[row]) == -1)
70 {
71 if ((err = set_next_object_id("unix_uid", USERS_TABLE, 1)))
72 return err;
73 EXEC SQL SELECT value INTO :nuid FROM numvalues WHERE name = 'unix_uid';
74 if (sqlca.sqlerrd[2] != 1)
75 return MR_INTERNAL;
76 sprintf(argv[row], "%d", nuid);
73cf66ba 77 }
78
5eaef520 79 if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[row]) == -1)
80 sprintf(argv[0], "#%s", argv[row]);
73cf66ba 81
5eaef520 82 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
83 return mr_errcode;
73cf66ba 84
5eaef520 85 return MR_SUCCESS;
73cf66ba 86}
87
88
89/* setup_dusr - verify that the user is no longer being referenced
90 * and may safely be deleted.
91 */
92
7ac48069 93int setup_dusr(struct query *q, char *argv[], client *cl)
73cf66ba 94{
5eaef520 95 EXEC SQL BEGIN DECLARE SECTION;
96 int flag, id, cnt;
97 EXEC SQL END DECLARE SECTION;
98
99 id = *(int *)argv[0];
100
101 /* For now, only allow users to be deleted if their status is 0 */
102 EXEC SQL SELECT status INTO :flag FROM users WHERE users_id = :id;
103 if (flag != 0 && flag != 4)
104 return MR_IN_USE;
105
106 EXEC SQL DELETE FROM quota WHERE entity_id = :id AND type = 'USER';
107 EXEC SQL DELETE FROM krbmap WHERE users_id = :id;
108 EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
109 WHERE member_id = :id AND member_type = 'USER';
110 if (cnt > 0)
111 return MR_IN_USE;
112 EXEC SQL SELECT COUNT(label) INTO :cnt FROM filesys
113 WHERE owner = :id;
114 if (cnt > 0)
115 return MR_IN_USE;
116 EXEC SQL SELECT COUNT(name) INTO :cnt FROM list
117 WHERE acl_id = :id AND acl_type = 'USER';
118 if (cnt > 0)
119 return MR_IN_USE;
120 EXEC SQL SELECT COUNT(name) INTO :cnt FROM servers
121 WHERE acl_id = :id AND acl_type = 'USER';
122 if (cnt > 0)
123 return MR_IN_USE;
124 EXEC SQL SELECT COUNT(acl_id) INTO :cnt FROM hostaccess
125 WHERE acl_id = :id AND acl_type = 'USER';
126 if (cnt > 0)
127 return MR_IN_USE;
128 if (dbms_errno)
129 return mr_errcode;
130 return MR_SUCCESS;
73cf66ba 131}
132
133
134/* setup_spop: verify that there is already a valid POP machine_id in the
135 * pop_id field. Also take care of keeping track of the post office usage.
136 */
7ac48069 137int setup_spop(struct query *q, char *argv[], client *cl)
73cf66ba 138{
5eaef520 139 EXEC SQL BEGIN DECLARE SECTION;
140 int id, mid;
e688520a 141 char type[USERS_POTYPE_SIZE];
5eaef520 142 EXEC SQL END DECLARE SECTION;
143
144 id = *(int *)argv[0];
145 EXEC SQL SELECT potype, pop_id INTO :type, :mid FROM users
146 WHERE users_id = :id;
7ac48069 147 if (sqlca.sqlerrd[2] == 0)
5eaef520 148 return MR_MACHINE;
149 EXEC SQL SELECT mach_id INTO :mid FROM machine
150 WHERE mach_id = :mid;
7ac48069 151 if (sqlca.sqlerrd[2] == 0)
5eaef520 152 return MR_MACHINE;
153 if (strcmp(strtrim(type), "POP"))
154 set_pop_usage(mid, 1);
155 return MR_SUCCESS;
73cf66ba 156}
157
158
159/* setup_dpob: Take care of keeping track of the post office usage.
160 */
7ac48069 161int setup_dpob(struct query *q, char *argv[], client *cl)
73cf66ba 162{
5eaef520 163 EXEC SQL BEGIN DECLARE SECTION;
164 int id, user;
e688520a 165 char type[USERS_POTYPE_SIZE];
5eaef520 166 EXEC SQL END DECLARE SECTION;
167
168 user = *(int *)argv[0];
169 EXEC SQL SELECT potype, pop_id INTO :type, :id FROM users
170 WHERE users_id = :user;
171 if (dbms_errno)
172 return mr_errcode;
173
174 if (!strcmp(strtrim(type), "POP"))
175 set_pop_usage(id, -1);
176 return MR_SUCCESS;
73cf66ba 177}
178
179
180/* setup_dmac - verify that the machine is no longer being referenced
181 * and may safely be deleted.
182 */
183
7ac48069 184int setup_dmac(struct query *q, char *argv[], client *cl)
73cf66ba 185{
5eaef520 186 EXEC SQL BEGIN DECLARE SECTION;
187 int flag, id, cnt;
188 EXEC SQL END DECLARE SECTION;
189
190 id = *(int *)argv[0];
191
192 EXEC SQL SELECT status INTO :flag FROM machine
193 WHERE mach_id = :id;
194 if (flag != 3)
195 return MR_IN_USE;
196 EXEC SQL SELECT COUNT(login) INTO :cnt FROM users
197 WHERE potype = 'POP' AND pop_id = :id;
198 if (cnt > 0)
199 return MR_IN_USE;
200 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM serverhosts
201 WHERE mach_id = :id;
202 if (cnt > 0)
203 return MR_IN_USE;
204 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM nfsphys
205 WHERE mach_id = :id;
206 if (cnt > 0)
207 return MR_IN_USE;
208 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM hostaccess
209 WHERE mach_id = :id;
210 if (cnt > 0)
211 return MR_IN_USE;
212 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM printcap
213 WHERE mach_id = :id;
214 if (cnt > 0)
215 return MR_IN_USE;
216 EXEC SQL SELECT COUNT(quotaserver) INTO :cnt FROM printcap
217 WHERE quotaserver = :id;
218 if (cnt > 0)
219 return MR_IN_USE;
220 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM palladium
221 WHERE mach_id = :id;
222 if (cnt > 0)
223 return MR_IN_USE;
224 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM hostalias
225 WHERE mach_id = :id;
226 if (cnt > 0)
227 return MR_IN_USE;
228
229 EXEC SQL DELETE FROM mcmap WHERE mach_id = :id;
230 if (dbms_errno)
231 return mr_errcode;
232 return MR_SUCCESS;
73cf66ba 233}
234
235
236/* setup_dsnt - verify that the subnet is no longer being referenced
237 * and may safely be deleted.
238 */
239
7ac48069 240int setup_dsnt(struct query *q, char *argv[], client *cl)
73cf66ba 241{
5eaef520 242 EXEC SQL BEGIN DECLARE SECTION;
243 int id, cnt = 0;
244 EXEC SQL END DECLARE SECTION;
245
246 id = *(int *)argv[0];
247 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM machine
248 WHERE snet_id = :id;
249 if (cnt > 0)
250 return MR_IN_USE;
251 return MR_SUCCESS;
73cf66ba 252}
253
254
255/* setup_dclu - verify that the cluster is no longer being referenced
256 * and may safely be deleted.
257 */
258
7ac48069 259int setup_dclu(struct query *q, char *argv[], client *cl)
73cf66ba 260{
5eaef520 261 EXEC SQL BEGIN DECLARE SECTION;
262 int id, cnt;
263 EXEC SQL END DECLARE SECTION;
264
265 id = *(int *)argv[0];
266 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM mcmap
267 WHERE clu_id = :id;
268 if (cnt > 0)
269 return MR_IN_USE;
270 EXEC SQL SELECT COUNT(clu_id) INTO :cnt FROM svc
271 WHERE clu_id = :id;
272 if (cnt > 0)
273 return MR_IN_USE;
274 if (dbms_errno)
275 return mr_errcode;
276 return MR_SUCCESS;
73cf66ba 277}
278
279
280/* setup_alis - if argv[5] is non-zero and argv[6] is UNIQUE_ID, then allocate
281 * a new gid and put it in argv[6]. Otherwise if argv[6] is UNIQUE_ID but
282 * argv[5] is not, then remember that UNIQUE_ID is being stored by putting
283 * a -1 there. Remember that this is also used for ulis, with the indexes
284 * at 6 & 7. Also check that the list name does not contain uppercase
285 * characters, control characters, @, or :.
286 */
287
288static int badlistchars[] = {
5eaef520 289 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
290 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
291 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
292 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, /* 0 - ? */
293 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
294 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, /* P - _ */
295 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
296 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
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,
301 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
302 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
303 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
304 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
73cf66ba 305};
306
5eaef520 307int setup_alis(struct query *q, char *argv[], client *cl)
73cf66ba 308{
5eaef520 309 EXEC SQL BEGIN DECLARE SECTION;
17f585b5 310 int ngid, cnt;
311 char *name;
5eaef520 312 EXEC SQL END DECLARE SECTION;
313 unsigned char *p;
314 int idx, err;
315
316 if (!strcmp(q->shortname, "alis"))
317 idx = 0;
318 else if (!strcmp(q->shortname, "ulis"))
319 idx = 1;
17f585b5 320 name = argv[idx];
5eaef520 321
5a22fdf5 322 if (idx == 1)
323 {
324 EXEC SQL BEGIN DECLARE SECTION;
325 int lid = *(int *)argv[0];
326 EXEC SQL END DECLARE SECTION;
327
328 if (acl_access_check(lid, cl))
329 return MR_PERM;
330 }
331
17f585b5 332 for (p = (unsigned char *) name; *p; p++)
5eaef520 333 {
73cf66ba 334 if (badlistchars[*p])
5eaef520 335 return MR_BAD_CHAR;
336 }
337
17f585b5 338 /* Check that it doesn't conflict with a pre-existing weirdly-cased
339 * name. */
340 EXEC SQL SELECT COUNT(name) INTO :cnt FROM list
20315440 341 WHERE LOWER(name) = :name AND name != :name;
17f585b5 342 if (cnt)
343 return MR_EXISTS;
344
5eaef520 345 if (!strcmp(argv[6 + idx], UNIQUE_GID) || atoi(argv[6 + idx]) == -1)
346 {
347 if (atoi(argv[5 + idx]))
348 {
349 if ((err = set_next_object_id("gid", LIST_TABLE, 1)))
350 return err;
351 EXEC SQL SELECT value INTO :ngid FROM numvalues
352 WHERE name = 'gid';
353 if (dbms_errno)
354 return mr_errcode;
355 sprintf(argv[6 + idx], "%d", ngid);
73cf66ba 356 }
5eaef520 357 else
358 strcpy(argv[6 + idx], "-1");
73cf66ba 359 }
360
5eaef520 361 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
362 return mr_errcode;
73cf66ba 363
5eaef520 364 return MR_SUCCESS;
73cf66ba 365}
366
367
368/* setup_dlis - verify that the list is no longer being referenced
369 * and may safely be deleted.
370 */
371
7ac48069 372int setup_dlis(struct query *q, char *argv[], client *cl)
73cf66ba 373{
5eaef520 374 int id;
375 EXEC SQL BEGIN DECLARE SECTION;
376 int cnt;
377 EXEC SQL END DECLARE SECTION;
378
379 id = *(int *)argv[0];
380
381 EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
382 WHERE member_id = :id AND member_type = 'LIST';
383 if (cnt > 0)
384 return MR_IN_USE;
385
386 EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
387 WHERE member_id = :id AND member_type = 'LIST';
388 if (cnt > 0)
389 return MR_IN_USE;
390
391 EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
392 WHERE list_id = :id;
393 if (cnt > 0)
394 return MR_IN_USE;
395
396 EXEC SQL SELECT COUNT(label) INTO :cnt FROM filesys WHERE owners = :id;
397 if (cnt > 0)
398 return MR_IN_USE;
399
400 EXEC SQL SELECT COUNT(tag) INTO :cnt FROM capacls WHERE list_id = :id;
401 if (cnt > 0)
402 return MR_IN_USE;
403
404 EXEC SQL SELECT COUNT(name) INTO :cnt FROM list
405 WHERE acl_id = :id AND acl_type = 'LIST' AND list_id != :id;
406 if (cnt > 0)
407 return MR_IN_USE;
408
409 EXEC SQL SELECT COUNT(name) INTO :cnt FROM servers
410 WHERE acl_id = :id AND acl_type = 'LIST';
411 if (cnt > 0)
412 return MR_IN_USE;
413
414 EXEC SQL SELECT COUNT(entity_id) INTO :cnt FROM quota
415 WHERE entity_id = :id AND type = 'GROUP';
416 if (cnt > 0)
417 return MR_IN_USE;
418
419 EXEC SQL SELECT COUNT(acl_id) INTO :cnt FROM hostaccess
420 WHERE acl_id = :id AND acl_type = 'LIST';
421 if (cnt > 0)
422 return MR_IN_USE;
423
424 EXEC SQL SELECT COUNT(class) INTO :cnt FROM zephyr z
425 WHERE z.xmt_type = 'LIST' AND z.xmt_id = :id
426 OR z.sub_type = 'LIST' AND z.sub_id = :id
427 OR z.iws_type = 'LIST' AND z.iws_id = :id
428 OR z.iui_type = 'LIST' AND z.iui_id = :id;
429 if (cnt > 0)
430 return MR_IN_USE;
431
432 return MR_SUCCESS;
73cf66ba 433}
434
435
436/* setup_dsin - verify that the service is no longer being referenced
437 * and may safely be deleted.
438 */
439
7ac48069 440int setup_dsin(struct query *q, char *argv[], client *cl)
73cf66ba 441{
5eaef520 442 EXEC SQL BEGIN DECLARE SECTION;
443 int ec, cnt;
444 char *svrname;
445 EXEC SQL END DECLARE SECTION;
446
447 svrname = argv[0];
448 EXEC SQL SELECT COUNT(service) INTO :cnt FROM serverhosts
449 WHERE service = UPPER(:svrname);
450 if (cnt > 0)
451 return MR_IN_USE;
452
453 EXEC SQL SELECT inprogress INTO :ec FROM servers
454 WHERE name = UPPER(:svrname);
455 if (dbms_errno)
456 return mr_errcode;
457 if (ec)
458 return MR_IN_USE;
459
460 return MR_SUCCESS;
73cf66ba 461}
462
463
464/* setup_dshi - verify that the service-host is no longer being referenced
465 * and may safely be deleted.
466 */
467
7ac48069 468int setup_dshi(struct query *q, char *argv[], client *cl)
73cf66ba 469{
5eaef520 470 EXEC SQL BEGIN DECLARE SECTION;
471 int id, ec;
472 char *svrname;
473 EXEC SQL END DECLARE SECTION;
474
475 svrname = argv[0];
476 id = *(int *)argv[1];
477
478 EXEC SQL SELECT inprogress INTO :ec FROM serverhosts
479 WHERE service = UPPER(:svrname) AND mach_id = :id;
480 if (dbms_errno)
481 return mr_errcode;
482 if (ec)
483 return MR_IN_USE;
484
485 return MR_SUCCESS;
73cf66ba 486}
487
488
489/**
490 ** setup_add_filesys - verify existance of referenced file systems
491 **
492 ** Inputs: Add
493 ** argv[1] - type
494 ** argv[2] - mach_id
495 ** argv[3] - name
03c05291 496 ** argv[5] - rwaccess
73cf66ba 497 **
498 ** Description:
499 ** - for type = RVD:
500 ** * allow anything
501 ** - for type = NFS:
502 ** * extract directory prefix from name
503 ** * verify mach_id/dir in nfsphys
03c05291 504 ** * verify rwaccess in {r, w, R, W}
73cf66ba 505 **
506 ** Side effect: sets variable _var_phys_id to the ID of the physical
507 ** filesystem (nfsphys_id for NFS, 0 for RVD)
508 **
509 ** Errors:
510 ** MR_NFS - specified directory not exported
511 ** MR_FILESYS_ACCESS - invalid filesys access
512 **
513 **/
514
515EXEC SQL BEGIN DECLARE SECTION;
516int _var_phys_id;
517EXEC SQL END DECLARE SECTION;
518
5eaef520 519int setup_afil(struct query *q, char *argv[], client *cl)
73cf66ba 520{
5eaef520 521 char *type, *name;
522 int mach_id;
523 EXEC SQL BEGIN DECLARE SECTION;
524 int ok;
e688520a 525 char ftype[FILESYS_TYPE_SIZE + 10], *rwaccess;
5eaef520 526 EXEC SQL END DECLARE SECTION;
527
528 type = argv[1];
529 mach_id = *(int *)argv[2];
530 name = argv[3];
531 rwaccess = argv[5];
532 _var_phys_id = 0;
533
534 sprintf(ftype, "fs_access_%s", type);
535 EXEC SQL SELECT COUNT(trans) INTO :ok FROM alias
536 WHERE name = :ftype AND type = 'TYPE' and trans = :rwaccess;
537 if (dbms_errno)
538 return mr_errcode;
539 if (ok == 0)
540 return MR_FILESYS_ACCESS;
541
542 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
543 return mr_errcode;
544
545 if (!strcmp(type, "NFS"))
546 return check_nfs(mach_id, name, rwaccess);
547
548 return MR_SUCCESS;
73cf66ba 549}
550
551
552/* Verify the arguments, depending on the FStype. Also, if this is an
553 * NFS filesystem, then update any quotas for that filesystem to reflect
554 * the new phys_id.
555 */
556
5eaef520 557int setup_ufil(struct query *q, char *argv[], client *cl)
73cf66ba 558{
5eaef520 559 int mach_id, status;
560 char *type, *name;
561 EXEC SQL BEGIN DECLARE SECTION;
562 int fid, total, who, ok;
e688520a 563 char *entity, ftype[FILESYS_TYPE_SIZE + 10], *access;
5eaef520 564 short int total_null;
565 EXEC SQL END DECLARE SECTION;
566
567 _var_phys_id = 0;
568 type = argv[2];
569 mach_id = *(int *)argv[3];
570 name = argv[4];
571 access = argv[6];
572 fid = *(int *)argv[0];
573 who = cl->client_id;
574 entity = cl->entity;
575
576 sprintf(ftype, "fs_access_%s", type);
577 EXEC SQL SELECT COUNT(trans) INTO :ok FROM alias
578 WHERE name = :ftype AND type = 'TYPE' AND trans = :access;
579 if (dbms_errno)
580 return mr_errcode;
581 if (ok == 0)
582 return MR_FILESYS_ACCESS;
583
584 EXEC SQL SELECT type INTO :ftype FROM filesys
585 WHERE filsys_id = :fid;
586 if (dbms_errno)
587 return mr_errcode;
588
589 if (!strcmp(type, "NFS"))
590 {
591 status = check_nfs(mach_id, name, access);
592 EXEC SQL UPDATE quota SET phys_id = :_var_phys_id
593 WHERE filsys_id = :fid;
594 if (dbms_errno)
595 return mr_errcode;
596 return status;
597 }
598 else if (!strcmp(type, "AFS") && strcmp(strtrim(ftype), "AFS")
599 && strcmp(strtrim(ftype), "ERR"))
600 {
601 total = 0;
602 EXEC SQL DELETE FROM quota
603 WHERE type = 'ANY' AND filsys_id = :fid;
604 EXEC SQL SELECT SUM (quota) INTO :total:total_null FROM quota
605 WHERE filsys_id = :fid AND phys_id != 0;
606 if (dbms_errno)
607 return mr_errcode;
608 if (!total_null && (total != 0))
609 {
610 EXEC SQL INSERT INTO quota (quota, filsys_id, phys_id, entity_id,
611 type, modtime, modby, modwith)
612 VALUES (:total, :fid, 0, 0, 'ANY', SYSDATE, :who, :entity);
613 if (dbms_errno)
614 return mr_errcode;
73cf66ba 615 }
73cf66ba 616 }
5eaef520 617 else
618 {
619 EXEC SQL UPDATE quota SET phys_id = 0 WHERE filsys_id = :fid;
620 if (dbms_errno)
621 return mr_errcode;
622 }
623 return MR_SUCCESS;
73cf66ba 624}
625
626
627/* Find the NFS physical partition that the named directory is on.
628 * This is done by comparing the dir against the mount point of the
629 * partition. To make sure we get the correct match when there is
630 * more than one, we sort the query in reverse order by dir name.
631 */
632
5eaef520 633int check_nfs(int mach_id, char *name, char *access)
73cf66ba 634{
5eaef520 635 EXEC SQL BEGIN DECLARE SECTION;
e688520a 636 char dir[NFSPHYS_DIR_SIZE];
5eaef520 637 int mid = mach_id;
638 EXEC SQL END DECLARE SECTION;
44d12d58 639 int status;
640 char *cp1;
641 char *cp2;
5eaef520 642
643 status = MR_NFS;
644 EXEC SQL DECLARE csr101 CURSOR FOR
645 SELECT nfsphys_id, dir FROM nfsphys
646 WHERE mach_id = :mid
647 ORDER BY 2 DESC;
648 if (dbms_errno)
649 return mr_errcode;
650 EXEC SQL OPEN csr101;
651 if (dbms_errno)
652 return mr_errcode;
653 while (1)
654 {
655 EXEC SQL FETCH csr101 INTO :_var_phys_id, :dir;
656 if (sqlca.sqlcode)
657 break;
658 cp1 = name;
659 cp2 = strtrim(dir);
660 while (*cp2)
661 {
662 if (*cp1++ != *cp2)
73cf66ba 663 break;
5eaef520 664 cp2++;
665 }
666 if (!*cp2)
667 {
668 status = MR_SUCCESS;
669 break;
73cf66ba 670 }
671 }
5eaef520 672 EXEC SQL CLOSE csr101;
673 if (dbms_errno)
674 return mr_errcode;
675 return status;
73cf66ba 676}
677
678
679/* setup_dfil: free any quota records and fsgroup info associated with
680 * a filesystem when it is deleted. Also adjust the allocation numbers.
681 */
682
5eaef520 683int setup_dfil(struct query *q, char **argv, client *cl)
73cf66ba 684{
5eaef520 685 EXEC SQL BEGIN DECLARE SECTION;
686 int id, total, phys_id;
687 short int none;
688 EXEC SQL END DECLARE SECTION;
689
690 id = *(int *)argv[0];
691 EXEC SQL SELECT SUM (quota) INTO :total:none FROM quota
692 WHERE filsys_id = :id;
693
694 if (none)
695 total = 0;
696
697 /** What if there are multiple phys_id's per f/s? (bad data) **/
698 EXEC SQL SELECT phys_id INTO :phys_id FROM filesys
699 WHERE filsys_id = :id;
700 EXEC SQL UPDATE nfsphys SET allocated = allocated - :total
701 WHERE nfsphys_id = :phys_id;
702
703 if (!none)
704 EXEC SQL DELETE FROM quota WHERE filsys_id = :id;
705 EXEC SQL DELETE FROM fsgroup WHERE filsys_id = :id;
706 EXEC SQL DELETE FROM fsgroup WHERE group_id = :id;
707 if (dbms_errno)
708 return mr_errcode;
709 return MR_SUCCESS;
73cf66ba 710}
711
712
713/* setup_dnfp: check to see that the nfs physical partition does not have
714 * any filesystems assigned to it before allowing it to be deleted.
715 */
716
5eaef520 717int setup_dnfp(struct query *q, char **argv, client *cl)
73cf66ba 718{
5eaef520 719 EXEC SQL BEGIN DECLARE SECTION;
720 int id, cnt;
721 char *dir;
722 EXEC SQL END DECLARE SECTION;
723
724 id = *(int *)argv[0];
725 dir = argv[1];
726 EXEC SQL SELECT count(fs.rowid) INTO :cnt FROM filesys fs, nfsphys np
727 WHERE fs.mach_id = :id AND fs.phys_id = np.nfsphys_id
728 AND np.mach_id = :id AND np.dir = :dir;
729 if (cnt > 0)
730 return MR_IN_USE;
731 if (dbms_errno)
732 return mr_errcode;
733 return MR_SUCCESS;
73cf66ba 734}
735
736
737/* setup_dqot: Remove allocation from nfsphys before deleting quota.
738 * argv[0] = filsys_id
739 * argv[1] = type if "update_quota" or "delete_quota"
740 * argv[2 or 1] = users_id or list_id
741 */
742
5eaef520 743int setup_dqot(struct query *q, char **argv, client *cl)
73cf66ba 744{
5eaef520 745 EXEC SQL BEGIN DECLARE SECTION;
746 int quota, fs, id, physid;
747 char *qtype;
748 EXEC SQL END DECLARE SECTION;
749
750 fs = *(int *)argv[0];
751 if (!strcmp(q->name, "update_quota") || !strcmp(q->name, "delete_quota"))
752 {
753 qtype = argv[1];
754 id = *(int *)argv[2];
755 }
756 else
757 {
758 qtype = "USER";
759 id = *(int *)argv[1];
73cf66ba 760 }
761
5eaef520 762 EXEC SQL SELECT quota INTO :quota FROM quota
763 WHERE type = :qtype AND entity_id = :id AND filsys_id = :fs;
764 EXEC SQL SELECT phys_id INTO :physid FROM filesys
765 WHERE filsys_id = :fs;
766 EXEC SQL UPDATE nfsphys SET allocated = allocated - :quota
767 WHERE nfsphys_id = :physid;
73cf66ba 768
5eaef520 769 if (dbms_errno)
770 return mr_errcode;
771 return MR_SUCCESS;
73cf66ba 772}
773
774
7f426981 775/* prefetch_value():
776 * This routine fetches an appropriate value from the numvalues table.
777 * It is a little hack to get around the fact that SQL doesn't let you
778 * do something like INSERT INTO table (foo) VALUES (other_table.bar).
779 *
5eaef520 780 * It is called from the query table as (*v->pre_rtn)(q, Argv, cl) or
7f426981 781 * from within a setup_...() routine with the appropriate arguments.
782 *
783 * Correct functioning of this routine may depend on the assumption
784 * that this query is an APPEND.
785 */
786
5eaef520 787int prefetch_value(struct query *q, char **argv, client *cl)
7f426981 788{
5eaef520 789 EXEC SQL BEGIN DECLARE SECTION;
790 char *name = q->validate->object_id;
791 int value;
792 EXEC SQL END DECLARE SECTION;
793 int status, limit, argc;
794
795 /* set next object id, limiting it if necessary */
796 if (!strcmp(name, "unix_uid") || !strcmp(name, "gid"))
797 limit = 1; /* So far as I know, this isn't needed. Just CMA. */
798 else
799 limit = 0;
800 if ((status = set_next_object_id(name, q->rtable, limit)) != MR_SUCCESS)
801 return status;
802
803 /* fetch object id */
804 EXEC SQL SELECT value INTO :value FROM numvalues WHERE name = :name;
805 if (dbms_errno)
806 return mr_errcode;
807 if (sqlca.sqlerrd[2] != 1)
808 return MR_INTERNAL;
809
810 argc = q->argc + q->vcnt; /* end of Argv for APPENDs */
811 sprintf(argv[argc], "%d", value);
812
813 return MR_SUCCESS;
7f426981 814}
815
816/* prefetch_filesys():
817 * Fetches the phys_id from filesys based on the filsys_id in argv[0].
818 * Appends the filsys_id and the phys_id to the argv so they can be
819 * referenced in an INSERT into a table other than filesys. Also
820 * see comments at prefetch_value().
821 *
822 * Assumes the existence of a row where filsys_id = argv[0], since a
823 * filesys label has already been resolved to a filsys_id.
824 */
5eaef520 825int prefetch_filesys(struct query *q, char **argv, client *cl)
7f426981 826{
5eaef520 827 EXEC SQL BEGIN DECLARE SECTION;
828 int fid, phid;
829 EXEC SQL END DECLARE SECTION;
830 int argc;
7f426981 831
5eaef520 832 fid = *(int *)argv[0];
833 EXEC SQL SELECT phys_id INTO :phid FROM filesys WHERE filsys_id = :fid;
834 if (dbms_errno)
835 return mr_errcode;
7f426981 836
5eaef520 837 argc = q->argc + q->vcnt;
838 sprintf(argv[argc++], "%d", phid);
839 sprintf(argv[argc], "%d", fid);
7f426981 840
5eaef520 841 return MR_SUCCESS;
7f426981 842}
843
844
845/* setup_ahst():
846 */
847
5eaef520 848int setup_ahst(struct query *q, char **argv, client *cl)
7f426981 849{
5eaef520 850 EXEC SQL BEGIN DECLARE SECTION;
e688520a 851 char *name, oldname[MACHINE_NAME_SIZE], vendor[MACHINE_VENDOR_SIZE];
db9491c6 852 char model[MACHINE_MODEL_SIZE], os[MACHINE_OS_SIZE];
ff98438b 853 int value, id, ssaddr, smask, shigh, slow, cnt;
854 unsigned int saddr, mask, high, low;
5eaef520 855 EXEC SQL END DECLARE SECTION;
856 int row;
857 struct in_addr addr;
5eaef520 858
fde09f2c 859 id = *(int *)argv[0];
860
5eaef520 861 if (!strcmp(q->shortname, "uhst"))
85330553 862 {
863 row = 1;
864 EXEC SQL SELECT name, vendor, model, os
865 INTO :oldname, :vendor, :model, :os
866 FROM machine WHERE mach_id = :id;
867 }
5eaef520 868 else
869 row = 0;
870
9e252e6f 871 /* Sanity check name, vendor, model, and os. */
872 if ((row == 0 || strcasecmp(argv[1], oldname)) &&
873 !hostname_check(argv[row]))
874 return MR_BAD_CHAR;
875 if ((row == 0 || strcasecmp(argv[2], vendor)) &&
17f585b5 876 !hostinfo_check(argv[row + 1], 0))
9e252e6f 877 return MR_BAD_CHAR;
878 if ((row == 0 || strcasecmp(argv[3], model)) &&
17f585b5 879 !hostinfo_check(argv[row + 2], 1))
9e252e6f 880 return MR_BAD_CHAR;
881 if ((row == 0 || strcasecmp(argv[4], os)) &&
17f585b5 882 !hostinfo_check(argv[row + 3], 0))
9e252e6f 883 return MR_BAD_CHAR;
8ca3e341 884
5eaef520 885 /* check for duplicate name */
886 name = argv[row];
887 EXEC SQL SELECT count(mach_id) INTO :cnt FROM hostalias
ad06a10e 888 WHERE name = UPPER(:name);
5eaef520 889 if (dbms_errno)
890 return mr_errcode;
891 if (cnt != 0)
892 return MR_EXISTS;
893
894 /* check address */
895 if (!strcmp(argv[9 + row], "unassigned"))
896 value = -1;
897 else if (!strcmp(argv[9 + row], "unique"))
898 {
899 if (*(int *)argv[8 + row] == 0)
900 value = -1;
901 else
902 value = -2;
903 }
904 else
905 {
906 value = ntohl(inet_addr(argv[9 + row]));
907 if (value == -1)
908 return MR_ADDRESS;
5482f508 909 }
5eaef520 910 if (value == 0)
911 return MR_ADDRESS;
912 if (value != -1)
913 {
914 /*
915 * an address or unique was specified.
916 */
917 id = *(int *)argv[8 + row];
ff98438b 918 EXEC SQL SELECT saddr, mask, high, low INTO :ssaddr, :smask,
919 :shigh, :slow FROM subnet WHERE snet_id = :id;
5eaef520 920 if (dbms_errno)
921 return mr_errcode;
ff98438b 922 saddr = (unsigned) ssaddr;
923 mask = (unsigned) smask;
924 high = (unsigned) shigh;
925 low = (unsigned) slow;
5eaef520 926 if (value != -2)
927 {
928 /*
929 * someone specified an IP address for the host record
930 */
082466aa 931 if ((value & mask) != saddr || value < low || value > high)
5eaef520 932 return MR_ADDRESS;
933 /*
934 * run the address argument through inet_addr(). This
935 * has the effect that any out of bounds host addrs will
936 * be converted to a valid host addr. We do this now
937 * so that the uniqueness check works. We should also
938 * link in an inet_addr() that returns an error for
939 * this case.
940 */
941 addr.s_addr = inet_addr(argv[9 + row]);
942 name = inet_ntoa(addr);
943 EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine
944 WHERE address = :name;
945 if (dbms_errno)
946 return mr_errcode;
947 if (cnt > 0)
948 {
949 /*
950 * make IP address is unique. If this a modify request
951 * (row == 1), then we expect one record to exist.
952 */
7ac48069 953 if (row == 0 || (row == 1 && cnt > 1))
5eaef520 954 return MR_ADDRESS;
955 if (row == 1 && cnt == 1)
956 {
957 EXEC SQL SELECT mach_id INTO :id FROM machine
958 WHERE address = :name;
959 if (id != *(int *)argv[0])
960 return MR_ADDRESS;
7f426981 961 }
962 }
5eaef520 963 }
964 else
965 {
966 /*
967 * a "unique" address was specified. Walk through the
968 * range specified in the network record, return
969 * error if no room left.
970 */
971 for (id = low; id <= high; id++)
972 {
973 if (((id & 0xff) == 0) || ((id & 0xff) == 255))
974 continue;
975 addr.s_addr = htonl(id);
7ac48069 976 name = inet_ntoa(addr);
5eaef520 977 EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine
978 WHERE address = :name;
979 if (dbms_errno)
980 return mr_errcode;
981 if (cnt == 0)
982 break;
7f426981 983 }
5eaef520 984 if (cnt != 0)
6715bac2 985 return MR_NO_ID;
5eaef520 986 else
987 value = htonl(id);
7f426981 988 }
5eaef520 989 /*
990 * we have an address in value. Convert it to a string and store it.
991 */
992 addr.s_addr = htonl(value);
993 strcpy(argv[9 + row], inet_ntoa(addr));
7f426981 994 }
5eaef520 995 else
996 strcpy(argv[9 + row], "unassigned");
997
998 /* status checking */
999 value = atoi(argv[7 + row]);
1000 if (row == 0 && !(value == 1 || value == 0))
1001 return MR_TYPE;
1002 if (row == 1)
1003 {
1004 id = *(int *)argv[0];
1005 EXEC SQL SELECT status INTO :cnt FROM machine WHERE mach_id = :id;
1006 if (dbms_errno)
1007 return mr_errcode;
1008 if (value != cnt)
1009 {
1010 EXEC SQL UPDATE machine SET statuschange = SYSDATE
1011 WHERE mach_id = :id;
7f426981 1012 }
1013 }
1014
5eaef520 1015 /*
1016 * If this is an update_host query, we're done.
1017 */
1018 if (row == 1)
1019 return MR_SUCCESS;
1020
1021 /*
1022 * For an add_host query, allocate and fill in a new machine id,
1023 * and then insert the creator id.
1024 */
1025 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
1026 return mr_errcode;
1027
1028 sprintf(argv[q->argc + q->vcnt + 1], "%d", cl->client_id);
1029 return MR_SUCCESS;
7f426981 1030}
1031
1032
1033/* setup_ahal():
1034 */
1035
5eaef520 1036int setup_ahal(struct query *q, char **argv, client *cl)
7f426981 1037{
5eaef520 1038 EXEC SQL BEGIN DECLARE SECTION;
1039 char *name;
1040 int cnt;
1041 EXEC SQL END DECLARE SECTION;
1042 char *p;
1043
84f3d463 1044 name = argv[0];
1045 if (!hostname_check(argv[0]))
5eaef520 1046 return MR_BAD_CHAR;
7f426981 1047
5eaef520 1048 EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine WHERE
ad06a10e 1049 name = UPPER(:name);
5eaef520 1050 if (dbms_errno)
1051 return mr_errcode;
1052 if (cnt > 0)
1053 return MR_EXISTS;
7f426981 1054
5eaef520 1055 return MR_SUCCESS;
7f426981 1056}
84f3d463 1057
1058/* hostname_check()
9e252e6f 1059 * validate the rfc1035/rfc1123-ness of a hostname
84f3d463 1060 */
1061
1062int hostname_check(char *name)
1063{
1064 char *p;
1065 int count;
1066
9e252e6f 1067 /* Sanity check name: must contain only letters, numerals, and
1068 * hyphen, and not start or end with a hyphen. Also make sure no
1069 * label (the thing the .s seperate) is longer than 63 characters.
84f3d463 1070 */
1071
9e252e6f 1072 for (p = name, count = 0; *p; p++)
84f3d463 1073 {
1074 count++;
1075 if ((!isalnum(*p) && *p != '-' && *p != '.') ||
1076 (*p == '-' && p[1] == '.'))
1077 return 0;
1078 if (*p == '.')
1079 count = 0;
1080 if (count == 64)
1081 return 0;
1082 }
1083 if (*(p - 1) == '-')
1084 return 0;
1085 return 1;
1086}
9e252e6f 1087
17f585b5 1088int hostinfo_check(char *info, int num)
9e252e6f 1089{
1090 char *p;
1091
1092 if (!*info)
1093 return 1;
1094
17f585b5 1095 /* Sanity check host hostinfo: must start with a letter (or number
1096 * if num is true), contain only letters, numerals, and hyphen, and
1097 * not end with a hyphen.
9e252e6f 1098 */
1099
17f585b5 1100 if (!isalpha(*info) && (!num || !isdigit(*info)))
9e252e6f 1101 return 0;
1102 for (p = info; *p; p++)
1103 {
1104 if ((!isalnum(*p) && *p != '-' && *p != '.') ||
1105 (*p == '-' && p[1] == '.'))
1106 return 0;
1107 }
1108 if (!isalnum(*(p - 1)))
1109 return 1;
1110}
This page took 0.48044 seconds and 5 git commands to generate.