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