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