]> andersk Git - moira.git/blob - server/qfollow.pc
support IMAP boxes in get_pobox
[moira.git] / server / qfollow.pc
1 /* $Id$
2  *
3  * Query followup 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
11 #include <mit-copyright.h>
12 #include "mr_server.h"
13 #include "query.h"
14 #include "qrtn.h"
15
16 #include <errno.h>
17 #include <ctype.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #ifdef GDSS
21 #include "gdss.h"
22 #endif /* GDSS */
23
24 EXEC SQL INCLUDE sqlca;
25
26 RCSID("$Header$");
27
28 extern char *whoami, *table_name[];
29 extern int dbms_errno, mr_errcode;
30
31 EXEC SQL BEGIN DECLARE SECTION;
32 extern char stmt_buf[];
33 EXEC SQL END DECLARE SECTION;
34
35 EXEC SQL WHENEVER SQLERROR DO dbmserr();
36
37
38 /* FOLLOWUP ROUTINES */
39
40 /* generic set_modtime routine.  This takes the table id from the query,
41  * and will update the modtime, modby, and modwho fields in the entry in
42  * the table whose name field matches argv[0].
43  */
44
45 int set_modtime(struct query *q, char *argv[], client *cl)
46 {
47   char *name, *entity, *table;
48   int who;
49
50   entity = cl->entity;
51   who = cl->client_id;
52   table = table_name[q->rtable];
53   name = argv[0];
54
55   sprintf(stmt_buf, "UPDATE %s SET modtime = SYSDATE, modby = %d, "
56           "modwith = '%s' WHERE name = '%s'", table, who, entity, name);
57   EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
58
59   return MR_SUCCESS;
60 }
61
62 /* generic set_modtime_by_id routine.  This takes the table id from
63  * the query, and the id name from the validate record,
64  * and will update the modtime, modby, and modwho fields in the entry in
65  * the table whose id matches argv[0].
66  */
67
68 int set_modtime_by_id(struct query *q, char *argv[], client *cl)
69 {
70   char *entity, *table, *id_name;
71   int who, id;
72
73   entity = cl->entity;
74   who = cl->client_id;
75   table = table_name[q->rtable];
76   id_name = q->validate->object_id;
77
78   id = *(int *)argv[0];
79   sprintf(stmt_buf, "UPDATE %s SET modtime = SYSDATE, modby = %d, "
80           "modwith = '%s' WHERE %s = %d", table, who, entity, id_name, id);
81   EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
82   return MR_SUCCESS;
83 }
84
85
86 /* Sets the finger modtime on a user record.  The users_id will be in argv[0].
87  */
88
89 int set_finger_modtime(struct query *q, char *argv[], client *cl)
90 {
91   EXEC SQL BEGIN DECLARE SECTION;
92   int users_id, who;
93   char *entity;
94   EXEC SQL END DECLARE SECTION;
95
96   entity = cl->entity;
97   who = cl->client_id;
98   users_id = *(int *)argv[0];
99
100   EXEC SQL UPDATE users SET fmodtime = SYSDATE, fmodby = :who,
101     fmodwith = :entity WHERE users_id = :users_id;
102
103   return MR_SUCCESS;
104 }
105
106
107 /* Sets the pobox modtime on a user record.  The users_id will be in argv[0].
108  */
109
110 int set_pobox_modtime(struct query *q, char *argv[], client *cl)
111 {
112   EXEC SQL BEGIN DECLARE SECTION;
113   int users_id, who;
114   char *entity;
115   EXEC SQL END DECLARE SECTION;
116
117   entity = cl->entity;
118   who = cl->client_id;
119   users_id = *(int *)argv[0];
120
121   EXEC SQL UPDATE users SET pmodtime = SYSDATE, pmodby = :who,
122     pmodwith = :entity WHERE users_id = :users_id;
123
124   return MR_SUCCESS;
125 }
126
127
128 /* Like set_modtime, but uppercases the name first.
129  */
130
131 int set_uppercase_modtime(struct query *q, char *argv[], client *cl)
132 {
133   char *name, *entity, *table;
134   int who;
135
136   entity = cl->entity;
137   who = cl->client_id;
138   table = table_name[q->rtable];
139   name = argv[0];
140
141   sprintf(stmt_buf, "UPDATE %s SET modtime = SYSDATE, modby = %d, "
142           "modwith = '%s' WHERE name = UPPER('%s')", table, who, entity, name);
143   EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
144
145   return MR_SUCCESS;
146 }
147
148
149 /* Sets the modtime on the machine whose mach_id is in argv[0].  This routine
150  * is necessary for add_machine_to_cluster becuase the table that query
151  * operates on is "mcm", not "machine".
152  */
153
154 int set_mach_modtime_by_id(struct query *q, char *argv[], client *cl)
155 {
156   EXEC SQL BEGIN DECLARE SECTION;
157   char *entity;
158   int who, id;
159   EXEC SQL END DECLARE SECTION;
160
161   entity = cl->entity;
162   who = cl->client_id;
163   id = *(int *)argv[0];
164   EXEC SQL UPDATE machine SET modtime = SYSDATE, modby = :who,
165     modwith = :entity WHERE mach_id = :id;
166
167   return MR_SUCCESS;
168 }
169
170
171 /* Sets the modtime on the cluster whose mach_id is in argv[0].  This routine
172  * is necessary for add_cluster_data and delete_cluster_data becuase the
173  * table that query operates on is "svc", not "cluster".
174  */
175
176 int set_cluster_modtime_by_id(struct query *q, char *argv[], client *cl)
177 {
178   EXEC SQL BEGIN DECLARE SECTION;
179   char *entity;
180   int who, id;
181   EXEC SQL END DECLARE SECTION;
182
183   entity = cl->entity;
184   who = cl->client_id;
185
186   id = *(int *)argv[0];
187   EXEC SQL UPDATE clusters SET modtime = SYSDATE, modby = :who,
188     modwith = :entity WHERE clu_id = :id;
189   return MR_SUCCESS;
190 }
191
192
193 /* sets the modtime on the serverhost where the service name is in argv[0]
194  * and the mach_id is in argv[1].
195  */
196
197 int set_serverhost_modtime(struct query *q, char *argv[], client *cl)
198 {
199   EXEC SQL BEGIN DECLARE SECTION;
200   char *entity, *serv;
201   int who, id;
202   EXEC SQL END DECLARE SECTION;
203
204   entity = cl->entity;
205   who = cl->client_id;
206
207   serv = argv[0];
208   id = *(int *)argv[1];
209   EXEC SQL UPDATE serverhosts
210     SET modtime = SYSDATE, modby = :who, modwith = :entity
211     WHERE service = :serv AND mach_id = :id;
212   return MR_SUCCESS;
213 }
214
215
216 /* sets the modtime on the nfsphys where the mach_id is in argv[0] and the
217  * directory name is in argv[1].
218  */
219
220 int set_nfsphys_modtime(struct query *q, char *argv[], client *cl)
221 {
222   EXEC SQL BEGIN DECLARE SECTION;
223   char *entity, *dir;
224   int who, id;
225   EXEC SQL END DECLARE SECTION;
226
227   entity = cl->entity;
228   who = cl->client_id;
229
230   id = *(int *)argv[0];
231   dir = argv[1];
232   EXEC SQL UPDATE nfsphys SET modtime = SYSDATE, modby = :who,
233     modwith = :entity WHERE dir = :dir AND mach_id = :id;
234   return MR_SUCCESS;
235 }
236
237
238 /* sets the modtime on a filesystem, where argv[0] contains the filesys
239  * label.
240  */
241
242 int set_filesys_modtime(struct query *q, char *argv[], client *cl)
243 {
244   EXEC SQL BEGIN DECLARE SECTION;
245   char *label, *entity;
246   int who;
247   extern int _var_phys_id;
248   EXEC SQL END DECLARE SECTION;
249
250   entity = cl->entity;
251   who = cl->client_id;
252
253   label = argv[0];
254   if (!strcmp(q->shortname, "ufil"))
255     label = argv[1];
256
257   EXEC SQL UPDATE filesys SET modtime = SYSDATE, modby = :who,
258     modwith = :entity, phys_id = :_var_phys_id
259     WHERE label = :label;
260   return MR_SUCCESS;
261 }
262
263
264 /* sets the modtime on a zephyr class, where argv[0] contains the class
265  * name.
266  */
267
268 int set_zephyr_modtime(struct query *q, char *argv[], client *cl)
269 {
270   EXEC SQL BEGIN DECLARE SECTION;
271   char *class, *entity;
272   int who;
273   EXEC SQL END DECLARE SECTION;
274
275   entity = cl->entity;
276   who = cl->client_id;
277
278   class = argv[0];
279
280   EXEC SQL UPDATE zephyr SET modtime = SYSDATE, modby = :who,
281     modwith = :entity WHERE class = :class;
282
283   return MR_SUCCESS;
284 }
285
286
287 /* fixes the modby field.  This will be the second to last thing in the
288  * argv, the argv length is determined from the query structure.  It is
289  * passed as a pointer to an integer.  This will either turn it into a
290  * username, or # + the users_id.
291  */
292 int followup_fix_modby(struct query *q, struct save_queue *sq,
293                        struct validate *v, int (*action)(int, char *[], void *),
294                        void *actarg, client *cl)
295 {
296   int i, j;
297   char **argv;
298   int id, status;
299
300   i = q->vcnt - 2;
301   while (sq_get_data(sq, &argv))
302     {
303       id = atoi(argv[i]);
304       if (id > 0)
305         status = id_to_name(id, USERS_TABLE, &argv[i]);
306       else
307         status = id_to_name(-id, STRINGS_TABLE, &argv[i]);
308       if (status && status != MR_NO_MATCH)
309         return status;
310       (*action)(q->vcnt, argv, actarg);
311       for (j = 0; j < q->vcnt; j++)
312         free(argv[j]);
313       free(argv);
314     }
315   sq_destroy(sq);
316   return MR_SUCCESS;
317 }
318
319
320 /* After retrieving a user account, fix the modby field and signature.
321  * The modby field is the second to last thing in the
322  * argv, the argv length is determined from the query structure.  It is
323  * passed as a pointer to an integer.  This will either turn it into a
324  * username, or # + the users_id.  Only "gua*" queries have a signature,
325  * these are ones with U_END return values.  "gub*" queries also use this
326  * routine but don't have a signature.
327  */
328 int followup_guax(struct query *q, struct save_queue *sq, struct validate *v,
329                   int (*action)(int, char *[], void *), void *actarg,
330                   client *cl)
331 {
332   int i, j;
333   char **argv;
334 #ifdef GDSS
335   unsigned char sigbuf[512];
336   char *kname;
337   SigInfo  si;
338   EXEC SQL BEGIN DECLARE SECTION;
339   int timestamp, who;
340   char *login;
341   char rsig[USERS_SIGNATURE_SIZE];
342   EXEC SQL VAR rsig IS STRING(USERS_SIGNATURE_SIZE);
343   EXEC SQL END DECLARE SECTION;
344 #endif /* GDSS */
345   int id, status;
346
347   i = q->vcnt - 2;
348   while (sq_get_data(sq, &argv))
349     {
350       id = atoi(argv[i]);
351       if (id > 0)
352         status = id_to_name(id, USERS_TABLE, &argv[i]);
353       else
354         status = id_to_name(-id, STRINGS_TABLE, &argv[i]);
355       if (status && status != MR_NO_MATCH)
356         return status;
357 #ifdef GDSS
358       if (q->vcnt == U_END && strlen(argv[U_SIGNATURE]))
359         {
360           login = strtrim(argv[U_NAME]);
361           EXEC SQL SELECT signature, sigdate, sigwho
362             INTO :rsig, :timestamp, :who FROM users
363             WHERE login = :login;
364           if (dbms_errno)
365             return mr_errcode;
366           kname = malloc(0);
367           status = id_to_name(who, STRINGS_TABLE, &kname);
368           si.timestamp = timestamp;
369           si.SigInfoVersion = 0; /* XXXXX this isn't used */
370           kname_parse(si.pname, si.pinst, si.prealm, kname);
371           free(kname);
372           si.rawsig = (unsigned char *)xstrdup(rsig);
373           GDSS_Recompose(&si, sigbuf);
374           free(si.rawsig);
375           free(argv[U_SIGNATURE]);
376           argv[U_SIGNATURE] = xstrdup(sigbuf);
377         }
378 #endif /* GDSS */
379       (*action)(q->vcnt, argv, actarg);
380       for (j = 0; j < q->vcnt; j++)
381         free(argv[j]);
382       free(argv);
383     }
384   sq_destroy(sq);
385   return MR_SUCCESS;
386 }
387
388
389 /**
390  ** followup_ausr - add finger and pobox entries, set_user_modtime
391  **
392  ** Inputs:
393  **     argv[0] - login (add_user)
394  **     argv[3] - last name
395  **     argv[4] - first name
396  **     argv[5] - middle name
397  **
398  **/
399
400 int followup_ausr(struct query *q, char *argv[], client *cl)
401 {
402   EXEC SQL BEGIN DECLARE SECTION;
403   int who, status;
404   char *login, *entity, *name;
405   char fullname[USERS_FIRST_SIZE + USERS_MIDDLE_SIZE + USERS_LAST_SIZE];
406   EXEC SQL END DECLARE SECTION;
407 #ifdef GDSS
408   char databuf[USERS_LOGIN_SIZE + USERS_CLEARID_SIZE];
409   EXEC SQL BEGIN DECLARE SECTION;
410   char rawsig[512];
411   int sigwho, timestamp;
412   EXEC SQL END DECLARE SECTION;
413   SigInfo si;
414 #endif /* GDSS */
415
416   /* build fullname */
417   if (strlen(argv[4]) && strlen(argv[5]))
418     sprintf(fullname, "%s %s %s", argv[4], argv[5], argv[3]);
419   else if (strlen(argv[4]))
420     sprintf(fullname, "%s %s", argv[4], argv[3]);
421   else
422     sprintf(fullname, "%s", argv[3]);
423
424 #ifdef GDSS
425   if (q->vcnt == U_END && *argv[U_SIGNATURE])
426     {
427       sprintf(databuf, "%s:%s", argv[U_NAME], argv[U_MITID]);
428       /* skip bytes for timestamp & kname */
429       si.rawsig = (unsigned char *) rawsig;
430       status = GDSS_Verify(databuf, strlen(databuf), argv[U_SIGNATURE], &si);
431       if (strlen(rawsig) > mr_sig_length)
432         {
433           com_err(whoami, 0, "GDSS signature would be truncated.");
434           return MR_INTERNAL;
435         }
436       if (status == 0)
437         {
438           name = kname_unparse(si.pname, si.pinst, si.prealm);
439           status = name_to_id(name, STRINGS_TABLE, &sigwho);
440           if (status == MR_NO_MATCH)
441             sigwho = add_string(name);
442           else if (status)
443             return status;
444           timestamp = si.timestamp;
445         }
446       else
447         return gdss2et(status);
448     }
449   else
450     {
451       rawsig[0] = '\0';
452       sigwho = 0;
453       timestamp = 0;
454     }
455 #endif /* GDSS */
456
457   login = argv[0];
458   who = cl->client_id;
459   entity = cl->entity;
460
461   /* create finger entry, pobox & set modtime on user */
462 #ifdef GDSS
463   EXEC SQL UPDATE users
464     SET modtime = SYSDATE, modby = :who, modwith = :entity,
465     fullname = NVL(:fullname, CHR(0)), affiliation = type,
466     signature = NVL(:rawsig, CHR(0)), sigdate = :timestamp,
467     sigwho = :sigwho, fmodtime = SYSDATE, fmodby = :who,
468     fmodwith = :entity, potype = 'NONE', pmodtime = SYSDATE,
469     pmodby = :who, pmodwith = :entity
470     WHERE login = :login;
471 #else /* GDSS */
472   EXEC SQL UPDATE users
473     SET modtime = SYSDATE, modby = :who, modwith = :entity,
474     fullname = NVL(:fullname, CHR(0)), affiliation = type,
475     fmodtime = SYSDATE, fmodby = :who, fmodwith = :entity,
476     potype = 'NONE', pmodtime = SYSDATE, pmodby = :who, pmodwith = :entity
477     WHERE login = :login;
478 #endif /* GDSS */
479
480   return MR_SUCCESS;
481 }
482
483
484 /**
485  ** followup_uuac - do signature, set_user_modtime
486  **
487  ** Inputs:
488  **   argv[0] - login (add_user)
489  **   argv[U_SIGNATURE] - sig
490  **
491  **/
492
493 int followup_uuac(struct query *q, char *argv[], client *cl)
494 {
495   EXEC SQL BEGIN DECLARE SECTION;
496   int who, status, id;
497   char *entity, *name;
498   EXEC SQL END DECLARE SECTION;
499 #ifdef GDSS
500   char databuf[USERS_LOGIN_SIZE + USERS_CLEARID_SIZE];
501   EXEC SQL BEGIN DECLARE SECTION;
502   char rawsig[512];
503   char *login;
504   int sigwho, timestamp;
505   EXEC SQL END DECLARE SECTION;
506   SigInfo si;
507 #endif /* GDSS */
508
509   id = *(int *)argv[0];
510   who = cl->client_id;
511   entity = cl->entity;
512
513 #ifdef GDSS
514   if (q->vcnt == U_MODTIME && *argv[U_SIGNATURE + 1])
515     {
516       login = malloc(0);
517       status = id_to_name(id, USERS_TABLE, &login);
518       sprintf(databuf, "%s:%s", login, argv[U_MITID + 1]);
519       free(login);
520       /* skip bytes for timestamp & kname */
521       si.rawsig = (unsigned char *) rawsig;
522       status = GDSS_Verify(databuf, strlen(databuf), argv[U_SIGNATURE + 1],
523                            &si);
524       if (strlen(rawsig) > mr_sig_length)
525         {
526           com_err(whoami, 0, "GDSS signature would be truncated.");
527           return MR_INTERNAL;
528         }
529       if (status == 0)
530         {
531           name = kname_unparse(si.pname, si.pinst, si.prealm);
532           status = name_to_id(name, STRINGS_TABLE, &sigwho);
533           if (status == MR_NO_MATCH)
534             sigwho = add_string(name);
535           else if (status)
536             return status;
537           timestamp = si.timestamp;
538         }
539       else
540         return gdss2et(status);
541     }
542   else
543     {
544       rawsig[0] = '\0';
545       sigwho = 0;
546       timestamp = 0;
547     }
548 #endif /* GDSS */
549
550   /* create finger entry, pobox & set modtime on user */
551
552 #ifdef GDSS
553   EXEC SQL UPDATE users SET modtime = SYSDATE, modby = :who, modwith = :entity,
554     signature = NVL(:rawsig, CHR(0)), sigdate = :timestamp, sigwho = :sigwho
555     WHERE users_id = :id;
556 #else /* GDSS */
557   EXEC SQL UPDATE users SET modtime = SYSDATE, modby = :who, modwith = :entity
558     WHERE users_id = :id;
559 #endif /* GDSS */
560   return MR_SUCCESS;
561 }
562
563
564 /* followup_gpob: fixes argv[2] based on the IDs currently there and the
565  * type in argv[1].  Then completes the upcall to the user.
566  *
567  * argv[2] is of the form "123:234" where the first integer is the
568  * machine ID if it is a pop box or filesys ID if it is an imap box,
569  * and the second is the string ID if it is an SMTP box. argv[1]
570  * should be "POP", "SMTP", "IMAP", or "NONE". Boxes of type NONE are
571  * skipped.
572  */
573
574 int followup_gpob(struct query *q, struct save_queue *sq, struct validate *v,
575                   int (*action)(int, char *[], void *), void *actarg,
576                   client *cl)
577 {
578   char **argv;
579   char *ptype, *p;
580   int mid, sid, status, i;
581
582   /* for each row */
583   while (sq_get_data(sq, &argv))
584     {
585       mr_trim_args(2, argv);
586       ptype = argv[1];
587       p = strchr(argv[2], ':');
588       *p++ = '\0';
589       mid = atoi(argv[2]);
590       sid = atoi(p);
591
592       if (!strcmp(ptype, "POP"))
593         {
594           status = id_to_name(mid, MACHINE_TABLE, &argv[2]);
595           if (status == MR_NO_MATCH)
596             return MR_MACHINE;
597         }
598       else if (!strcmp(ptype, "SMTP"))
599         {
600           status = id_to_name(sid, STRINGS_TABLE, &argv[2]);
601           if (status == MR_NO_MATCH)
602             return MR_STRING;
603         }
604       else if (!strcmp(ptype, "IMAP"))
605         {
606           status = id_to_name(mid, FILESYS_TABLE, &argv[2]);
607           if (status == MR_NO_MATCH)
608             return MR_FILESYS;
609         }
610       else /* ptype == "NONE" */
611         goto skip;
612       if (status)
613         return status;
614
615       if (!strcmp(q->shortname, "gpob"))
616         {
617           sid = atoi(argv[4]);
618           if (sid > 0)
619             status = id_to_name(sid, USERS_TABLE, &argv[4]);
620           else
621             status = id_to_name(-sid, STRINGS_TABLE, &argv[4]);
622         }
623       if (status && status != MR_NO_MATCH)
624         return status;
625
626       (*action)(q->vcnt, argv, actarg);
627     skip:
628       /* free saved data */
629       for (i = 0; i < q->vcnt; i++)
630         free(argv[i]);
631       free(argv);
632     }
633
634   sq_destroy(sq);
635   return MR_SUCCESS;
636 }
637
638
639 /* followup_gsnt: fix the ace_name in argv[7].  argv[6] will contain the
640  * ace_type: "LIST", "USER", or "NONE".  Decode the id in argv[7] into the
641  * proper name based on the type, and repace that string in the argv.
642  * Also fixes the modby field by called followup_fix_modby.
643  */
644
645 int followup_gsnt(struct query *q, struct save_queue *sq, struct validate *v,
646                   int (*action)(int, char *[], void *), void *actarg,
647                   client *cl)
648 {
649   char **argv, *type;
650   int id, i, idx, status;
651
652   idx = 8;
653
654   while (sq_get_data(sq, &argv))
655     {
656       mr_trim_args(q->vcnt, argv);
657
658       id = atoi(argv[i = q->vcnt - 2]);
659       if (id > 0)
660         status = id_to_name(id, USERS_TABLE, &argv[i]);
661       else
662         status = id_to_name(-id, STRINGS_TABLE, &argv[i]);
663       if (status && status != MR_NO_MATCH)
664         return status;
665
666       id = atoi(argv[idx]);
667       type = argv[idx - 1];
668
669       if (!strcmp(type, "LIST"))
670         status = id_to_name(id, LIST_TABLE, &argv[idx]);
671       else if (!strcmp(type, "USER"))
672         status = id_to_name(id, USERS_TABLE, &argv[idx]);
673       else if (!strcmp(type, "KERBEROS"))
674         status = id_to_name(id, STRINGS_TABLE, &argv[idx]);
675       else if (!strcmp(type, "NONE"))
676         {
677           status = 0;
678           free(argv[idx]);
679           argv[idx] = xstrdup("NONE");
680         }
681       else
682         {
683           status = 0;
684           free(argv[idx]);
685           argv[idx] = xstrdup("???");
686         }
687       if (status && status != MR_NO_MATCH)
688         return status;
689
690       /* send the data */
691       (*action)(q->vcnt, argv, actarg);
692
693       /* free saved data */
694       for (i = 0; i < q->vcnt; i++)
695         free(argv[i]);
696       free(argv);
697     }
698
699   sq_destroy(sq);
700   return MR_SUCCESS;
701 }
702
703
704 /* followup_ghst: fix the ace_name in argv[12].  argv[11] will contain the
705  * ace_type: "LIST", "USER", or "NONE".  Decode the id in argv[12] into the
706  * proper name based on the type, and repace that string in the argv.
707  * Also fixes the modby field by called followup_fix_modby.
708  */
709
710 int followup_ghst(struct query *q, struct save_queue *sq, struct validate *v,
711                   int (*action)(int, char *[], void *), void *actarg,
712                   client *cl)
713 {
714   char **argv, *type;
715   int id, i, idx, status;
716
717   while (sq_get_data(sq, &argv))
718     {
719       mr_trim_args(q->vcnt, argv);
720
721       id = atoi(argv[i = q->vcnt - 2]);
722       if (id > 0)
723         status = id_to_name(id, USERS_TABLE, &argv[i]);
724       else
725         status = id_to_name(-id, STRINGS_TABLE, &argv[i]);
726       if (status && status != MR_NO_MATCH)
727         return status;
728
729       id = atoi(argv[13]);
730       status = id_to_name(id, STRINGS_TABLE, &argv[13]);
731       if (status)
732         return status;
733       id = atoi(argv[14]);
734       status = id_to_name(id, STRINGS_TABLE, &argv[14]);
735       if (status)
736         return status;
737       id = atoi(argv[16]);
738       if (id < 0)
739         status = id_to_name(-id, STRINGS_TABLE, &argv[16]);
740       else
741         status = id_to_name(id, USERS_TABLE, &argv[16]);
742       if (status && status != MR_NO_MATCH)
743         return status;
744
745       idx = 12;
746       id = atoi(argv[idx]);
747       type = strtrim(argv[idx - 1]);
748
749       if (!strcmp(type, "LIST"))
750         status = id_to_name(id, LIST_TABLE, &argv[idx]);
751       else if (!strcmp(type, "USER"))
752         status = id_to_name(id, USERS_TABLE, &argv[idx]);
753       else if (!strcmp(type, "KERBEROS"))
754         status = id_to_name(id, STRINGS_TABLE, &argv[idx]);
755       else if (!strcmp(type, "NONE"))
756         {
757           status = 0;
758           free(argv[idx]);
759           argv[idx] = xstrdup("NONE");
760         }
761       else
762         {
763           status = 0;
764           free(argv[idx]);
765           argv[idx] = xstrdup("???");
766         }
767       if (status && status != MR_NO_MATCH)
768         return status;
769
770       /* send the data */
771       (*action)(q->vcnt, argv, actarg);
772
773       /* free saved data */
774       for (i = 0; i < q->vcnt; i++)
775         free(argv[i]);
776       free(argv);
777     }
778
779   sq_destroy(sq);
780   return MR_SUCCESS;
781 }
782
783
784 /* followup_glin: fix the ace_name in argv[8].  argv[7] will contain the
785  * ace_type: "LIST", "USER", or "NONE".  Decode the id in argv[8] into the
786  * proper name based on the type, and repace that string in the argv.
787  * Also fixes the modby field by called followup_fix_modby.
788  */
789
790 int followup_glin(struct query *q, struct save_queue *sq, struct validate *v,
791                   int (*action)(int, char *[], void *), void *actarg,
792                   client *cl)
793 {
794   char **argv, *type;
795   int id, i, idx, status;
796
797   idx = 8;
798   if (!strcmp(q->shortname, "gsin"))
799     idx = 12;
800
801   while (sq_get_data(sq, &argv))
802     {
803       mr_trim_args(q->vcnt, argv);
804
805       id = atoi(argv[i = q->vcnt - 2]);
806       if (id > 0)
807         status = id_to_name(id, USERS_TABLE, &argv[i]);
808       else
809         status = id_to_name(-id, STRINGS_TABLE, &argv[i]);
810       if (status && status != MR_NO_MATCH)
811         return status;
812
813       id = atoi(argv[idx]);
814       type = argv[idx - 1];
815
816       if (!strcmp(type, "LIST"))
817         status = id_to_name(id, LIST_TABLE, &argv[idx]);
818       else if (!strcmp(type, "USER"))
819         status = id_to_name(id, USERS_TABLE, &argv[idx]);
820       else if (!strcmp(type, "KERBEROS"))
821         status = id_to_name(id, STRINGS_TABLE, &argv[idx]);
822       else if (!strcmp(type, "NONE"))
823         {
824           status = 0;
825           free(argv[idx]);
826           argv[idx] = xstrdup("NONE");
827         }
828       else
829         {
830           status = 0;
831           free(argv[idx]);
832           argv[idx] = xstrdup("???");
833         }
834       if (status && status != MR_NO_MATCH)
835         return status;
836
837       if (!strcmp(q->shortname, "glin") && atoi(argv[6]) == -1)
838         {
839           argv[6] = xrealloc(argv[6], strlen(UNIQUE_GID) + 1);
840           strcpy(argv[6], UNIQUE_GID);
841         }
842
843       /* send the data */
844       (*action)(q->vcnt, argv, actarg);
845
846       /* free saved data */
847       for (i = 0; i < q->vcnt; i++)
848         free(argv[i]);
849       free(argv);
850     }
851
852   sq_destroy(sq);
853   return MR_SUCCESS;
854 }
855
856 int followup_gpsv(struct query *q, struct save_queue *sq, struct validate *v,
857                   int (*action)(int, char *[], void *), void *actarg,
858                   client *cl)
859 {
860   char **argv, *type;
861   int id, i, status;
862
863   while (sq_get_data(sq, &argv))
864     {
865       mr_trim_args(q->vcnt, argv);
866
867       id = atoi(argv[PRINTSERVER_OWNER_NAME]);
868       type = argv[PRINTSERVER_OWNER_TYPE];
869
870       if (!strcmp(type, "LIST"))
871         status = id_to_name(id, LIST_TABLE, &argv[PRINTSERVER_OWNER_NAME]);
872       else if (!strcmp(type, "USER"))
873         status = id_to_name(id, USERS_TABLE, &argv[PRINTSERVER_OWNER_NAME]);
874       else if (!strcmp(type, "KERBEROS"))
875         status = id_to_name(id, STRINGS_TABLE, &argv[PRINTSERVER_OWNER_NAME]);
876       else
877         {
878           status = 0;
879           free(argv[PRINTSERVER_OWNER_NAME]);
880           argv[PRINTSERVER_OWNER_NAME] = xstrdup("NONE");
881         }
882       if (status && status != MR_NO_MATCH)
883         return status;
884     }
885
886   return followup_fix_modby(q, sq, v, action, actarg, cl);
887 }
888   
889
890 /* followup_gqot: Fix the entity name, directory name & modby fields
891  *   argv[0] = filsys_id
892  *   argv[1] = type
893  *   argv[2] = entity_id
894  *   argv[3] = ascii(quota)
895  */
896
897 int followup_gqot(struct query *q, struct save_queue *sq, struct validate *v,
898                   int (*action)(int, char *[], void *), void *actarg,
899                   client *cl)
900 {
901   int j;
902   char **argv;
903   EXEC SQL BEGIN DECLARE SECTION;
904   int id;
905   char *name, *label;
906   EXEC SQL END DECLARE SECTION;
907   int status, idx;
908
909   if (!strcmp(q->name, "get_quota") ||
910       !strcmp(q->name, "get_quota_by_filesys"))
911     idx = 4;
912   else
913     idx = 3;
914   while (sq_get_data(sq, &argv))
915     {
916       if (idx == 4)
917         {
918           switch (argv[1][0])
919             {
920             case 'U':
921               status = id_to_name(atoi(argv[2]), USERS_TABLE, &argv[2]);
922               break;
923             case 'G':
924             case 'L':
925               status = id_to_name(atoi(argv[2]), LIST_TABLE, &argv[2]);
926               break;
927             case 'A':
928               free(argv[2]);
929               argv[2] = xstrdup("system:anyuser");
930               break;
931             default:
932               id = atoi(argv[2]);
933               argv[2] = xmalloc(8);
934               sprintf(argv[2], "%d", id);
935             }
936         }
937       id = atoi(argv[idx]);
938       free(argv[idx]);
939       argv[idx] = xmalloc(id ? NFSPHYS_DIR_SIZE : FILESYS_NAME_SIZE);
940       name = argv[idx];
941       name[0] = '\0';
942       if (id == 0)
943         {
944           label = argv[0];
945           EXEC SQL SELECT name INTO :name FROM filesys
946             WHERE label = :label;
947         }
948       else
949         {
950           EXEC SQL SELECT dir INTO :name FROM nfsphys
951             WHERE nfsphys_id = :id;
952         }
953       if (sqlca.sqlerrd[2] != 1)
954         sprintf(argv[idx], "#%d", id);
955
956       id = atoi(argv[idx + 3]);
957       if (id > 0)
958         status = id_to_name(id, USERS_TABLE, &argv[idx + 3]);
959       else
960         status = id_to_name(-id, STRINGS_TABLE, &argv[idx + 3]);
961       if (status && status != MR_NO_MATCH)
962         return status;
963       (*action)(q->vcnt, argv, actarg);
964       for (j = 0; j < q->vcnt; j++)
965         free(argv[j]);
966       free(argv);
967     }
968   sq_destroy(sq);
969   return MR_SUCCESS;
970 }
971
972
973 /* followup_aqot: Add allocation to nfsphys after creating quota.
974  *   argv[0] = filsys_id
975  *   argv[1] = type if "add_quota" or "update_quota"
976  *   argv[2 or 1] = id
977  *   argv[3 or 2] = ascii(quota)
978  */
979
980 int followup_aqot(struct query *q, char *argv[], client *cl)
981 {
982   EXEC SQL BEGIN DECLARE SECTION;
983   int quota, id, fs, who, physid, table;
984   char *entity, *qtype, *tname;
985   EXEC SQL END DECLARE SECTION;
986   char incr_qual[60];
987   char *incr_argv[2];
988   int status;
989
990   table = q->rtable;
991   tname = table_name[table];
992   fs = *(int *)argv[0];
993   EXEC SQL SELECT phys_id INTO :physid FROM filesys
994     WHERE filsys_id = :fs;
995   if (dbms_errno)
996     return mr_errcode;
997
998   if (!strcmp(q->shortname, "aqot") || !strcmp(q->shortname, "uqot"))
999     {
1000       qtype = argv[1];
1001       id = *(int *)argv[2];
1002       quota = atoi(argv[3]);
1003       sprintf(incr_qual, "q.filsys_id = %d", fs);
1004     }
1005   else
1006     {
1007       qtype = "USER";
1008       id = *(int *)argv[1];
1009       quota = atoi(argv[2]);
1010       sprintf(incr_qual, "q.filsys_id = %d AND q.type = '%s' AND "
1011               "q.entity_id = %d", fs, qtype, id);
1012     }
1013
1014   /* quota case of incremental_{before|after} only looks at slot 1 */
1015   incr_argv[1] = qtype;
1016
1017   /* Follows one of many possible gross hacks to fix these particular
1018    * conflicts between what is possible in the query table and what
1019    * is possible in SQL.
1020    */
1021   if (q->type == APPEND)
1022     {
1023       incremental_clear_before();
1024       EXEC SQL INSERT INTO quota
1025         (filsys_id, type, entity_id, quota, phys_id)
1026         VALUES (:fs, NVL(:qtype, CHR(0)), :id, :quota, :physid);
1027       incremental_after(table, incr_qual, incr_argv);
1028     }
1029   else
1030     {
1031       incremental_before(table, incr_qual, incr_argv);
1032       EXEC SQL UPDATE quota SET quota = :quota
1033         WHERE filsys_id = :fs AND type = :qtype AND entity_id = :id;
1034       status = mr_errcode;
1035       incremental_after(table, incr_qual, incr_argv);
1036     }
1037
1038   if (dbms_errno)
1039     return mr_errcode;
1040   flush_name(argv[0], table);
1041   if (q->type == APPEND)
1042     {
1043       EXEC SQL UPDATE tblstats SET appends = appends + 1, modtime = SYSDATE
1044         WHERE table_name = :tname;
1045     }
1046   else
1047     {
1048       EXEC SQL UPDATE tblstats SET updates = updates + 1, modtime = SYSDATE
1049         WHERE table_name = :tname;
1050     }
1051
1052   /* Proceed with original followup */
1053   who = cl->client_id;
1054   entity = cl->entity;
1055
1056   EXEC SQL UPDATE quota
1057     SET modtime = SYSDATE, modby = :who, modwith = :entity
1058     WHERE filsys_id = :fs and type = :qtype and entity_id = :id;
1059   EXEC SQL UPDATE nfsphys SET allocated = allocated + :quota
1060     WHERE nfsphys_id = :physid;
1061   if (dbms_errno)
1062     return mr_errcode;
1063   return MR_SUCCESS;
1064 }
1065
1066
1067 /* Necessitated by the requirement of a correlation name by the incremental
1068  * routines, since query table deletes don't provide one.
1069  */
1070 int followup_dqot(struct query *q, char **argv, client *cl)
1071 {
1072   char *qtype;
1073   int id, fs, table;
1074   char *incr_argv[2];
1075   EXEC SQL BEGIN DECLARE SECTION;
1076   char incr_qual[80], *tname;
1077   EXEC SQL END DECLARE SECTION;
1078
1079   table = q->rtable;
1080   tname = table_name[table];
1081   fs = *(int *)argv[0];
1082   if (!strcmp(q->shortname, "dqot"))
1083     {
1084       qtype = argv[1];
1085       id = *(int *)argv[2];
1086     }
1087   else
1088     {
1089       qtype = "USER";
1090       id = *(int *)argv[1];
1091     }
1092   sprintf(incr_qual, "q.filsys_id = %d AND q.type = '%s' AND q.entity_id = %d",
1093           fs, qtype, id);
1094
1095   /* quota case of incremental_{before|after} only looks at slot 1 */
1096   incr_argv[1] = qtype;
1097
1098   incremental_before(table, incr_qual, incr_argv);
1099   EXEC SQL DELETE FROM quota q WHERE q.filsys_id = :fs AND q.type = :qtype
1100     AND q.entity_id = :id;
1101   incremental_clear_after();
1102
1103   if (dbms_errno)
1104     return mr_errcode;
1105   flush_name(argv[0], table);
1106
1107   EXEC SQL UPDATE tblstats SET deletes = deletes + 1, modtime = SYSDATE
1108     WHERE table_name = :tname;
1109   return MR_SUCCESS;
1110 }
1111
1112 /* followup_gzcl:
1113  */
1114
1115 int followup_gzcl(struct query *q, struct save_queue *sq, struct validate *v,
1116                   int (*action)(int, char *[], void *), void *actarg,
1117                   client *cl)
1118 {
1119   int id, i, status;
1120   char **argv;
1121
1122   while (sq_get_data(sq, &argv))
1123     {
1124       mr_trim_args(q->vcnt, argv);
1125
1126       id = atoi(argv[i = q->vcnt - 2]);
1127       if (id > 0)
1128         status = id_to_name(id, USERS_TABLE, &argv[i]);
1129       else
1130         status = id_to_name(-id, STRINGS_TABLE, &argv[i]);
1131       if (status && status != MR_NO_MATCH)
1132         return status;
1133
1134       for (i = 1; i < 8; i += 2)
1135         {
1136           id = atoi(argv[i + 1]);
1137           if (!strcmp(argv[i], "LIST"))
1138             status = id_to_name(id, LIST_TABLE, &argv[i + 1]);
1139           else if (!strcmp(argv[i], "USER"))
1140             status = id_to_name(id, USERS_TABLE, &argv[i + 1]);
1141           else if (!strcmp(argv[i], "KERBEROS"))
1142             status = id_to_name(id, STRINGS_TABLE, &argv[i + 1]);
1143           else if (!strcmp(argv[i], "NONE"))
1144             {
1145               status = 0;
1146               free(argv[i + 1]);
1147               argv[i + 1] = xstrdup("NONE");
1148             }
1149           else
1150             {
1151               status = 0;
1152               free(argv[i + 1]);
1153               argv[i + 1] = xstrdup("???");
1154             }
1155           if (status && status != MR_NO_MATCH)
1156             return status;
1157         }
1158
1159       /* send the data */
1160       (*action)(q->vcnt, argv, actarg);
1161
1162       /* free saved data */
1163       for (i = 0; i < q->vcnt; i++)
1164         free(argv[i]);
1165       free(argv);
1166     }
1167   sq_destroy(sq);
1168   return MR_SUCCESS;
1169 }
1170
1171
1172 /* followup_gsha:
1173  */
1174
1175 int followup_gsha(struct query *q, struct save_queue *sq, struct validate *v,
1176                   int (*action)(int, char *[], void *), void *actarg,
1177                   client *cl)
1178 {
1179   char **argv;
1180   int i, id, status;
1181
1182   while (sq_get_data(sq, &argv))
1183     {
1184       mr_trim_args(q->vcnt, argv);
1185
1186       id = atoi(argv[4]);
1187       if (id > 0)
1188         status = id_to_name(id, USERS_TABLE, &argv[4]);
1189       else
1190         status = id_to_name(-id, STRINGS_TABLE, &argv[4]);
1191       if (status && status != MR_NO_MATCH)
1192         return status;
1193
1194       id = atoi(argv[2]);
1195       if (!strcmp(argv[1], "LIST"))
1196         status = id_to_name(id, LIST_TABLE, &argv[2]);
1197       else if (!strcmp(argv[1], "USER"))
1198         status = id_to_name(id, USERS_TABLE, &argv[2]);
1199       else if (!strcmp(argv[1], "KERBEROS"))
1200         status = id_to_name(id, STRINGS_TABLE, &argv[2]);
1201       else if (!strcmp(argv[1], "NONE"))
1202         {
1203           status = 0;
1204           free(argv[2]);
1205           argv[2] = xstrdup("NONE");
1206         }
1207       else
1208         {
1209           status = 0;
1210           free(argv[2]);
1211           argv[2] = xstrdup("???");
1212         }
1213       if (status && status != MR_NO_MATCH)
1214         return status;
1215
1216       /* send the data */
1217       (*action)(q->vcnt, argv, actarg);
1218
1219       /* free saved data */
1220       for (i = 0; i < q->vcnt; i++)
1221         free(argv[i]);
1222       free(argv);
1223     }
1224   sq_destroy(sq);
1225   return MR_SUCCESS;
1226 }
1227
1228
1229 int _sdl_followup(struct query *q, char *argv[], client *cl)
1230 {
1231   if (atoi(argv[0]))
1232     EXEC SQL ALTER SESSION SET SQL_TRACE TRUE;
1233   else
1234     EXEC SQL ALTER SESSION SET SQL_TRACE FALSE;
1235
1236   return MR_SUCCESS;
1237 }
1238
1239
1240 int trigger_dcm(struct query *q, char *argv[], client *cl)
1241 {
1242   pid_t pid;
1243   char prog[MAXPATHLEN];
1244
1245   sprintf(prog, "%s/startdcm", BIN_DIR);
1246   pid = vfork();
1247   switch (pid)
1248     {
1249     case 0:
1250       execl(prog, "startdcm", 0);
1251       exit(1);
1252
1253     case -1:
1254       return errno;
1255
1256     default:
1257       return MR_SUCCESS;
1258     }
1259 }
This page took 0.138066 seconds and 5 git commands to generate.