source: trunk/third/moira/server/qfollow.pc @ 23178

Revision 23178, 25.3 KB checked in by broder, 16 years ago (diff)
Take a new snapshot from CVS for Moira, and add a debathena-moira-update-server package
Line 
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
21EXEC SQL INCLUDE sqlca;
22
23RCSID("$Header$");
24
25extern char *whoami, *table_name[];
26extern int dbms_errno, mr_errcode;
27
28EXEC SQL BEGIN DECLARE SECTION;
29extern char stmt_buf[];
30EXEC SQL END DECLARE SECTION;
31
32EXEC SQL WHENEVER SQLERROR DO dbmserr();
33
34
35/* FOLLOWUP ROUTINES */
36
37/* generic set_modtime routine.  This takes the table id from the query,
38 * and will update the modtime, modby, and modwho fields in the entry in
39 * the table whose name field matches argv[0].
40 */
41
42int set_modtime(struct query *q, char *argv[], client *cl)
43{
44  char *name, *entity, *table;
45  int who;
46
47  entity = cl->entity;
48  who = cl->client_id;
49  table = table_name[q->rtable];
50  name = argv[0];
51
52  sprintf(stmt_buf, "UPDATE %s SET modtime = SYSDATE, modby = %d, "
53          "modwith = '%s' WHERE name = '%s'", table, who, entity, name);
54  EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
55
56  return MR_SUCCESS;
57}
58
59/* generic set_modtime_by_id routine.  This takes the table id from
60 * the query, and the id name from the validate record,
61 * and will update the modtime, modby, and modwho fields in the entry in
62 * the table whose id matches argv[0].
63 */
64
65int set_modtime_by_id(struct query *q, char *argv[], client *cl)
66{
67  char *entity, *table, *id_name;
68  int who, id;
69
70  entity = cl->entity;
71  who = cl->client_id;
72  table = table_name[q->rtable];
73  id_name = q->validate->object_id;
74
75  id = *(int *)argv[0];
76  sprintf(stmt_buf, "UPDATE %s SET modtime = SYSDATE, modby = %d, "
77          "modwith = '%s' WHERE %s = %d", table, who, entity, id_name, id);
78  EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
79  return MR_SUCCESS;
80}
81
82
83/* Sets the finger modtime on a user record.  The users_id will be in argv[0].
84 */
85
86int set_finger_modtime(struct query *q, char *argv[], client *cl)
87{
88  EXEC SQL BEGIN DECLARE SECTION;
89  int users_id, who;
90  char *entity;
91  EXEC SQL END DECLARE SECTION;
92
93  entity = cl->entity;
94  who = cl->client_id;
95  users_id = *(int *)argv[0];
96
97  EXEC SQL UPDATE users SET fmodtime = SYSDATE, fmodby = :who,
98    fmodwith = :entity WHERE users_id = :users_id;
99
100  return MR_SUCCESS;
101}
102
103
104/* Sets the pobox modtime on a user record.  The users_id will be in argv[0].
105 */
106
107int set_pobox_modtime(struct query *q, char *argv[], client *cl)
108{
109  EXEC SQL BEGIN DECLARE SECTION;
110  int users_id, who;
111  char *entity;
112  EXEC SQL END DECLARE SECTION;
113
114  entity = cl->entity;
115  who = cl->client_id;
116  users_id = *(int *)argv[0];
117
118  EXEC SQL UPDATE users SET pmodtime = SYSDATE, pmodby = :who,
119    pmodwith = :entity WHERE users_id = :users_id;
120
121  return MR_SUCCESS;
122}
123
124
125/* Like set_modtime, but uppercases the name first.
126 */
127
128int set_uppercase_modtime(struct query *q, char *argv[], client *cl)
129{
130  char *name, *entity, *table;
131  int who;
132
133  entity = cl->entity;
134  who = cl->client_id;
135  table = table_name[q->rtable];
136  name = argv[0];
137
138  sprintf(stmt_buf, "UPDATE %s SET modtime = SYSDATE, modby = %d, "
139          "modwith = '%s' WHERE name = UPPER('%s')", table, who, entity, name);
140  EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
141
142  return MR_SUCCESS;
143}
144
145
146/* Sets the modtime on the machine whose mach_id is in argv[0].  This routine
147 * is necessary for add_machine_to_cluster becuase the table that query
148 * operates on is "mcm", not "machine".
149 */
150
151int set_mach_modtime_by_id(struct query *q, char *argv[], client *cl)
152{
153  EXEC SQL BEGIN DECLARE SECTION;
154  char *entity;
155  int who, id;
156  EXEC SQL END DECLARE SECTION;
157
158  entity = cl->entity;
159  who = cl->client_id;
160  id = *(int *)argv[0];
161  EXEC SQL UPDATE machine SET modtime = SYSDATE, modby = :who,
162    modwith = :entity WHERE mach_id = :id;
163
164  return MR_SUCCESS;
165}
166
167
168/* Sets the modtime on the cluster whose mach_id is in argv[0].  This routine
169 * is necessary for add_cluster_data and delete_cluster_data becuase the
170 * table that query operates on is "svc", not "cluster".
171 */
172
173int set_cluster_modtime_by_id(struct query *q, char *argv[], client *cl)
174{
175  EXEC SQL BEGIN DECLARE SECTION;
176  char *entity;
177  int who, id;
178  EXEC SQL END DECLARE SECTION;
179
180  entity = cl->entity;
181  who = cl->client_id;
182
183  id = *(int *)argv[0];
184  EXEC SQL UPDATE clusters SET modtime = SYSDATE, modby = :who,
185    modwith = :entity WHERE clu_id = :id;
186  return MR_SUCCESS;
187}
188
189
190/* sets the modtime on the serverhost where the service name is in argv[0]
191 * and the mach_id is in argv[1].
192 */
193
194int set_serverhost_modtime(struct query *q, char *argv[], client *cl)
195{
196  EXEC SQL BEGIN DECLARE SECTION;
197  char *entity, *serv;
198  int who, id;
199  EXEC SQL END DECLARE SECTION;
200
201  entity = cl->entity;
202  who = cl->client_id;
203
204  serv = argv[0];
205  id = *(int *)argv[1];
206  EXEC SQL UPDATE serverhosts
207    SET modtime = SYSDATE, modby = :who, modwith = :entity
208    WHERE service = :serv AND mach_id = :id;
209  return MR_SUCCESS;
210}
211
212
213/* sets the modtime on the nfsphys where the mach_id is in argv[0] and the
214 * directory name is in argv[1].
215 */
216
217int set_nfsphys_modtime(struct query *q, char *argv[], client *cl)
218{
219  EXEC SQL BEGIN DECLARE SECTION;
220  char *entity, *dir;
221  int who, id;
222  EXEC SQL END DECLARE SECTION;
223
224  entity = cl->entity;
225  who = cl->client_id;
226
227  id = *(int *)argv[0];
228  dir = argv[1];
229  EXEC SQL UPDATE nfsphys SET modtime = SYSDATE, modby = :who,
230    modwith = :entity WHERE dir = :dir AND mach_id = :id;
231  return MR_SUCCESS;
232}
233
234
235/* sets the modtime on a filesystem, where argv[0] contains the filesys
236 * label.
237 */
238
239int set_filesys_modtime(struct query *q, char *argv[], client *cl)
240{
241  EXEC SQL BEGIN DECLARE SECTION;
242  char *label, *entity;
243  int who;
244  extern int _var_phys_id;
245  EXEC SQL END DECLARE SECTION;
246
247  entity = cl->entity;
248  who = cl->client_id;
249
250  label = argv[0];
251  if (!strcmp(q->shortname, "ufil"))
252    label = argv[1];
253
254  EXEC SQL UPDATE filesys SET modtime = SYSDATE, modby = :who,
255    modwith = :entity, phys_id = :_var_phys_id
256    WHERE label = :label;
257  return MR_SUCCESS;
258}
259
260
261/* sets the modtime on a zephyr class, where argv[0] contains the class
262 * name.
263 */
264
265int set_zephyr_modtime(struct query *q, char *argv[], client *cl)
266{
267  EXEC SQL BEGIN DECLARE SECTION;
268  char *class, *entity;
269  int who;
270  EXEC SQL END DECLARE SECTION;
271
272  entity = cl->entity;
273  who = cl->client_id;
274
275  class = argv[0];
276
277  EXEC SQL UPDATE zephyr SET modtime = SYSDATE, modby = :who,
278    modwith = :entity WHERE class = :class;
279
280  return MR_SUCCESS;
281}
282
283/* sets the modtime on an entry in services table, where argv[0] contains
284 * the service name.
285 */
286
287int set_service_modtime(struct query *q, char *argv[], client *cl)
288{
289  EXEC SQL BEGIN DECLARE SECTION;
290  char *service, *protocol, *entity;
291  int who;
292  EXEC SQL END DECLARE SECTION;
293
294  entity = cl->entity;
295  who = cl->client_id;
296
297  service = argv[0];
298  protocol = argv[1];
299
300  EXEC SQL UPDATE services SET modtime = SYSDATE, modby = :who,
301    modwith = :entity WHERE name = :service AND protocol = :protocol;
302
303  return MR_SUCCESS;
304}
305
306/* fixes the modby field.  This will be the second to last thing in the
307 * argv, the argv length is determined from the query structure.  It is
308 * passed as a pointer to an integer.  This will either turn it into a
309 * username, or # + the users_id.
310 */
311int followup_fix_modby(struct query *q, struct save_queue *sq,
312                       struct validate *v, int (*action)(int, char *[], void *),
313                       void *actarg, client *cl)
314{
315  int i, j;
316  char **argv;
317  int id, status;
318
319  i = q->vcnt - 2;
320  while (sq_get_data(sq, &argv))
321    {
322      id = atoi(argv[i]);
323      if (id > 0)
324        status = id_to_name(id, USERS_TABLE, &argv[i]);
325      else
326        status = id_to_name(-id, STRINGS_TABLE, &argv[i]);
327      if (status && status != MR_NO_MATCH)
328        return status;
329      (*action)(q->vcnt, argv, actarg);
330      for (j = 0; j < q->vcnt; j++)
331        free(argv[j]);
332      free(argv);
333    }
334  sq_destroy(sq);
335  return MR_SUCCESS;
336}
337
338/**
339 ** followup_ausr - add finger and pobox entries, set_user_modtime
340 **
341 ** Inputs:
342 **     argv[0] - login (add_user)
343 **     argv[U_LAST] - last name
344 **     argv[U_FIRST] - first name
345 **     argv[U_MIDDLE] - middle name
346 **
347 **/
348
349int followup_ausr(struct query *q, char *argv[], client *cl)
350{
351  EXEC SQL BEGIN DECLARE SECTION;
352  int who, status;
353  char *login, *entity, *name;
354  char fullname[USERS_FIRST_SIZE + USERS_MIDDLE_SIZE + USERS_LAST_SIZE];
355  EXEC SQL END DECLARE SECTION;
356
357  /* build fullname */
358  if (strlen(argv[U_FIRST]) && strlen(argv[U_MIDDLE]))
359    sprintf(fullname, "%s %s %s", argv[U_FIRST], argv[U_MIDDLE],
360            argv[U_LAST]);
361  else if (strlen(argv[U_FIRST]))
362    sprintf(fullname, "%s %s", argv[U_FIRST], argv[U_LAST]);
363  else
364    sprintf(fullname, "%s", argv[U_LAST]);
365
366  login = argv[0];
367  who = cl->client_id;
368  entity = cl->entity;
369
370  /* create finger entry, pobox & set modtime on user */
371  EXEC SQL UPDATE users
372    SET modtime = SYSDATE, modby = :who, modwith = :entity,
373    fullname = NVL(:fullname, CHR(0)), affiliation = type,
374    fmodtime = SYSDATE, fmodby = :who, fmodwith = :entity,
375    potype = 'NONE', pmodtime = SYSDATE, pmodby = :who, pmodwith = :entity
376    WHERE login = :login;
377
378  return MR_SUCCESS;
379}
380
381/* followup_gpob: fixes argv[2] and argv[3] based on the pobox type.
382 * Then completes the upcall to the user.
383 *
384 * argv[2] is the users_id on input and should be converted to the
385 * pobox name on output. argv[3] is empty on input and should be
386 * converted to an email address on output.
387 */
388
389int followup_gpob(struct query *q, struct save_queue *sq, struct validate *v,
390                  int (*action)(int, char *[], void *), void *actarg,
391                  client *cl)
392{
393  char **argv;
394  char *ptype, *p;
395  int mid, sid, status, i;
396  EXEC SQL BEGIN DECLARE SECTION;
397  int users_id, pid, iid, bid, eid;
398  char mach[MACHINE_NAME_SIZE], fs[FILESYS_LABEL_SIZE];
399  char str[STRINGS_STRING_SIZE];
400  EXEC SQL END DECLARE SECTION;
401
402  /* for each row */
403  while (sq_get_data(sq, &argv))
404    {
405      mr_trim_args(4, argv);
406      ptype = argv[1];
407      users_id = atoi(argv[2]);
408
409      EXEC SQL SELECT pop_id, imap_id, box_id, exchange_id INTO :pid, :iid, :bid, :eid
410        FROM users WHERE users_id = :users_id;
411      if (sqlca.sqlcode)
412        return MR_USER;
413
414      if (ptype[0] == 'S')
415        {
416          /* SMTP or SPLIT */
417          EXEC SQL SELECT string INTO :str FROM strings
418            WHERE string_id = :bid;
419          if (sqlca.sqlcode)
420            return MR_STRING;
421
422          /* If SMTP, don't bother fetching IMAP and POP boxes. */
423          if (ptype[1] == 'M')
424            pid = iid = eid = 0;
425        }
426      if (iid)
427        {
428          /* IMAP, or SPLIT with IMAP */
429          EXEC SQL SELECT f.label, m.name INTO :fs, :mach
430            FROM filesys f, machine m
431            WHERE f.filsys_id = :iid AND f.mach_id = m.mach_id;
432          if (sqlca.sqlcode)
433            return MR_FILESYS;
434        }
435      if (pid)
436        {
437          /* POP, or SPLIT with POP */
438          EXEC SQL SELECT m.name INTO :mach FROM machine m, users u
439            WHERE u.users_id = :users_id AND u.pop_id = m.mach_id;
440          if (sqlca.sqlcode)
441            return MR_MACHINE;
442        }
443      if (eid)
444        {
445          /* EXCHANGE, or SPLIT with EXCHANGE */
446          EXEC SQL SELECT m.name INTO :mach FROM machine m, users u
447            WHERE u.users_id = :users_id AND u.exchange_id = m.mach_id;
448          if (sqlca.sqlcode)
449            return MR_MACHINE;
450        }
451
452      free(argv[2]);
453      free(argv[3]);
454
455      /* Now assemble the right answer. */
456      if (!strcmp(ptype, "POP") || !strcmp(ptype, "EXCHANGE"))
457        {
458          argv[2] = xstrdup(strtrim(mach));
459          argv[3] = xmalloc(strlen(argv[0]) + strlen(argv[2]) + 2);
460          sprintf(argv[3], "%s@%s", argv[0], argv[2]);
461        }
462      else if (!strcmp(ptype, "SMTP"))
463        {
464          argv[2] = xstrdup(strtrim(str));
465          argv[3] = xstrdup(str);
466        }
467      else if (!strcmp(ptype, "IMAP"))
468        {
469          argv[2] = xstrdup(strtrim(fs));
470          argv[3] = xmalloc(strlen(argv[0]) + strlen(strtrim(mach)) + 2);
471          sprintf(argv[3], "%s@%s", argv[0], mach);
472        }
473      else if (!strcmp(ptype, "SPLIT"))
474        {
475          argv[2] = xstrdup(strtrim(str));
476          argv[3] = xmalloc(strlen(argv[0]) + strlen(strtrim(mach)) +
477                            strlen(str) + 4);
478          sprintf(argv[3], "%s@%s, %s", argv[0], mach, str);
479        }
480      else /* ptype == "NONE" */
481        goto skip;
482
483      if (!strcmp(q->shortname, "gpob"))
484        {
485          sid = atoi(argv[5]);
486          if (sid > 0)
487            status = id_to_name(sid, USERS_TABLE, &argv[5]);
488          else
489            status = id_to_name(-sid, STRINGS_TABLE, &argv[5]);
490          if (status && status != MR_NO_MATCH)
491            return status;
492        }
493
494      (*action)(q->vcnt, argv, actarg);
495    skip:
496      /* free saved data */
497      for (i = 0; i < q->vcnt; i++)
498        free(argv[i]);
499      free(argv);
500    }
501
502  sq_destroy(sq);
503  return MR_SUCCESS;
504}
505
506/* Fix an ace_name, based on its type. */
507
508static int fix_ace(char *type, char **name)
509{
510  int id = atoi(*name);
511
512  if (!strcmp(type, "LIST"))
513    return id_to_name(id, LIST_TABLE, name);
514  else if (!strcmp(type, "USER"))
515    return id_to_name(id, USERS_TABLE, name);
516  else if (!strcmp(type, "KERBEROS"))
517    return id_to_name(id, STRINGS_TABLE, name);
518  else
519    {
520      free(*name);
521      if (!strcmp(type, "NONE"))
522        *name = xstrdup("NONE");
523      else
524        *name = xstrdup("???");
525      return MR_SUCCESS;
526    }
527}
528
529
530/* followup_gsnt: fix the ace_name and modby */
531
532int followup_gsnt(struct query *q, struct save_queue *sq, struct validate *v,
533                  int (*action)(int, char *[], void *), void *actarg,
534                  client *cl)
535{
536  char **argv;
537  int status, idx;
538
539  if (q->version < 8)
540    idx = 0;
541  else
542    idx = 3;
543
544  while (sq_get_data(sq, &argv))
545    {
546      mr_trim_args(q->vcnt, argv);
547
548      status = fix_ace(argv[7 + idx], &argv[8 + idx]);
549      if (status && status != MR_NO_MATCH)
550        return status;
551    }
552
553  return followup_fix_modby(q, sq, v, action, actarg, cl);
554}
555
556
557/* followup_ghst: fix the ace_name, strings and modby */
558
559int followup_ghst(struct query *q, struct save_queue *sq, struct validate *v,
560                  int (*action)(int, char *[], void *), void *actarg,
561                  client *cl)
562{
563  char **argv;
564  int id, status, idx;
565
566  if (q->version < 6)
567    idx = 0;
568  else if (q->version >= 6 && q->version < 8)
569    idx = 1;
570  else
571    idx = 2;
572
573  while (sq_get_data(sq, &argv))
574    {
575      mr_trim_args(q->vcnt, argv);
576
577      id = atoi(argv[13 + idx]);
578      status = id_to_name(id, STRINGS_TABLE, &argv[13 + idx]);
579      if (status)
580        return status;
581      id = atoi(argv[14 + idx]);
582      status = id_to_name(id, STRINGS_TABLE, &argv[14 + idx]);
583      if (status)
584        return status;
585      id = atoi(argv[16 + idx]);
586      if (id < 0)
587        status = id_to_name(-id, STRINGS_TABLE, &argv[16 + idx]);
588      else
589        status = id_to_name(id, USERS_TABLE, &argv[16 + idx]);
590      if (status && status != MR_NO_MATCH)
591        return status;
592
593      status = fix_ace(argv[11 + idx], &argv[12 + idx]);
594      if (status && status != MR_NO_MATCH)
595        return status;
596    }
597
598  return followup_fix_modby(q, sq, v, action, actarg, cl);
599}
600
601
602/* followup_glin: fix the ace_name, modace_name, expiration, and modby */
603
604int followup_glin(struct query *q, struct save_queue *sq, struct validate *v,
605                  int (*action)(int, char *[], void *), void *actarg,
606                  client *cl)
607{
608  char **argv;
609  int status;
610
611  while (sq_get_data(sq, &argv))
612    {
613      mr_trim_args(q->vcnt, argv);
614
615      if (q->version == 2)
616        status = fix_ace(argv[7], &argv[8]);
617      else if (q->version > 2 && q->version < 10)
618        status = fix_ace(argv[8], &argv[9]);
619      else
620        status = fix_ace(argv[10], &argv[11]);
621
622      if (status && status != MR_NO_MATCH)
623        return status;
624
625      if (q->version > 3)
626        {
627          if (q->version < 10)
628            status = fix_ace(argv[10], &argv[11]);
629          else if (q->version >= 10)
630            status = fix_ace(argv[12], &argv[13]);
631     
632          if (status && status != MR_NO_MATCH)
633            return status;
634        }
635
636      if (atoi(argv[6]) == -1)
637        {
638          argv[6] = xrealloc(argv[6], strlen(UNIQUE_GID) + 1);
639          strcpy(argv[6], UNIQUE_GID);
640        }
641    }
642
643  return followup_fix_modby(q, sq, v, action, actarg, cl);
644}
645
646/* followup_gsin: fix the ace_name and modby. */
647int followup_gsin(struct query *q, struct save_queue *sq, struct validate *v,
648                  int (*action)(int, char *[], void *), void *actarg,
649                  client *cl)
650{
651  char **argv;
652  int status;
653
654  while (sq_get_data(sq, &argv))
655    {
656      mr_trim_args(q->vcnt, argv);
657
658      status = fix_ace(argv[11], &argv[12]);
659      if (status && status != MR_NO_MATCH)
660        return status;
661    }
662
663  return followup_fix_modby(q, sq, v, action, actarg, cl);
664}
665
666int followup_gpsv(struct query *q, struct save_queue *sq, struct validate *v,
667                  int (*action)(int, char *[], void *), void *actarg,
668                  client *cl)
669{
670  char **argv;
671  int status;
672
673  while (sq_get_data(sq, &argv))
674    {
675      mr_trim_args(q->vcnt, argv);
676
677      status = fix_ace(argv[PRINTSERVER_OWNER_TYPE],
678                       &argv[PRINTSERVER_OWNER_NAME]);
679      if (status && status != MR_NO_MATCH)
680        return status;
681    }
682
683  return followup_fix_modby(q, sq, v, action, actarg, cl);
684}
685 
686
687/* followup_gqot: Fix the entity name, directory name & modby fields
688 *   argv[0] = filsys_id
689 *   argv[1] = type
690 *   argv[2] = entity_id
691 *   argv[3] = ascii(quota)
692 */
693
694int followup_gqot(struct query *q, struct save_queue *sq, struct validate *v,
695                  int (*action)(int, char *[], void *), void *actarg,
696                  client *cl)
697{
698  int j;
699  char **argv;
700  EXEC SQL BEGIN DECLARE SECTION;
701  int id;
702  char *name, *label;
703  EXEC SQL END DECLARE SECTION;
704  int status, idx;
705
706  if (!strcmp(q->name, "get_quota") ||
707      !strcmp(q->name, "get_quota_by_filesys"))
708    idx = 4;
709  else
710    idx = 3;
711
712  while (sq_get_data(sq, &argv))
713    {
714      if (idx == 4)
715        {
716          switch (argv[1][0])
717            {
718            case 'U':
719              status = id_to_name(atoi(argv[2]), USERS_TABLE, &argv[2]);
720              break;
721            case 'G':
722            case 'L':
723              status = id_to_name(atoi(argv[2]), LIST_TABLE, &argv[2]);
724              break;
725            case 'A':
726              free(argv[2]);
727              argv[2] = xstrdup("system:anyuser");
728              break;
729            default:
730              id = atoi(argv[2]);
731              argv[2] = xmalloc(8);
732              sprintf(argv[2], "%d", id);
733            }
734        }
735      id = atoi(argv[idx]);
736      free(argv[idx]);
737      argv[idx] = xmalloc(id ? NFSPHYS_DIR_SIZE : FILESYS_NAME_SIZE);
738      name = argv[idx];
739      name[0] = '\0';
740      if (id == 0)
741        {
742          label = argv[0];
743          EXEC SQL SELECT name INTO :name FROM filesys
744            WHERE label = :label;
745        }
746      else
747        {
748          EXEC SQL SELECT dir INTO :name FROM nfsphys
749            WHERE nfsphys_id = :id;
750        }
751      if (sqlca.sqlerrd[2] != 1)
752        sprintf(argv[idx], "#%d", id);
753
754      id = atoi(argv[idx + 3]);
755      if (id > 0)
756        status = id_to_name(id, USERS_TABLE, &argv[idx + 3]);
757      else
758        status = id_to_name(-id, STRINGS_TABLE, &argv[idx + 3]);
759      if (status && status != MR_NO_MATCH)
760        return status;
761      (*action)(q->vcnt, argv, actarg);
762      for (j = 0; j < q->vcnt; j++)
763        free(argv[j]);
764      free(argv);
765    }
766  sq_destroy(sq);
767  return MR_SUCCESS;
768}
769
770
771/* followup_aqot: Add allocation to nfsphys after creating quota.
772 *   argv[0] = filsys_id
773 *   argv[1] = type if "add_quota" or "update_quota"
774 *   argv[2 or 1] = id
775 *   argv[3 or 2] = ascii(quota)
776 */
777
778int followup_aqot(struct query *q, char *argv[], client *cl)
779{
780  EXEC SQL BEGIN DECLARE SECTION;
781  int quota, id, fs, who, physid, table;
782  char *entity, *qtype, *tname;
783  EXEC SQL END DECLARE SECTION;
784  char incr_qual[60];
785  char *incr_argv[2];
786  int status;
787
788  table = q->rtable;
789  tname = table_name[table];
790  fs = *(int *)argv[0];
791  EXEC SQL SELECT phys_id INTO :physid FROM filesys
792    WHERE filsys_id = :fs;
793  if (dbms_errno)
794    return mr_errcode;
795
796  if (!strcmp(q->shortname, "aqot") || !strcmp(q->shortname, "uqot"))
797    {
798      qtype = argv[1];
799      id = *(int *)argv[2];
800      quota = atoi(argv[3]);
801      sprintf(incr_qual, "q.filsys_id = %d", fs);
802    }
803  else
804    {
805      qtype = "USER";
806      id = *(int *)argv[1];
807      quota = atoi(argv[2]);
808      sprintf(incr_qual, "q.filsys_id = %d AND q.type = '%s' AND "
809              "q.entity_id = %d", fs, qtype, id);
810    }
811
812  /* quota case of incremental_{before|after} only looks at slot 1 */
813  incr_argv[1] = qtype;
814
815  /* Follows one of many possible gross hacks to fix these particular
816   * conflicts between what is possible in the query table and what
817   * is possible in SQL.
818   */
819  if (q->type == MR_Q_APPEND)
820    {
821      incremental_clear_before();
822      EXEC SQL INSERT INTO quota
823        (filsys_id, type, entity_id, quota, phys_id)
824        VALUES (:fs, NVL(:qtype, CHR(0)), :id, :quota, :physid);
825      incremental_after(table, incr_qual, incr_argv);
826    }
827  else
828    {
829      incremental_before(table, incr_qual, incr_argv);
830      EXEC SQL UPDATE quota SET quota = :quota
831        WHERE filsys_id = :fs AND type = :qtype AND entity_id = :id;
832      status = mr_errcode;
833      incremental_after(table, incr_qual, incr_argv);
834    }
835
836  if (dbms_errno)
837    return mr_errcode;
838  if (q->type == MR_Q_APPEND)
839    {
840      EXEC SQL UPDATE tblstats SET appends = appends + 1, modtime = SYSDATE
841        WHERE table_name = :tname;
842    }
843  else
844    {
845      EXEC SQL UPDATE tblstats SET updates = updates + 1, modtime = SYSDATE
846        WHERE table_name = :tname;
847    }
848
849  /* Proceed with original followup */
850  who = cl->client_id;
851  entity = cl->entity;
852
853  EXEC SQL UPDATE quota
854    SET modtime = SYSDATE, modby = :who, modwith = :entity
855    WHERE filsys_id = :fs and type = :qtype and entity_id = :id;
856  EXEC SQL UPDATE nfsphys SET allocated = allocated + :quota
857    WHERE nfsphys_id = :physid;
858  if (dbms_errno)
859    return mr_errcode;
860  return MR_SUCCESS;
861}
862
863
864/* Necessitated by the requirement of a correlation name by the incremental
865 * routines, since query table deletes don't provide one.
866 */
867int followup_dqot(struct query *q, char **argv, client *cl)
868{
869  char *qtype;
870  int id, fs, table;
871  char *incr_argv[2];
872  EXEC SQL BEGIN DECLARE SECTION;
873  char incr_qual[80], *tname;
874  EXEC SQL END DECLARE SECTION;
875
876  table = q->rtable;
877  tname = table_name[table];
878  fs = *(int *)argv[0];
879  if (!strcmp(q->shortname, "dqot"))
880    {
881      qtype = argv[1];
882      id = *(int *)argv[2];
883    }
884  else
885    {
886      qtype = "USER";
887      id = *(int *)argv[1];
888    }
889  sprintf(incr_qual, "q.filsys_id = %d AND q.type = '%s' AND q.entity_id = %d",
890          fs, qtype, id);
891
892  /* quota case of incremental_{before|after} only looks at slot 1 */
893  incr_argv[1] = qtype;
894
895  incremental_before(table, incr_qual, incr_argv);
896  EXEC SQL DELETE FROM quota q WHERE q.filsys_id = :fs AND q.type = :qtype
897    AND q.entity_id = :id;
898  incremental_clear_after();
899
900  if (dbms_errno)
901    return mr_errcode;
902
903  EXEC SQL UPDATE tblstats SET deletes = deletes + 1, modtime = SYSDATE
904    WHERE table_name = :tname;
905  return MR_SUCCESS;
906}
907
908/* followup_gzcl:
909 */
910
911int followup_gzcl(struct query *q, struct save_queue *sq, struct validate *v,
912                  int (*action)(int, char *[], void *), void *actarg,
913                  client *cl)
914{
915  int i, n, status;
916  char **argv;
917
918  if (q->version < 5)
919    n = 8;
920  else
921    n = 10;
922
923  while (sq_get_data(sq, &argv))
924    {
925      mr_trim_args(q->vcnt, argv);
926
927      for (i = 1; i < n; i += 2)
928        {
929          status = fix_ace(argv[i], &argv[i + 1]);
930          if (status && status != MR_NO_MATCH)
931            return status;
932        }
933    }
934
935  return followup_fix_modby(q, sq, v, action, actarg, cl);
936}
937
938
939/* followup_gsha:
940 */
941
942int followup_gsha(struct query *q, struct save_queue *sq, struct validate *v,
943                  int (*action)(int, char *[], void *), void *actarg,
944                  client *cl)
945{
946  char **argv;
947  int status;
948
949  while (sq_get_data(sq, &argv))
950    {
951      mr_trim_args(q->vcnt, argv);
952
953      status = fix_ace(argv[1], &argv[2]);
954      if (status && status != MR_NO_MATCH)
955        return status;
956    }
957
958  return followup_fix_modby(q, sq, v, action, actarg, cl);
959}
960
961
962int _sdl_followup(struct query *q, char *argv[], client *cl)
963{
964  if (atoi(argv[0]))
965    EXEC SQL ALTER SESSION SET SQL_TRACE TRUE;
966  else
967    EXEC SQL ALTER SESSION SET SQL_TRACE FALSE;
968
969  return MR_SUCCESS;
970}
971
972
973int trigger_dcm(struct query *q, char *argv[], client *cl)
974{
975  pid_t pid;
976  char prog[MAXPATHLEN];
977
978  sprintf(prog, "%s/startdcm", BIN_DIR);
979  pid = vfork();
980  switch (pid)
981    {
982    case 0:
983      execl(prog, "startdcm", 0);
984      exit(1);
985
986    case -1:
987      return errno;
988
989    default:
990      return MR_SUCCESS;
991    }
992}
993
994/* followup_gcon: fix the ace_name, memace_name, and modby */
995
996int followup_gcon(struct query *q, struct save_queue *sq, struct validate *v,
997                  int (*action)(int, char *[], void *), void *actarg,
998                  client *cl)
999{
1000  char **argv;
1001  int status, idx = 0;
1002
1003  if (q->version >= 9)
1004    idx = 1;
1005
1006  while (sq_get_data(sq, &argv))
1007  {
1008    mr_trim_args(q->vcnt, argv);
1009
1010    status = fix_ace(argv[4 + idx], &argv[5 + idx]);
1011    if (status && status != MR_NO_MATCH)
1012            return status;
1013     
1014          status = fix_ace(argv[6 + idx], &argv[7 + idx]);
1015          if (status && status != MR_NO_MATCH)
1016            return status;
1017        }
1018
1019  return followup_fix_modby(q, sq, v, action, actarg, cl);
1020}
1021
1022/* followup_get_user:  fix the modby and creator.
1023 * This assumes that the modby and creator fields are always
1024 * in the same relative position in the argv.
1025 */
1026
1027int followup_get_user(struct query *q, struct save_queue *sq, struct
1028                      validate *v, int (*action)(int, char *[], void *),
1029                      void *actarg, client *cl)
1030{
1031  char **argv;
1032  int i, j, k, status, id;
1033
1034  i = q->vcnt - 4;
1035  j = q->vcnt - 1;
1036  while (sq_get_data(sq, &argv))
1037    {
1038      mr_trim_args(q->vcnt, argv);
1039
1040      id = atoi(argv[i]);
1041      if (id > 0)
1042        status = id_to_name(id, USERS_TABLE, &argv[i]);
1043      else
1044        status = id_to_name(-id, STRINGS_TABLE, &argv[i]);
1045      if (status && status != MR_NO_MATCH)
1046        return status;
1047
1048      id = atoi(argv[j]);
1049      if (id > 0)
1050        status = id_to_name(id, USERS_TABLE, &argv[j]);
1051      else
1052        status = id_to_name(-id, STRINGS_TABLE, &argv[j]);
1053      if (status && status != MR_NO_MATCH)
1054        return status;
1055
1056      if (q->version > 11)
1057        {
1058          status = fix_ace(argv[15], &argv[16]);
1059          if (status && status != MR_NO_MATCH)
1060            return status;
1061        }
1062
1063      (*action)(q->vcnt, argv, actarg);
1064      for (k = 0; k < q->vcnt; k++)
1065        free(argv[k]);
1066      free(argv);
1067    }
1068  sq_destroy(sq);
1069  return MR_SUCCESS;
1070}
Note: See TracBrowser for help on using the repository browser.