]> andersk Git - moira.git/blob - server/qsupport.pc
second code style cleanup: void/void * usage, proper #includes. try to
[moira.git] / server / qsupport.pc
1 /* $Id$
2  *
3  * Special query 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 <ctype.h>
16 #include <stdlib.h>
17 #include <string.h>
18
19 EXEC SQL INCLUDE sqlca;
20
21 RCSID("$Header$");
22
23 extern char *whoami, *table_name[];
24 extern int dbms_errno, mr_errcode;
25
26 EXEC SQL BEGIN DECLARE SECTION;
27 extern char stmt_buf[];
28 EXEC SQL END DECLARE SECTION;
29
30 EXEC SQL WHENEVER SQLERROR DO dbmserr();
31
32 int get_ace_internal(char *atypex, int aid,
33                      int (*action)(int, char *[], void *), void *actarg);
34 int gmol_internal(struct query *q, char *argv[], client *cl,
35                   int (*action)(int, char *[], void *), void *actarg,
36                   int flag);
37 int qualified_get(struct query *q, char *argv[],
38                   int (*action)(int, char *[], void *), void *actarg,
39                   char *start, char *range, char *field, char *flags[]);
40
41
42 /* set_pobox - this does all of the real work.
43  *       argv = user_id, type, box
44  * if type is POP, then box should be a machine, and its ID should be put in
45  * pop_id.  If type is SMTP, then box should be a string and its ID should
46  * be put in box_id.  If type is NONE, then box doesn't matter.
47  */
48
49
50 int set_pobox(struct query *q, char **argv, client *cl)
51 {
52   EXEC SQL BEGIN DECLARE SECTION;
53   int user, id;
54   char *box, potype[9];
55   EXEC SQL END DECLARE SECTION;
56   int status;
57
58   box = argv[2];
59   user = *(int *)argv[0];
60
61   EXEC SQL SELECT pop_id, potype INTO :id, :potype FROM users
62     WHERE users_id = :user;
63   if (dbms_errno)
64     return mr_errcode;
65   if (!strcmp(strtrim(potype), "POP"))
66     set_pop_usage(id, -1);
67
68   if (!strcmp(argv[1], "POP"))
69     {
70       status = name_to_id(box, MACHINE_TABLE, &id);
71       if (status == MR_NO_MATCH)
72         return MR_MACHINE;
73       else if (status)
74         return status;
75       EXEC SQL UPDATE users SET potype = 'POP', pop_id = :id
76         WHERE users_id = :user;
77       set_pop_usage(id, 1);
78     }
79   else if (!strcmp(argv[1], "SMTP"))
80     {
81       if (strchr(box, '/') || strchr(box, '|'))
82         return MR_BAD_CHAR;
83       status = name_to_id(box, STRINGS_TABLE, &id);
84       if (status == MR_NO_MATCH)
85         id = add_string(box);
86       else if (status)
87         return status;
88       EXEC SQL UPDATE users SET potype = 'SMTP', box_id = :id
89         WHERE users_id = :user;
90     }
91   else /* argv[1] == "NONE" */
92     {
93       EXEC SQL UPDATE users SET potype = 'NONE'
94         WHERE users_id = :user;
95     }
96
97   set_pobox_modtime(q, argv, cl);
98   EXEC SQL UPDATE tblstats SET updates = updates + 1, modtime = SYSDATE
99     WHERE table_name = 'users';
100   if (dbms_errno)
101     return mr_errcode;
102   return MR_SUCCESS;
103 }
104
105
106 /* get_list_info:  passed a wildcard list name, returns lots of stuff about
107  * each list.  This is tricky:  first build a queue of all requested
108  * data.  Rest of processing consists of fixing gid, ace_name, and modby.
109  */
110
111 int get_list_info(struct query *q, char **aargv, client *cl,
112                   int (*action)(int, char *[], void *), void *actarg)
113 {
114   char *argv[13];
115   EXEC SQL BEGIN DECLARE SECTION;
116   char *name, acl_type[9], listname[33], active[5], public[5], hidden[5];
117   char maillist[5], grouplist[5], gid_str[6], desc[256];
118   char modtime[27], modwith[9];
119   int id, rowcount, acl_id, hid, modby_id;
120   EXEC SQL END DECLARE SECTION;
121   int returned, status;
122   struct save_queue *sq;
123
124   returned = rowcount = 0;
125   name = aargv[0];
126   convert_wildcards(name);
127
128   sq = sq_create();
129   EXEC SQL DECLARE csr102 CURSOR FOR SELECT list_id FROM list
130     WHERE name LIKE :name ESCAPE '*';
131   if (dbms_errno)
132     return mr_errcode;
133   EXEC SQL OPEN csr102;
134   if (dbms_errno)
135     return mr_errcode;
136   while (1)
137     {
138       EXEC SQL FETCH csr102 INTO :id;
139       if (sqlca.sqlcode)
140         break;
141       sq_save_data(sq, (void *)id);
142       rowcount++;
143     }
144   EXEC SQL CLOSE csr102;
145
146   if (dbms_errno)
147     return mr_errcode;
148   if (rowcount == 0)
149     return MR_NO_MATCH;
150
151   argv[0] = listname; argv[1] = active; argv[2] = public; argv[3] = hidden;
152   argv[4] = maillist; argv[5] = grouplist; argv[6] = gid_str;
153   argv[7] = acl_type; argv[9] = desc; argv[10] = modtime; argv[12] = modwith;
154
155   while (sq_get_data(sq, &id))
156     {
157       if (id == 0)
158         continue;
159       argv[6] = gid_str;
160       EXEC SQL SELECT name, active, publicflg,
161         hidden, hidden, maillist, grouplist, gid,
162         acl_type, acl_id, description,
163         TO_CHAR(modtime, 'DD-mon-YYYY HH24:MI:SS'), modby, modwith
164         INTO :listname, :active, :public, :hidden, :hid, :maillist,
165         :grouplist, :gid_str, :acl_type, :acl_id, :desc,
166         :modtime, :modby_id, :modwith
167         FROM list WHERE list_id = :id;
168
169       if (dbms_errno)
170         return mr_errcode;
171       strtrim(acl_type);
172
173       if (atoi(gid_str) == -1)
174         argv[6] = UNIQUE_GID;
175
176       argv[8] = malloc(0);
177       if (!strcmp(acl_type, "LIST"))
178         status = id_to_name(acl_id, LIST_TABLE, &argv[8]);
179       else if (!strcmp(acl_type, "USER"))
180         status = id_to_name(acl_id, USERS_TABLE, &argv[8]);
181       else if (!strcmp(acl_type, "KERBEROS"))
182         status = id_to_name(acl_id, STRINGS_TABLE, &argv[8]);
183       else if (!strcmp(acl_type, "NONE"))
184         {
185           status = 0;
186           free(argv[8]);
187           argv[8] = strdup("NONE");
188         }
189       else
190         {
191           status = 0;
192           free(argv[8]);
193           argv[8] = strdup("???");
194         }
195       if (status && status != MR_NO_MATCH)
196         return status;
197
198       argv[11] = malloc(0);
199       if (modby_id > 0)
200         status = id_to_name(modby_id, USERS_TABLE, &argv[11]);
201       else
202         status = id_to_name(-modby_id, STRINGS_TABLE, &argv[11]);
203       if (status && status != MR_NO_MATCH)
204         return status;
205
206       mr_trim_args(q->vcnt, argv);
207       returned++;
208       (*action)(q->vcnt, argv, actarg);
209       free(argv[8]);
210       free(argv[11]);
211     }
212
213   sq_destroy(sq);
214   if (dbms_errno)
215     return mr_errcode;
216   return MR_SUCCESS;
217 }
218
219
220 /* Add_member_to_list: do list flattening as we go!  MAXLISTDEPTH is
221  * how many different ancestors a member is allowed to have.
222  */
223
224 #define MAXLISTDEPTH    1024
225
226 int add_member_to_list(struct query *q, char **argv, client *cl)
227 {
228   EXEC SQL BEGIN DECLARE SECTION;
229   int id, lid, mid, error, who, ref, rowcnt;
230   char *mtype, dtype[9], *entity;
231   EXEC SQL END DECLARE SECTION;
232   int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a;
233   int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d;
234   int status;
235   char *dtypes[MAXLISTDEPTH];
236   char *iargv[3], *buf;
237
238   lid = *(int *)argv[0];
239   mtype = argv[1];
240   mid = *(int *)argv[2];
241   /* if the member is already a direct member of the list, punt */
242   EXEC SQL SELECT COUNT(list_id) INTO :rowcnt FROM imembers
243     WHERE list_id = :lid AND member_id = :mid
244     AND member_type = :mtype AND direct = 1;
245   if (rowcnt > 0)
246     return MR_EXISTS;
247   if (!strcasecmp(mtype, "STRING"))
248     {
249       buf = malloc(0);
250       status = id_to_name(mid, STRINGS_TABLE, &buf);
251       if (status)
252         return status;
253       if (strchr(buf, '/') || strchr(buf, '|'))
254         {
255           free(buf);
256           return MR_BAD_CHAR;
257         }
258       free(buf);
259     }
260
261   ancestors[0] = lid;
262   aref[0] = 1;
263   acount = 1;
264   EXEC SQL DECLARE csr103 CURSOR FOR
265     SELECT list_id, ref_count   FROM imembers
266     WHERE member_id = :lid AND member_type = 'LIST';
267   if (dbms_errno)
268     return mr_errcode;
269   EXEC SQL OPEN csr103;
270   if (dbms_errno)
271     return mr_errcode;
272   while (1)
273     {
274       EXEC SQL FETCH csr103 INTO :id, :ref;
275       if (sqlca.sqlcode)
276         break;
277       aref[acount] = ref;
278       ancestors[acount++] = id;
279       if (acount >= MAXLISTDEPTH)
280         break;
281     }
282   EXEC SQL CLOSE csr103;
283   if (dbms_errno)
284     return mr_errcode;
285   if (acount >= MAXLISTDEPTH)
286     return MR_INTERNAL;
287   descendants[0] = mid;
288   dtypes[0] = mtype;
289   dref[0] = 1;
290   dcount = 1;
291   error = 0;
292   if (!strcmp(mtype, "LIST"))
293     {
294       EXEC SQL DECLARE csr104 CURSOR FOR
295         SELECT member_id, member_type, ref_count
296         FROM imembers
297         WHERE list_id = :mid;
298       if (dbms_errno)
299         return mr_errcode;
300       EXEC SQL OPEN csr104;
301       if (dbms_errno)
302         return mr_errcode;
303       while (1)
304         {
305           EXEC SQL FETCH csr104 INTO :id, :dtype, :ref;
306           if (sqlca.sqlcode)
307             break;
308           switch (dtype[0])
309             {
310             case 'L':
311               dtypes[dcount] = "LIST";
312               break;
313             case 'U':
314               dtypes[dcount] = "USER";
315               break;
316             case 'S':
317               dtypes[dcount] = "STRING";
318               break;
319             case 'K':
320               dtypes[dcount] = "KERBEROS";
321               break;
322             default:
323               error++;
324               break;
325             }
326           dref[dcount] = ref;
327           descendants[dcount++] = id;
328           if (dcount >= MAXLISTDEPTH)
329             {
330               error++;
331               break;
332             }
333         }
334       EXEC SQL CLOSE csr104;
335       if (dbms_errno)
336         return mr_errcode;
337       if (error)
338         return MR_INTERNAL;
339     }
340   for (a = 0; a < acount; a++)
341     {
342       lid = ancestors[a];
343       for (d = 0; d < dcount; d++)
344         {
345           mid = descendants[d];
346           mtype = dtypes[d];
347           if (mid == lid && !strcmp(mtype, "LIST"))
348             return MR_LISTLOOP;
349           EXEC SQL SELECT COUNT(ref_count) INTO :rowcnt
350             FROM imembers
351             WHERE list_id = :lid AND member_id = :mid
352             AND member_type = :mtype;
353           ref = aref[a] * dref[d];
354           if (rowcnt > 0)
355             {
356               if (a == 0 && d == 0)
357                 {
358                   EXEC SQL UPDATE imembers
359                     SET ref_count = ref_count + :ref, direct = 1
360                     WHERE list_id = :lid AND member_id = :mid
361                     AND member_type = :mtype;
362                 }
363               else
364                 {
365                   EXEC SQL UPDATE imembers
366                     SET ref_count = ref_count + :ref
367                     WHERE list_id = :lid AND member_id = :mid
368                     AND member_type = :mtype;
369                 }
370             }
371           else
372             {
373               incremental_clear_before();
374               if (a == 0 && d == 0)
375                 {
376                   EXEC SQL INSERT INTO imembers
377                     (list_id, member_id, direct, member_type, ref_count)
378                     VALUES (:lid, :mid, 1, :mtype, 1);
379                 }
380               else
381                 {
382                   EXEC SQL INSERT INTO imembers
383                     (list_id, member_id, direct, member_type, ref_count)
384                     VALUES (:lid, :mid, 0, :mtype, 1);
385                 }
386               iargv[0] = (char *)lid;
387               iargv[1] = mtype;
388               iargv[2] = (char *)mid;
389               incremental_after(IMEMBERS_TABLE, 0, iargv);
390             }
391         }
392     }
393   lid = *(int *)argv[0];
394   entity = cl->entity;
395   who = cl->client_id;
396   EXEC SQL UPDATE list
397     SET modtime = SYSDATE, modby = :who, modwith = :entity
398     WHERE list_id = :lid;
399   if (dbms_errno)
400     return mr_errcode;
401   return MR_SUCCESS;
402 }
403
404
405 /* Delete_member_from_list: do list flattening as we go!
406  */
407
408 int delete_member_from_list(struct query *q, char **argv, client *cl)
409 {
410   EXEC SQL BEGIN DECLARE SECTION;
411   int id, lid, mid, cnt, error, who, ref;
412   char *mtype, dtype[9], *entity;
413   EXEC SQL END DECLARE SECTION;
414   int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a;
415   int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d;
416   char *dtypes[MAXLISTDEPTH];
417   char *iargv[3];
418
419   lid = *(int *)argv[0];
420   mtype = argv[1];
421   mid = *(int *)argv[2];
422   /* if the member is not a direct member of the list, punt */
423   EXEC SQL SELECT COUNT(list_id) INTO :cnt FROM imembers
424     WHERE list_id = :lid AND member_id = :mid
425     AND member_type = :mtype AND direct = 1;
426   if (dbms_errno)
427     return mr_errcode;
428   if (cnt == 0)
429     return MR_NO_MATCH;
430   ancestors[0] = lid;
431   aref[0] = 1;
432   acount = 1;
433   EXEC SQL DECLARE csr105 CURSOR FOR
434     SELECT list_id, ref_count FROM imembers
435     WHERE member_id = :lid AND member_type = 'LIST';
436   if (dbms_errno)
437     return mr_errcode;
438   EXEC SQL OPEN csr105;
439   if (dbms_errno)
440     return mr_errcode;
441   while (1)
442     {
443       EXEC SQL FETCH csr105 INTO :id, :ref;
444       if (sqlca.sqlcode)
445         break;
446       aref[acount] = ref;
447       ancestors[acount++] = id;
448       if (acount >= MAXLISTDEPTH)
449         break;
450     }
451   EXEC SQL CLOSE csr105;
452   if (dbms_errno)
453     return mr_errcode;
454   if (acount >= MAXLISTDEPTH)
455     return MR_INTERNAL;
456   descendants[0] = mid;
457   dtypes[0] = mtype;
458   dref[0] = 1;
459   dcount = 1;
460   error = 0;
461   if (!strcmp(mtype, "LIST"))
462     {
463       EXEC SQL DECLARE csr106 CURSOR FOR
464         SELECT member_id, member_type, ref_count FROM imembers
465         WHERE list_id = :mid;
466       if (dbms_errno)
467         return mr_errcode;
468       EXEC SQL OPEN csr106;
469       if (dbms_errno)
470         return mr_errcode;
471       while (1)
472         {
473           EXEC SQL FETCH csr106 INTO :id, :dtype, :ref;
474           if (sqlca.sqlcode)
475             break;
476           switch (dtype[0])
477             {
478             case 'L':
479               dtypes[dcount] = "LIST";
480               break;
481             case 'U':
482               dtypes[dcount] = "USER";
483               break;
484             case 'S':
485               dtypes[dcount] = "STRING";
486               break;
487             case 'K':
488               dtypes[dcount] = "KERBEROS";
489               break;
490             default:
491               error++;
492               break;
493             }
494           dref[dcount] = ref;
495           descendants[dcount++] = id;
496           if (dcount >= MAXLISTDEPTH)
497             break;
498         }
499       EXEC SQL CLOSE csr106;
500       if (dbms_errno)
501         return mr_errcode;
502       if (error)
503         return MR_INTERNAL;
504     }
505   for (a = 0; a < acount; a++)
506     {
507       lid = ancestors[a];
508       for (d = 0; d < dcount; d++)
509         {
510           mid = descendants[d];
511           mtype = dtypes[d];
512           if (mid == lid && !strcmp(mtype, "LIST"))
513             return MR_LISTLOOP;
514           EXEC SQL SELECT ref_count INTO :cnt FROM imembers
515             WHERE list_id = :lid AND member_id = :mid AND member_type = :mtype;
516           ref = aref[a] * dref[d];
517           if (cnt <= ref)
518             {
519               iargv[0] = (char *)lid;
520               iargv[1] = mtype;
521               iargv[2] = (char *)mid;
522               incremental_before(IMEMBERS_TABLE, 0, iargv);
523               EXEC SQL DELETE FROM imembers
524                 WHERE list_id = :lid AND member_id = :mid
525                 AND member_type= :mtype;
526               incremental_clear_after();
527             }
528           else if (a == 0 && d == 0)
529             {
530               EXEC SQL UPDATE imembers
531                 SET ref_count = ref_count - :ref, direct = 0
532                 WHERE list_id = :lid AND member_id = :mid
533                 AND member_type = :mtype;
534             }
535           else
536             {
537               EXEC SQL UPDATE imembers
538                 SET ref_count = ref_count - :ref
539                 WHERE list_id = :lid AND member_id = :mid
540                 AND member_type = :mtype;
541             }
542         }
543     }
544   lid = *(int *)argv[0];
545   entity = cl->entity;
546   who = cl->client_id;
547   EXEC SQL UPDATE list SET modtime = SYSDATE, modby = :who, modwith = :entity
548     WHERE list_id = :lid;
549   if (dbms_errno)
550     return mr_errcode;
551   return MR_SUCCESS;
552 }
553
554
555 /* get_ace_use - given a type and a name, return a type and a name.
556  * The ace_type is one of "LIST", "USER", "RLIST", or "RUSER" in argv[0],
557  * and argv[1] will contain the ID of the entity in question.  The R*
558  * types mean to recursively look at every containing list, not just
559  * when the object in question is a direct member.  On return, the
560  * usage type will be one of LIST, SERVICE, FILESYS, QUOTA, QUERY, or ZEPHYR.
561  */
562
563 int get_ace_use(struct query *q, char *argv[], client *cl,
564                 int (*action)(int, char *[], void *), void *actarg)
565 {
566   int found = 0;
567   EXEC SQL BEGIN DECLARE SECTION;
568   char *atype;
569   int aid, listid, id;
570   EXEC SQL END DECLARE SECTION;
571   struct save_queue *sq;
572
573   atype = argv[0];
574   aid = *(int *)argv[1];
575   if (!strcmp(atype, "LIST") || !strcmp(atype, "USER") ||
576       !strcmp(atype, "KERBEROS"))
577     return get_ace_internal(atype, aid, action, actarg);
578
579   sq = sq_create();
580   if (!strcmp(atype, "RLIST"))
581     {
582       sq_save_data(sq, (void *)aid);
583       /* get all the list_id's of containing lists */
584       EXEC SQL DECLARE csr107 CURSOR FOR
585         SELECT list_id FROM imembers
586         WHERE member_type = 'LIST' AND member_id = :aid;
587       if (dbms_errno)
588         return mr_errcode;
589       EXEC SQL OPEN csr107;
590       if (dbms_errno)
591         return mr_errcode;
592       while (1)
593         {
594           EXEC SQL FETCH csr107 INTO :listid;
595           if (sqlca.sqlcode)
596             break;
597           sq_save_unique_data(sq, (void *)listid);
598         }
599       EXEC SQL CLOSE csr107;
600       /* now process each one */
601       while (sq_get_data(sq, &id))
602         {
603           if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
604             found++;
605         }
606     }
607
608   if (!strcmp(atype, "RUSER"))
609     {
610       EXEC SQL DECLARE csr108 CURSOR FOR
611         SELECT list_id FROM imembers
612         WHERE member_type = 'USER' AND member_id = :aid;
613       if (dbms_errno)
614         return mr_errcode;
615       EXEC SQL OPEN csr108;
616       if (dbms_errno)
617         return mr_errcode;
618       while (1)
619         {
620           EXEC SQL FETCH csr108 INTO :listid;
621           if (sqlca.sqlcode)
622             break;
623           sq_save_data(sq, (void *)listid);
624         }
625       EXEC SQL CLOSE csr108;
626       /* now process each one */
627       while (sq_get_data(sq, &id))
628         {
629           if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
630             found++;
631         }
632       if (get_ace_internal("USER", aid, action, actarg) == MR_SUCCESS)
633         found++;
634     }
635
636   if (!strcmp(atype, "RKERBEROS"))
637     {
638       EXEC SQL DECLARE csr109 CURSOR FOR
639         SELECT list_id FROM imembers
640         WHERE member_type = 'KERBEROS' AND member_id = :aid;
641       if (dbms_errno)
642         return mr_errcode;
643       EXEC SQL OPEN csr109;
644       if (dbms_errno)
645         return mr_errcode;
646       while (1)
647         {
648           EXEC SQL FETCH csr109 INTO :listid;
649           if (sqlca.sqlcode)
650             break;
651           sq_save_data(sq, (void *)listid);
652         }
653       EXEC SQL CLOSE csr109;
654       /* now process each one */
655       while (sq_get_data(sq, &id))
656         {
657           if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
658             found++;
659         }
660       if (get_ace_internal("KERBEROS", aid, action, actarg) == MR_SUCCESS)
661         found++;
662     }
663
664   sq_destroy(sq);
665   if (dbms_errno)
666     return mr_errcode;
667   if (!found)
668     return MR_NO_MATCH;
669   return MR_SUCCESS;
670 }
671
672
673 /* This looks up a single list or user for ace use.  atype must be "USER"
674  * or "LIST", and aid is the ID of the corresponding object.  This is used
675  * by get_ace_use above.
676  */
677
678 int get_ace_internal(char *atype, int aid,
679                      int (*action)(int, char *[], void *), void *actarg)
680 {
681   char *rargv[2];
682   int found = 0;
683   EXEC SQL BEGIN DECLARE SECTION;
684   char name[33], *type = atype;
685   int id = aid;
686   EXEC SQL END DECLARE SECTION;
687
688   rargv[1] = name;
689   if (!strcmp(atype, "LIST"))
690     {
691       rargv[0] = "FILESYS";
692       EXEC SQL DECLARE csr110 CURSOR FOR
693         SELECT label FROM filesys
694         WHERE owners = :id;
695       if (dbms_errno)
696         return mr_errcode;
697       EXEC SQL OPEN csr110;
698       if (dbms_errno)
699         return mr_errcode;
700       while (1)
701         {
702           EXEC SQL FETCH csr110 INTO :name;
703           if (sqlca.sqlcode)
704             break;
705           (*action)(2, rargv, actarg);
706           found++;
707         }
708       EXEC SQL CLOSE csr110;
709
710       rargv[0] = "QUERY";
711       EXEC SQL DECLARE csr111 CURSOR FOR
712         SELECT capability FROM capacls
713         WHERE list_id = :id;
714       if (dbms_errno)
715         return mr_errcode;
716       EXEC SQL OPEN csr111;
717       if (dbms_errno)
718         return mr_errcode;
719       while (1)
720         {
721           EXEC SQL FETCH csr111 INTO :name;
722           if (sqlca.sqlcode)
723             break;
724           (*action)(2, rargv, actarg);
725           found++;
726         }
727       EXEC SQL CLOSE csr111;
728     }
729   else if (!strcmp(atype, "USER"))
730     {
731       rargv[0] = "FILESYS";
732       EXEC SQL DECLARE csr112 CURSOR FOR
733         SELECT label FROM filesys
734         WHERE owner = :id;
735       if (dbms_errno)
736         return mr_errcode;
737       EXEC SQL OPEN csr112;
738       if (dbms_errno)
739         return mr_errcode;
740       while (1)
741         {
742           EXEC SQL FETCH csr112 INTO :name;
743           if (sqlca.sqlcode)
744             break;
745           (*action)(2, rargv, actarg);
746           found++;
747         }
748       EXEC SQL CLOSE csr112;
749     }
750
751   rargv[0] = "LIST";
752   EXEC SQL DECLARE csr113 CURSOR FOR
753     SELECT name FROM list
754     WHERE acl_type = :type AND acl_id = :id;
755   if (dbms_errno)
756     return mr_errcode;
757   EXEC SQL OPEN csr113;
758   if (dbms_errno)
759     return mr_errcode;
760   while (1)
761     {
762       EXEC SQL FETCH csr113 INTO :name;
763       if (sqlca.sqlcode)
764         break;
765       (*action)(2, rargv, actarg);
766       found++;
767     }
768   EXEC SQL CLOSE csr113;
769
770   rargv[0] = "SERVICE";
771   EXEC SQL DECLARE csr114 CURSOR FOR
772     SELECT name FROM servers
773     WHERE acl_type = :type AND acl_id = :id;
774   if (dbms_errno)
775     return mr_errcode;
776   EXEC SQL OPEN csr114;
777   if (dbms_errno)
778     return mr_errcode;
779   while (1)
780     {
781       EXEC SQL FETCH csr114 INTO :name;
782       if (sqlca.sqlcode)
783         break;
784       (*action)(2, rargv, actarg);
785       found++;
786     }
787   EXEC SQL CLOSE csr114;
788
789   rargv[0] = "HOSTACCESS";
790   EXEC SQL DECLARE csr115 CURSOR FOR
791     SELECT name FROM machine m, hostaccess ha
792     WHERE m.mach_id = ha.mach_id AND ha.acl_type = :type
793     AND ha.acl_id = :id;
794     if (dbms_errno)
795         return mr_errcode;
796     EXEC SQL OPEN csr115;
797     if (dbms_errno)
798         return mr_errcode;
799     while (1)
800       {
801         EXEC SQL FETCH csr115 INTO :name;
802         if (sqlca.sqlcode)
803           break;
804         (*action)(2, rargv, actarg);
805         found++;
806       }
807     EXEC SQL CLOSE csr115;
808
809     rargv[0] = "ZEPHYR";
810     EXEC SQL DECLARE csr116 CURSOR FOR
811       SELECT class FROM zephyr z
812       WHERE z.xmt_type = :type AND z.xmt_id = :id
813       OR z.sub_type = :type AND z.sub_id = :id
814       OR z.iws_type = :type AND z.iws_id = :id
815       OR z.iui_type = :type AND z.iui_id = :id;
816     if (dbms_errno)
817       return mr_errcode;
818     EXEC SQL OPEN csr116;
819     if (dbms_errno)
820       return mr_errcode;
821     while (1)
822       {
823         EXEC SQL FETCH csr116 INTO :name;
824         if (sqlca.sqlcode)
825           break;
826         (*action)(2, rargv, actarg);
827         found++;
828       }
829     EXEC SQL CLOSE csr116;
830
831     if (!found)
832       return MR_NO_MATCH;
833     return MR_SUCCESS;
834 }
835
836
837 /* get_lists_of_member - given a type and a name, return the name and flags
838  * of all of the lists of the given member.  The member_type is one of
839  * "LIST", "USER", "STRING", "RLIST", "RUSER", or "RSTRING" in argv[0],
840  * and argv[1] will contain the ID of the entity in question.  The R*
841  * types mean to recursively look at every containing list, not just
842  * when the object in question is a direct member.
843  */
844
845 int get_lists_of_member(struct query *q, char *argv[], client *cl,
846                         int (*action)(int, char *[], void *), void *actarg)
847 {
848   int found = 0, direct = 1;
849   char *rargv[6];
850   EXEC SQL BEGIN DECLARE SECTION;
851   char *atype;
852   int aid;
853   char name[33], active[5], public[5], hidden[5], maillist[5], grouplist[5];
854   EXEC SQL END DECLARE SECTION;
855
856   atype = argv[0];
857   aid = *(int *)argv[1];
858   if (!strcmp(atype, "RLIST"))
859     {
860       atype = "LIST";
861       direct = 0;
862     }
863   if (!strcmp(atype, "RUSER"))
864     {
865       atype = "USER";
866       direct = 0;
867     }
868   if (!strcmp(atype, "RSTRING"))
869     {
870       atype = "STRING";
871       direct = 0;
872     }
873   if (!strcmp(atype, "RKERBEROS"))
874     {
875       atype = "KERBEROS";
876       direct = 0;
877     }
878
879   rargv[0] = name;
880   rargv[1] = active;
881   rargv[2] = public;
882   rargv[3] = hidden;
883   rargv[4] = maillist;
884   rargv[5] = grouplist;
885   if (direct)
886     {
887       EXEC SQL DECLARE csr117a CURSOR FOR
888         SELECT l.name, l.active, l.publicflg, l.hidden, l.maillist, l.grouplist
889         FROM list l, imembers im
890         WHERE l.list_id = im.list_id AND im.direct = 1
891         AND im.member_type = :atype AND im.member_id = :aid;
892       if (dbms_errno)
893         return mr_errcode;
894       EXEC SQL OPEN csr117a;
895       if (dbms_errno)
896         return mr_errcode;
897       while (1)
898         {
899           EXEC SQL FETCH csr117a
900             INTO :name, :active, :public, :hidden, :maillist, :grouplist;
901           if (sqlca.sqlcode)
902             break;
903           (*action)(6, rargv, actarg);
904           found++;
905         }
906       EXEC SQL CLOSE csr117a;
907     }
908   else
909     {
910       EXEC SQL DECLARE csr117b CURSOR FOR
911         SELECT l.name, l.active, l.publicflg, l.hidden, l.maillist, l.grouplist
912         FROM list l, imembers im
913         WHERE l.list_id = im.list_id
914         AND im.member_type = :atype AND im.member_id = :aid;
915       if (dbms_errno)
916         return mr_errcode;
917       EXEC SQL OPEN csr117b;
918       if (dbms_errno)
919         return mr_errcode;
920       while (1)
921         {
922           EXEC SQL FETCH csr117b
923             INTO :name, :active, :public, :hidden, :maillist, :grouplist;
924           if (sqlca.sqlcode)
925             break;
926           (*action)(6, rargv, actarg);
927           found++;
928         }
929       EXEC SQL CLOSE csr117b;
930     }
931
932   if (dbms_errno)
933     return mr_errcode;
934   if (!found)
935     return MR_NO_MATCH;
936   return MR_SUCCESS;
937 }
938
939
940 /* qualified_get_lists: passed "TRUE", "FALSE", or "DONTCARE" for each of
941  * the five flags associated with each list.  It will return the name of
942  * each list that meets the quailifications.  It does this by building a
943  * where clause based on the arguments, then doing a retrieve.
944  */
945
946 static char *lflags[5] = { "active", "publicflg", "hidden", "maillist", "grouplist" };
947
948 int qualified_get_lists(struct query *q, char *argv[], client *cl,
949                         int (*action)(int, char *[], void *), void *actarg)
950 {
951   return qualified_get(q, argv, action, actarg, "l.list_id != 0",
952                        "l", "name", lflags);
953 }
954
955
956 /* get_members_of_list - this gets only direct members */
957
958 int get_members_of_list(struct query *q, char *argv[], client *cl,
959                         int (*action)(int, char *[], void *), void *actarg)
960 {
961   return gmol_internal(q, argv, cl, action, actarg, 1);
962 }
963
964 /* get_end_members_of_list - this gets direct or indirect members */
965
966 int get_end_members_of_list(struct query *q, char *argv[], client *cl,
967                             int (*action)(int, char *[], void *), void *actarg)
968 {
969   return gmol_internal(q, argv, cl, action, actarg, 0);
970 }
971
972 /** gmol_internal - optimized query for retrieval of list members
973  **   used by both get_members_of_list and get_end_members_of_list
974  **
975  ** Inputs:
976  **   argv[0] - list_id
977  **
978  ** Description:
979  **   - retrieve USER members, then LIST members, then STRING members
980  **/
981
982 int gmol_internal(struct query *q, char *argv[], client *cl,
983                   int (*action)(int, char *[], void *), void *actarg, int flag)
984 {
985   EXEC SQL BEGIN DECLARE SECTION;
986   int list_id, direct;
987   char member_name[129];
988   EXEC SQL END DECLARE SECTION;
989   char *targv[2];
990
991   /* true/false flag indicates whether to display only direct members. */
992   if (flag)
993     direct = 0;
994   else
995     direct = -1;
996
997   list_id = *(int *)argv[0];
998
999   targv[1] = member_name;
1000   targv[0] = "USER";
1001   EXEC SQL DECLARE csr119 CURSOR FOR
1002     SELECT u.login FROM users u, imembers im
1003     WHERE im.list_id = :list_id AND im.member_type = 'USER'
1004     AND im.member_id = u.users_id AND im.direct > :direct
1005     ORDER BY 1;
1006   if (dbms_errno)
1007     return mr_errcode;
1008   EXEC SQL OPEN csr119;
1009   if (dbms_errno)
1010     return mr_errcode;
1011   while (1)
1012     {
1013       EXEC SQL FETCH csr119 INTO :member_name;
1014       if (sqlca.sqlcode)
1015         break;
1016       (*action)(2, targv, actarg);
1017     }
1018   EXEC SQL CLOSE csr119;
1019   if (dbms_errno)
1020     return mr_errcode;
1021
1022   targv[0] = "LIST";
1023   EXEC SQL DECLARE csr120 CURSOR FOR
1024     SELECT l.name FROM list l, imembers im
1025     WHERE im.list_id = :list_id AND im.member_type = 'LIST'
1026     AND im.member_id = l.list_id AND im.direct > :direct
1027     ORDER BY 1;
1028   if (dbms_errno)
1029     return mr_errcode;
1030   EXEC SQL OPEN csr120;
1031   if (dbms_errno)
1032     return mr_errcode;
1033   while (1)
1034     {
1035       EXEC SQL FETCH csr120 INTO :member_name;
1036       if (sqlca.sqlcode)
1037         break;
1038       (*action)(2, targv, actarg);
1039     }
1040   EXEC SQL CLOSE csr120;
1041   if (dbms_errno)
1042     return mr_errcode;
1043
1044   targv[0] = "STRING";
1045   EXEC SQL DECLARE csr121 CURSOR FOR
1046     SELECT str.string FROM strings str, imembers im
1047     WHERE im.list_id = :list_id AND im.member_type = 'STRING'
1048     AND im.member_id = str.string_id AND im.direct > :direct
1049     ORDER BY 1;
1050   if (dbms_errno)
1051     return mr_errcode;
1052   EXEC SQL OPEN csr121;
1053   if (dbms_errno)
1054     return mr_errcode;
1055   while (1)
1056     {
1057       EXEC SQL FETCH csr121 INTO :member_name;
1058       if (sqlca.sqlcode)
1059         break;
1060       (*action)(2, targv, actarg);
1061     }
1062   EXEC SQL CLOSE csr121;
1063   if (dbms_errno)
1064     return mr_errcode;
1065
1066   targv[0] = "KERBEROS";
1067   EXEC SQL DECLARE csr122 CURSOR FOR
1068     SELECT str.string FROM strings str, imembers im
1069     WHERE im.list_id = :list_id AND im.member_type = 'KERBEROS'
1070     AND im.member_id = str.string_id
1071     AND im.direct > :direct
1072     ORDER BY 1;
1073   if (dbms_errno)
1074     return mr_errcode;
1075   EXEC SQL OPEN csr122;
1076   if (dbms_errno)
1077     return mr_errcode;
1078   while (1)
1079     {
1080       EXEC SQL FETCH csr122 INTO :member_name;
1081       if (sqlca.sqlcode)
1082         break;
1083       (*action)(2, targv, actarg);
1084     }
1085   EXEC SQL CLOSE csr122;
1086   if (dbms_errno)
1087     return mr_errcode;
1088
1089   return MR_SUCCESS;
1090 }
1091
1092
1093 /* count_members_of_list: this is a simple query, but it cannot be done
1094  * through the dispatch table.
1095  */
1096
1097 int count_members_of_list(struct query *q, char *argv[], client *cl,
1098                           int (*action)(int, char *[], void *), void *actarg)
1099 {
1100   EXEC SQL BEGIN DECLARE SECTION;
1101   int  list, ct = 0;
1102   EXEC SQL END DECLARE SECTION;
1103   char *rargv[1], countbuf[5];
1104
1105   list = *(int *)argv[0];
1106   rargv[0] = countbuf;
1107   EXEC SQL SELECT count (*) INTO :ct FROM imembers
1108     WHERE list_id = :list AND direct = 1;
1109   if (dbms_errno)
1110     return mr_errcode;
1111   sprintf(countbuf, "%d", ct);
1112   (*action)(1, rargv, actarg);
1113   return MR_SUCCESS;
1114 }
1115
1116
1117 /* qualified_get_server: passed "TRUE", "FALSE", or "DONTCARE" for each of
1118  * the three flags associated with each service.  It will return the name of
1119  * each service that meets the quailifications.  It does this by building a
1120  * where clause based on the arguments, then doing a retrieve.
1121  */
1122
1123 static char *sflags[3] = { "enable", "inprogress", "harderror" };
1124
1125 int qualified_get_server(struct query *q, char *argv[], client *cl,
1126                          int (*action)(int, char *[], void *), void *actarg)
1127 {
1128   return qualified_get(q, argv, action, actarg, "s.name is not null",
1129                        "s", "name", sflags);
1130   /* of course, name will never be null, but we need something there
1131      to make qualified_get happy */
1132 }
1133
1134
1135 /* generic qualified get routine, used by qualified_get_lists,
1136  * qualified_get_server, and qualified_get_serverhost.
1137  *   Args:
1138  *      start - a simple where clause, must not be empty
1139  *      range - the name of the range variable
1140  *      field - the field to return
1141  *      flags - an array of strings, names of the flag variables
1142  */
1143
1144 int qualified_get(struct query *q, char *argv[],
1145                   int (*action)(int, char *[], void *), void *actarg,
1146                   char *start, char *range, char *field, char *flags[])
1147 {
1148   char qual[256];
1149   int i;
1150   char buf[32];
1151
1152   strcpy(qual, start);
1153   for (i = 0; i < q->argc; i++)
1154     {
1155       if (!strcmp(argv[i], "TRUE"))
1156         {
1157           sprintf(buf, " AND %s.%s != 0", range, flags[i]);
1158           strcat(qual, buf);
1159         }
1160       else if (!strcmp(argv[i], "FALSE"))
1161         {
1162           sprintf(buf, " AND %s.%s = 0", range, flags[i]);
1163           strcat(qual, buf);
1164         }
1165     }
1166
1167   sprintf(stmt_buf, "SELECT %s.%s FROM %s %s WHERE %s", range, field,
1168           table_name[q->rtable], range, qual);
1169   return do_for_all_rows(stmt_buf, 1, action, actarg);
1170 }
1171
1172
1173 /* qualified_get_serverhost: passed "TRUE", "FALSE", or "DONTCARE" for each of
1174  * the five flags associated with each serverhost.  It will return the name of
1175  * each service and host that meets the quailifications.  It does this by
1176  * building a where clause based on the arguments, then doing a retrieve.
1177  */
1178
1179 static char *shflags[6] = { "service", "enable", "override", "success",
1180                             "inprogress", "hosterror" };
1181
1182 int qualified_get_serverhost(struct query *q, char *argv[], client *cl,
1183                              int (*action)(int, char *[], void *),
1184                              void *actarg)
1185 {
1186   char qual[256], buf[32];
1187   int i;
1188
1189   sprintf(qual, "m.mach_id = sh.mach_id AND sh.service = UPPER('%s')",
1190           argv[0]);
1191   for (i = 1; i < q->argc; i++)
1192     {
1193       if (!strcmp(argv[i], "TRUE"))
1194         {
1195           sprintf(buf, " AND sh.%s != 0", shflags[i]);
1196           strcat(qual, buf);
1197         }
1198       else if (!strcmp(argv[i], "FALSE"))
1199         {
1200           sprintf(buf, " AND sh.%s = 0", shflags[i]);
1201           strcat(qual, buf);
1202         }
1203     }
1204
1205   sprintf(stmt_buf, "SELECT sh.service, m.name FROM serverhosts sh, "
1206           "machine m WHERE %s", qual);
1207   return do_for_all_rows(stmt_buf, 2, action, actarg);
1208 }
1209
1210
1211 /* register_user - change user's login name and allocate a pobox, group,
1212  * filesystem, and quota for them.  The user's status must start out as 0,
1213  * and is left as 2.  Arguments are: user's UID, new login name, and user's
1214  * type for filesystem allocation (MR_FS_STUDENT, MR_FS_FACULTY,
1215  * MR_FS_STAFF, MR_FS_MISC).
1216  */
1217
1218 int register_user(struct query *q, char **argv, client *cl)
1219 {
1220   EXEC SQL BEGIN DECLARE SECTION;
1221   char *login, *entity, directory[129], machname[33];
1222   int who, rowcount, mid, uid, users_id, utype, list_id;
1223   int ostatus, nstatus, fsidval;
1224   static int m_id = 0, def_quota = 0;
1225   EXEC SQL END DECLARE SECTION;
1226   char buffer[256], *aargv[3];
1227
1228   entity = cl->entity;
1229   who = cl->client_id;
1230
1231   uid = atoi(argv[0]);
1232   login = argv[1];
1233   utype = atoi(argv[2]);
1234
1235   /* find user */
1236   EXEC SQL SELECT users_id, status INTO :users_id, :ostatus
1237     FROM users
1238     WHERE unix_uid = :uid AND (status = 0 OR status = 5 OR status = 6);
1239
1240   if (sqlca.sqlerrd[2] == 0)
1241     return MR_NO_MATCH;
1242   if (sqlca.sqlerrd[2] > 1)
1243     return MR_NOT_UNIQUE;
1244
1245   /* check new login name */
1246   EXEC SQL SELECT COUNT(login) INTO :rowcount FROM users
1247     WHERE login = :login AND users_id != :users_id;
1248   if (dbms_errno)
1249     return mr_errcode;
1250   if (rowcount > 0)
1251     return MR_IN_USE;
1252   EXEC SQL SELECT COUNT(name) INTO :rowcount FROM list
1253     WHERE name = :login;
1254   if (dbms_errno)
1255     return mr_errcode;
1256   if (rowcount > 0)
1257     return MR_IN_USE;
1258   EXEC SQL SELECT COUNT(label) INTO :rowcount FROM filesys
1259     WHERE label = :login;
1260   if (dbms_errno)
1261     return mr_errcode;
1262   if (rowcount > 0)
1263     return MR_IN_USE;
1264   EXEC SQL SELECT COUNT(name) INTO :rowcount FROM alias
1265     WHERE name = :login AND type = 'FILESYS';
1266   if (dbms_errno)
1267     return mr_errcode;
1268   if (rowcount > 0)
1269     return MR_IN_USE;
1270   com_err(whoami, 0, "login name OK");
1271
1272   /* choose place for pobox, put in mid */
1273   EXEC SQL DECLARE csr130 CURSOR FOR
1274     SELECT sh.mach_id, m.name FROM serverhosts sh, machine m
1275     WHERE sh.service = 'POP' AND sh.mach_id = m.mach_id
1276     AND sh.value2 - sh.value1 = (SELECT MAX(value2 - value1) FROM serverhosts
1277                                  WHERE service = 'POP');
1278   if (dbms_errno)
1279     return mr_errcode;
1280   EXEC SQL OPEN csr130;
1281   if (dbms_errno)
1282     return mr_errcode;
1283   EXEC SQL FETCH csr130 INTO :mid, :machname;
1284   if (sqlca.sqlerrd[2] == 0)
1285     {
1286       EXEC SQL CLOSE csr130;
1287       if (dbms_errno)
1288         return mr_errcode;
1289       return MR_NO_POBOX;
1290     }
1291   else
1292     {
1293       EXEC SQL CLOSE csr130;
1294       if (dbms_errno)
1295         return mr_errcode;
1296     }
1297
1298   /* change login name, set pobox */
1299   sprintf(buffer, "u.users_id = %d", users_id);
1300   incremental_before(USERS_TABLE, buffer, 0);
1301   nstatus = 2;
1302   if (ostatus == 5 || ostatus == 6)
1303     nstatus = 1;
1304   EXEC SQL UPDATE users SET login = :login, status = :nstatus,
1305     modtime = SYSDATE, modby = :who, modwith = :entity, potype = 'POP',
1306     pop_id = :mid, pmodtime = SYSDATE, pmodby = :who, pmodwith = :entity
1307     WHERE users_id = :users_id;
1308
1309   if (dbms_errno)
1310     return mr_errcode;
1311   if (sqlca.sqlerrd[2] != 1)
1312     return MR_INTERNAL;
1313   set_pop_usage(mid, 1);
1314   com_err(whoami, 0, "set login name to %s and pobox to %s", login,
1315           strtrim(machname));
1316   incremental_after(USERS_TABLE, buffer, 0);
1317
1318   if (m_id == 0)
1319     {
1320       /* Cell Name (I know, it shouldn't be hard coded...) */
1321       strcpy(machname, "ATHENA.MIT.EDU");
1322       EXEC SQL SELECT mach_id INTO :m_id FROM machine
1323         WHERE name = :machname;
1324     }
1325
1326   EXEC SQL SELECT list_id INTO :list_id FROM list
1327     WHERE name = 'wheel';
1328
1329   /* create filesystem */
1330   if (set_next_object_id("filsys_id", FILESYS_TABLE, 0))
1331     return MR_NO_ID;
1332   incremental_clear_before();
1333   if (islower(login[0]) && islower(login[1]))
1334     {
1335       sprintf(directory, "/afs/athena.mit.edu/user/%c/%c/%s",
1336               login[0], login[1], login);
1337     }
1338   else
1339     sprintf(directory, "/afs/athena.mit.edu/user/other/%s", login);
1340
1341   EXEC SQL SELECT value INTO :fsidval FROM numvalues
1342     WHERE numvalues.name = 'filsys_id';
1343   EXEC SQL INSERT INTO filesys
1344     (filsys_id, phys_id, label, type, mach_id, name,
1345      mount, rwaccess, comments, owner, owners, createflg,
1346      lockertype, modtime, modby, modwith)
1347     VALUES
1348     (:fsidval, 0, :login, 'AFS', :m_id, :directory,
1349      '/mit/' || :login, 'w', 'User Locker', :users_id, :list_id, 1,
1350      'HOMEDIR', SYSDATE, :who, :entity);
1351
1352   if (dbms_errno)
1353     return mr_errcode;
1354   if (sqlca.sqlerrd[2] != 1)
1355     return MR_INTERNAL;
1356   sprintf(buffer, "fs.filsys_id = %d", fsidval);
1357   incremental_after(FILESYS_TABLE, buffer, 0);
1358
1359   /* set quota */
1360   if (def_quota == 0)
1361     {
1362       EXEC SQL SELECT value INTO :def_quota FROM numvalues
1363         WHERE name = 'def_quota';
1364       if (dbms_errno)
1365         return mr_errcode;
1366       if (sqlca.sqlerrd[2] != 1)
1367         return MR_NO_QUOTA;
1368     }
1369   incremental_clear_before();
1370   EXEC SQL INSERT INTO quota
1371     (entity_id, filsys_id, type, quota, phys_id, modtime, modby, modwith)
1372     VALUES (0, :fsidval, 'ANY', :def_quota, 0, SYSDATE, :who, :entity);
1373   if (dbms_errno)
1374     return mr_errcode;
1375   if (sqlca.sqlerrd[2] != 1)
1376     return MR_INTERNAL;
1377   aargv[0] = login;
1378   aargv[1] = "ANY";
1379   aargv[2] = login;
1380   sprintf(buffer, "q.entity_id = 0 and q.filsys_id = %d and q.type = 'ANY'",
1381           fsidval);
1382   incremental_after(QUOTA_TABLE, buffer, aargv);
1383   com_err(whoami, 0, "quota of %d assigned", def_quota);
1384   if (dbms_errno)
1385     return mr_errcode;
1386
1387   cache_entry(login, USERS_TABLE, users_id);
1388
1389   EXEC SQL UPDATE tblstats SET updates = updates + 1, modtime = SYSDATE
1390     WHERE table_name = 'users';
1391   EXEC SQL UPDATE tblstats SET appends = appends + 1, modtime = SYSDATE
1392     WHERE table_name = 'filesys' OR table_name = 'quota';
1393   if (dbms_errno)
1394     return mr_errcode;
1395   return MR_SUCCESS;
1396 }
1397
1398
1399
1400 /** set_pop_usage - incr/decr usage count for pop server in serverhosts talbe
1401  **
1402  ** Inputs:
1403  **   id of machine
1404  **   delta (will be +/- 1)
1405  **
1406  ** Description:
1407  **   - incr/decr value field in serverhosts table for pop/mach_id
1408  **
1409  **/
1410
1411 int set_pop_usage(id, cnt)
1412     int id, cnt;
1413 {
1414   EXEC SQL BEGIN DECLARE SECTION;
1415   int iid = id, icnt = cnt;
1416   EXEC SQL END DECLARE SECTION;
1417
1418   EXEC SQL UPDATE serverhosts SET value1 = value1 + :icnt
1419     WHERE serverhosts.service = 'POP' AND serverhosts.mach_id = :iid;
1420
1421   if (dbms_errno)
1422     return mr_errcode;
1423   return MR_SUCCESS;
1424 }
1425
This page took 0.159099 seconds and 5 git commands to generate.