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