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

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