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

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