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