]>
Commit | Line | Data |
---|---|---|
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 | ||
21 | EXEC SQL INCLUDE sqlca; | |
22 | ||
23 | RCSID("$Header$"); | |
24 | ||
25 | extern char *whoami, *table_name[]; | |
26 | extern int dbms_errno, mr_errcode; | |
27 | ||
28 | EXEC SQL BEGIN DECLARE SECTION; | |
29 | extern char stmt_buf[]; | |
30 | EXEC SQL END DECLARE SECTION; | |
31 | ||
32 | EXEC 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 | ||
42 | int 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 | ||
65 | int 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 | ||
86 | int 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 | ||
107 | int 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 | ||
128 | int 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 | ||
151 | int 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 | ||
173 | int 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 | ||
194 | int 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 | ||
217 | int 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 | ||
239 | int 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 | ||
265 | int 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 | ||
284 | /* fixes the modby field. This will be the second to last thing in the | |
285 | * argv, the argv length is determined from the query structure. It is | |
286 | * passed as a pointer to an integer. This will either turn it into a | |
287 | * username, or # + the users_id. | |
288 | */ | |
289 | int followup_fix_modby(struct query *q, struct save_queue *sq, | |
290 | struct validate *v, int (*action)(int, char *[], void *), | |
291 | void *actarg, client *cl) | |
292 | { | |
293 | int i, j; | |
294 | char **argv; | |
295 | int id, status; | |
296 | ||
297 | i = q->vcnt - 2; | |
298 | while (sq_get_data(sq, &argv)) | |
299 | { | |
300 | id = atoi(argv[i]); | |
301 | if (id > 0) | |
302 | status = id_to_name(id, USERS_TABLE, &argv[i]); | |
303 | else | |
304 | status = id_to_name(-id, STRINGS_TABLE, &argv[i]); | |
305 | if (status && status != MR_NO_MATCH) | |
306 | return status; | |
307 | (*action)(q->vcnt, argv, actarg); | |
308 | for (j = 0; j < q->vcnt; j++) | |
309 | free(argv[j]); | |
310 | free(argv); | |
311 | } | |
312 | sq_destroy(sq); | |
313 | return MR_SUCCESS; | |
314 | } | |
315 | ||
316 | /** | |
317 | ** followup_ausr - add finger and pobox entries, set_user_modtime | |
318 | ** | |
319 | ** Inputs: | |
320 | ** argv[0] - login (add_user) | |
321 | ** argv[3] - last name | |
322 | ** argv[4] - first name | |
323 | ** argv[5] - middle name | |
324 | ** | |
325 | **/ | |
326 | ||
327 | int followup_ausr(struct query *q, char *argv[], client *cl) | |
328 | { | |
329 | EXEC SQL BEGIN DECLARE SECTION; | |
330 | int who, status; | |
331 | char *login, *entity, *name; | |
332 | char fullname[USERS_FIRST_SIZE + USERS_MIDDLE_SIZE + USERS_LAST_SIZE]; | |
333 | EXEC SQL END DECLARE SECTION; | |
334 | ||
335 | /* build fullname */ | |
336 | if (strlen(argv[4]) && strlen(argv[5])) | |
337 | sprintf(fullname, "%s %s %s", argv[4], argv[5], argv[3]); | |
338 | else if (strlen(argv[4])) | |
339 | sprintf(fullname, "%s %s", argv[4], argv[3]); | |
340 | else | |
341 | sprintf(fullname, "%s", argv[3]); | |
342 | ||
343 | login = argv[0]; | |
344 | who = cl->client_id; | |
345 | entity = cl->entity; | |
346 | ||
347 | /* create finger entry, pobox & set modtime on user */ | |
348 | EXEC SQL UPDATE users | |
349 | SET modtime = SYSDATE, modby = :who, modwith = :entity, | |
350 | fullname = NVL(:fullname, CHR(0)), affiliation = type, | |
351 | fmodtime = SYSDATE, fmodby = :who, fmodwith = :entity, | |
352 | potype = 'NONE', pmodtime = SYSDATE, pmodby = :who, pmodwith = :entity | |
353 | WHERE login = :login; | |
354 | ||
355 | return MR_SUCCESS; | |
356 | } | |
357 | ||
358 | /* followup_gpob: fixes argv[2] and argv[3] based on the pobox type. | |
359 | * Then completes the upcall to the user. | |
360 | * | |
361 | * argv[2] is the users_id on input and should be converted to the | |
362 | * pobox name on output. argv[3] is empty on input and should be | |
363 | * converted to an email address on output. | |
364 | */ | |
365 | ||
366 | int followup_gpob(struct query *q, struct save_queue *sq, struct validate *v, | |
367 | int (*action)(int, char *[], void *), void *actarg, | |
368 | client *cl) | |
369 | { | |
370 | char **argv; | |
371 | char *ptype, *p; | |
372 | int mid, sid, status, i; | |
373 | EXEC SQL BEGIN DECLARE SECTION; | |
374 | int users_id, pid, iid, bid; | |
375 | char mach[MACHINE_NAME_SIZE], fs[FILESYS_LABEL_SIZE]; | |
376 | char str[STRINGS_STRING_SIZE]; | |
377 | EXEC SQL END DECLARE SECTION; | |
378 | ||
379 | /* for each row */ | |
380 | while (sq_get_data(sq, &argv)) | |
381 | { | |
382 | mr_trim_args(4, argv); | |
383 | ptype = argv[1]; | |
384 | users_id = atoi(argv[2]); | |
385 | ||
386 | EXEC SQL SELECT pop_id, imap_id, box_id INTO :pid, :iid, :bid | |
387 | FROM users WHERE users_id = :users_id; | |
388 | if (sqlca.sqlcode) | |
389 | return MR_USER; | |
390 | ||
391 | if (ptype[0] == 'S') | |
392 | { | |
393 | /* SMTP or SPLIT */ | |
394 | EXEC SQL SELECT string INTO :str FROM strings | |
395 | WHERE string_id = :bid; | |
396 | if (sqlca.sqlcode) | |
397 | return MR_STRING; | |
398 | ||
399 | /* If SMTP, don't bother fetching IMAP and POP boxes. */ | |
400 | if (ptype[1] == 'M') | |
401 | pid = iid = 0; | |
402 | } | |
403 | if (iid) | |
404 | { | |
405 | /* IMAP, or SPLIT with IMAP */ | |
406 | EXEC SQL SELECT f.label, m.name INTO :fs, :mach | |
407 | FROM filesys f, machine m | |
408 | WHERE f.filsys_id = :iid AND f.mach_id = m.mach_id; | |
409 | if (sqlca.sqlcode) | |
410 | return MR_FILESYS; | |
411 | } | |
412 | if (pid) | |
413 | { | |
414 | /* POP, or SPLIT with POP */ | |
415 | EXEC SQL SELECT m.name INTO :mach FROM machine m, users u | |
416 | WHERE u.users_id = :users_id AND u.pop_id = m.mach_id; | |
417 | if (sqlca.sqlcode) | |
418 | return MR_MACHINE; | |
419 | } | |
420 | ||
421 | free(argv[2]); | |
422 | free(argv[3]); | |
423 | ||
424 | /* Now assemble the right answer. */ | |
425 | if (!strcmp(ptype, "POP")) | |
426 | { | |
427 | argv[2] = xstrdup(strtrim(mach)); | |
428 | argv[3] = xmalloc(strlen(argv[0]) + strlen(argv[2]) + 2); | |
429 | sprintf(argv[3], "%s@%s", argv[0], argv[2]); | |
430 | } | |
431 | else if (!strcmp(ptype, "SMTP")) | |
432 | { | |
433 | argv[2] = xstrdup(strtrim(str)); | |
434 | argv[3] = xstrdup(str); | |
435 | } | |
436 | else if (!strcmp(ptype, "IMAP")) | |
437 | { | |
438 | argv[2] = xstrdup(strtrim(fs)); | |
439 | argv[3] = xmalloc(strlen(argv[0]) + strlen(strtrim(mach)) + 2); | |
440 | sprintf(argv[3], "%s@%s", argv[0], mach); | |
441 | } | |
442 | else if (!strcmp(ptype, "SPLIT")) | |
443 | { | |
444 | argv[2] = xstrdup(strtrim(str)); | |
445 | argv[3] = xmalloc(strlen(argv[0]) + strlen(strtrim(mach)) + | |
446 | strlen(str) + 4); | |
447 | sprintf(argv[3], "%s@%s, %s", argv[0], mach, str); | |
448 | } | |
449 | else /* ptype == "NONE" */ | |
450 | goto skip; | |
451 | ||
452 | if (!strcmp(q->shortname, "gpob")) | |
453 | { | |
454 | sid = atoi(argv[5]); | |
455 | if (sid > 0) | |
456 | status = id_to_name(sid, USERS_TABLE, &argv[5]); | |
457 | else | |
458 | status = id_to_name(-sid, STRINGS_TABLE, &argv[5]); | |
459 | if (status && status != MR_NO_MATCH) | |
460 | return status; | |
461 | } | |
462 | ||
463 | (*action)(q->vcnt, argv, actarg); | |
464 | skip: | |
465 | /* free saved data */ | |
466 | for (i = 0; i < q->vcnt; i++) | |
467 | free(argv[i]); | |
468 | free(argv); | |
469 | } | |
470 | ||
471 | sq_destroy(sq); | |
472 | return MR_SUCCESS; | |
473 | } | |
474 | ||
475 | /* Fix an ace_name, based on its type. */ | |
476 | ||
477 | static int fix_ace(char *type, char **name) | |
478 | { | |
479 | int id = atoi(*name); | |
480 | ||
481 | if (!strcmp(type, "LIST")) | |
482 | return id_to_name(id, LIST_TABLE, name); | |
483 | else if (!strcmp(type, "USER")) | |
484 | return id_to_name(id, USERS_TABLE, name); | |
485 | else if (!strcmp(type, "KERBEROS")) | |
486 | return id_to_name(id, STRINGS_TABLE, name); | |
487 | else | |
488 | { | |
489 | free(*name); | |
490 | if (!strcmp(type, "NONE")) | |
491 | *name = xstrdup("NONE"); | |
492 | else | |
493 | *name = xstrdup("???"); | |
494 | return MR_SUCCESS; | |
495 | } | |
496 | } | |
497 | ||
498 | ||
499 | /* followup_gsnt: fix the ace_name and modby */ | |
500 | ||
501 | int followup_gsnt(struct query *q, struct save_queue *sq, struct validate *v, | |
502 | int (*action)(int, char *[], void *), void *actarg, | |
503 | client *cl) | |
504 | { | |
505 | char **argv; | |
506 | int status; | |
507 | ||
508 | while (sq_get_data(sq, &argv)) | |
509 | { | |
510 | mr_trim_args(q->vcnt, argv); | |
511 | ||
512 | status = fix_ace(argv[7], &argv[8]); | |
513 | if (status && status != MR_NO_MATCH) | |
514 | return status; | |
515 | } | |
516 | ||
517 | return followup_fix_modby(q, sq, v, action, actarg, cl); | |
518 | } | |
519 | ||
520 | ||
521 | /* followup_ghst: fix the ace_name, strings and modby */ | |
522 | ||
523 | int followup_ghst(struct query *q, struct save_queue *sq, struct validate *v, | |
524 | int (*action)(int, char *[], void *), void *actarg, | |
525 | client *cl) | |
526 | { | |
527 | char **argv; | |
528 | int id, status; | |
529 | ||
530 | while (sq_get_data(sq, &argv)) | |
531 | { | |
532 | mr_trim_args(q->vcnt, argv); | |
533 | ||
534 | id = atoi(argv[13]); | |
535 | status = id_to_name(id, STRINGS_TABLE, &argv[13]); | |
536 | if (status) | |
537 | return status; | |
538 | id = atoi(argv[14]); | |
539 | status = id_to_name(id, STRINGS_TABLE, &argv[14]); | |
540 | if (status) | |
541 | return status; | |
542 | id = atoi(argv[16]); | |
543 | if (id < 0) | |
544 | status = id_to_name(-id, STRINGS_TABLE, &argv[16]); | |
545 | else | |
546 | status = id_to_name(id, USERS_TABLE, &argv[16]); | |
547 | if (status && status != MR_NO_MATCH) | |
548 | return status; | |
549 | ||
550 | status = fix_ace(argv[11], &argv[12]); | |
551 | if (status && status != MR_NO_MATCH) | |
552 | return status; | |
553 | } | |
554 | ||
555 | return followup_fix_modby(q, sq, v, action, actarg, cl); | |
556 | } | |
557 | ||
558 | ||
559 | /* followup_glin: fix the ace_name, modace_name, expiration, and modby */ | |
560 | ||
561 | int followup_glin(struct query *q, struct save_queue *sq, struct validate *v, | |
562 | int (*action)(int, char *[], void *), void *actarg, | |
563 | client *cl) | |
564 | { | |
565 | char **argv; | |
566 | int id, i, idx, status; | |
567 | ||
568 | idx = 7; | |
569 | if (!strcmp(q->shortname, "gsin")) | |
570 | idx = 11; | |
571 | ||
572 | while (sq_get_data(sq, &argv)) | |
573 | { | |
574 | mr_trim_args(q->vcnt, argv); | |
575 | ||
576 | status = fix_ace(argv[idx], &argv[idx + 1]); | |
577 | if (status && status != MR_NO_MATCH) | |
578 | return status; | |
579 | ||
580 | if (!strcmp(q->shortname, "glin") && atoi(argv[6]) == -1) | |
581 | { | |
582 | argv[6] = xrealloc(argv[6], strlen(UNIQUE_GID) + 1); | |
583 | strcpy(argv[6], UNIQUE_GID); | |
584 | } | |
585 | } | |
586 | ||
587 | return followup_fix_modby(q, sq, v, action, actarg, cl); | |
588 | } | |
589 | ||
590 | int followup_gpsv(struct query *q, struct save_queue *sq, struct validate *v, | |
591 | int (*action)(int, char *[], void *), void *actarg, | |
592 | client *cl) | |
593 | { | |
594 | char **argv; | |
595 | int status; | |
596 | ||
597 | while (sq_get_data(sq, &argv)) | |
598 | { | |
599 | mr_trim_args(q->vcnt, argv); | |
600 | ||
601 | status = fix_ace(argv[PRINTSERVER_OWNER_TYPE], | |
602 | &argv[PRINTSERVER_OWNER_NAME]); | |
603 | if (status && status != MR_NO_MATCH) | |
604 | return status; | |
605 | } | |
606 | ||
607 | return followup_fix_modby(q, sq, v, action, actarg, cl); | |
608 | } | |
609 | ||
610 | ||
611 | /* followup_gqot: Fix the entity name, directory name & modby fields | |
612 | * argv[0] = filsys_id | |
613 | * argv[1] = type | |
614 | * argv[2] = entity_id | |
615 | * argv[3] = ascii(quota) | |
616 | */ | |
617 | ||
618 | int followup_gqot(struct query *q, struct save_queue *sq, struct validate *v, | |
619 | int (*action)(int, char *[], void *), void *actarg, | |
620 | client *cl) | |
621 | { | |
622 | int j; | |
623 | char **argv; | |
624 | EXEC SQL BEGIN DECLARE SECTION; | |
625 | int id; | |
626 | char *name, *label; | |
627 | EXEC SQL END DECLARE SECTION; | |
628 | int status, idx; | |
629 | ||
630 | if (!strcmp(q->name, "get_quota") || | |
631 | !strcmp(q->name, "get_quota_by_filesys")) | |
632 | idx = 4; | |
633 | else | |
634 | idx = 3; | |
635 | ||
636 | while (sq_get_data(sq, &argv)) | |
637 | { | |
638 | if (idx == 4) | |
639 | { | |
640 | switch (argv[1][0]) | |
641 | { | |
642 | case 'U': | |
643 | status = id_to_name(atoi(argv[2]), USERS_TABLE, &argv[2]); | |
644 | break; | |
645 | case 'G': | |
646 | case 'L': | |
647 | status = id_to_name(atoi(argv[2]), LIST_TABLE, &argv[2]); | |
648 | break; | |
649 | case 'A': | |
650 | free(argv[2]); | |
651 | argv[2] = xstrdup("system:anyuser"); | |
652 | break; | |
653 | default: | |
654 | id = atoi(argv[2]); | |
655 | argv[2] = xmalloc(8); | |
656 | sprintf(argv[2], "%d", id); | |
657 | } | |
658 | } | |
659 | id = atoi(argv[idx]); | |
660 | free(argv[idx]); | |
661 | argv[idx] = xmalloc(id ? NFSPHYS_DIR_SIZE : FILESYS_NAME_SIZE); | |
662 | name = argv[idx]; | |
663 | name[0] = '\0'; | |
664 | if (id == 0) | |
665 | { | |
666 | label = argv[0]; | |
667 | EXEC SQL SELECT name INTO :name FROM filesys | |
668 | WHERE label = :label; | |
669 | } | |
670 | else | |
671 | { | |
672 | EXEC SQL SELECT dir INTO :name FROM nfsphys | |
673 | WHERE nfsphys_id = :id; | |
674 | } | |
675 | if (sqlca.sqlerrd[2] != 1) | |
676 | sprintf(argv[idx], "#%d", id); | |
677 | ||
678 | id = atoi(argv[idx + 3]); | |
679 | if (id > 0) | |
680 | status = id_to_name(id, USERS_TABLE, &argv[idx + 3]); | |
681 | else | |
682 | status = id_to_name(-id, STRINGS_TABLE, &argv[idx + 3]); | |
683 | if (status && status != MR_NO_MATCH) | |
684 | return status; | |
685 | (*action)(q->vcnt, argv, actarg); | |
686 | for (j = 0; j < q->vcnt; j++) | |
687 | free(argv[j]); | |
688 | free(argv); | |
689 | } | |
690 | sq_destroy(sq); | |
691 | return MR_SUCCESS; | |
692 | } | |
693 | ||
694 | ||
695 | /* followup_aqot: Add allocation to nfsphys after creating quota. | |
696 | * argv[0] = filsys_id | |
697 | * argv[1] = type if "add_quota" or "update_quota" | |
698 | * argv[2 or 1] = id | |
699 | * argv[3 or 2] = ascii(quota) | |
700 | */ | |
701 | ||
702 | int followup_aqot(struct query *q, char *argv[], client *cl) | |
703 | { | |
704 | EXEC SQL BEGIN DECLARE SECTION; | |
705 | int quota, id, fs, who, physid, table; | |
706 | char *entity, *qtype, *tname; | |
707 | EXEC SQL END DECLARE SECTION; | |
708 | char incr_qual[60]; | |
709 | char *incr_argv[2]; | |
710 | int status; | |
711 | ||
712 | table = q->rtable; | |
713 | tname = table_name[table]; | |
714 | fs = *(int *)argv[0]; | |
715 | EXEC SQL SELECT phys_id INTO :physid FROM filesys | |
716 | WHERE filsys_id = :fs; | |
717 | if (dbms_errno) | |
718 | return mr_errcode; | |
719 | ||
720 | if (!strcmp(q->shortname, "aqot") || !strcmp(q->shortname, "uqot")) | |
721 | { | |
722 | qtype = argv[1]; | |
723 | id = *(int *)argv[2]; | |
724 | quota = atoi(argv[3]); | |
725 | sprintf(incr_qual, "q.filsys_id = %d", fs); | |
726 | } | |
727 | else | |
728 | { | |
729 | qtype = "USER"; | |
730 | id = *(int *)argv[1]; | |
731 | quota = atoi(argv[2]); | |
732 | sprintf(incr_qual, "q.filsys_id = %d AND q.type = '%s' AND " | |
733 | "q.entity_id = %d", fs, qtype, id); | |
734 | } | |
735 | ||
736 | /* quota case of incremental_{before|after} only looks at slot 1 */ | |
737 | incr_argv[1] = qtype; | |
738 | ||
739 | /* Follows one of many possible gross hacks to fix these particular | |
740 | * conflicts between what is possible in the query table and what | |
741 | * is possible in SQL. | |
742 | */ | |
743 | if (q->type == APPEND) | |
744 | { | |
745 | incremental_clear_before(); | |
746 | EXEC SQL INSERT INTO quota | |
747 | (filsys_id, type, entity_id, quota, phys_id) | |
748 | VALUES (:fs, NVL(:qtype, CHR(0)), :id, :quota, :physid); | |
749 | incremental_after(table, incr_qual, incr_argv); | |
750 | } | |
751 | else | |
752 | { | |
753 | incremental_before(table, incr_qual, incr_argv); | |
754 | EXEC SQL UPDATE quota SET quota = :quota | |
755 | WHERE filsys_id = :fs AND type = :qtype AND entity_id = :id; | |
756 | status = mr_errcode; | |
757 | incremental_after(table, incr_qual, incr_argv); | |
758 | } | |
759 | ||
760 | if (dbms_errno) | |
761 | return mr_errcode; | |
762 | flush_name(argv[0], table); | |
763 | if (q->type == APPEND) | |
764 | { | |
765 | EXEC SQL UPDATE tblstats SET appends = appends + 1, modtime = SYSDATE | |
766 | WHERE table_name = :tname; | |
767 | } | |
768 | else | |
769 | { | |
770 | EXEC SQL UPDATE tblstats SET updates = updates + 1, modtime = SYSDATE | |
771 | WHERE table_name = :tname; | |
772 | } | |
773 | ||
774 | /* Proceed with original followup */ | |
775 | who = cl->client_id; | |
776 | entity = cl->entity; | |
777 | ||
778 | EXEC SQL UPDATE quota | |
779 | SET modtime = SYSDATE, modby = :who, modwith = :entity | |
780 | WHERE filsys_id = :fs and type = :qtype and entity_id = :id; | |
781 | EXEC SQL UPDATE nfsphys SET allocated = allocated + :quota | |
782 | WHERE nfsphys_id = :physid; | |
783 | if (dbms_errno) | |
784 | return mr_errcode; | |
785 | return MR_SUCCESS; | |
786 | } | |
787 | ||
788 | ||
789 | /* Necessitated by the requirement of a correlation name by the incremental | |
790 | * routines, since query table deletes don't provide one. | |
791 | */ | |
792 | int followup_dqot(struct query *q, char **argv, client *cl) | |
793 | { | |
794 | char *qtype; | |
795 | int id, fs, table; | |
796 | char *incr_argv[2]; | |
797 | EXEC SQL BEGIN DECLARE SECTION; | |
798 | char incr_qual[80], *tname; | |
799 | EXEC SQL END DECLARE SECTION; | |
800 | ||
801 | table = q->rtable; | |
802 | tname = table_name[table]; | |
803 | fs = *(int *)argv[0]; | |
804 | if (!strcmp(q->shortname, "dqot")) | |
805 | { | |
806 | qtype = argv[1]; | |
807 | id = *(int *)argv[2]; | |
808 | } | |
809 | else | |
810 | { | |
811 | qtype = "USER"; | |
812 | id = *(int *)argv[1]; | |
813 | } | |
814 | sprintf(incr_qual, "q.filsys_id = %d AND q.type = '%s' AND q.entity_id = %d", | |
815 | fs, qtype, id); | |
816 | ||
817 | /* quota case of incremental_{before|after} only looks at slot 1 */ | |
818 | incr_argv[1] = qtype; | |
819 | ||
820 | incremental_before(table, incr_qual, incr_argv); | |
821 | EXEC SQL DELETE FROM quota q WHERE q.filsys_id = :fs AND q.type = :qtype | |
822 | AND q.entity_id = :id; | |
823 | incremental_clear_after(); | |
824 | ||
825 | if (dbms_errno) | |
826 | return mr_errcode; | |
827 | flush_name(argv[0], table); | |
828 | ||
829 | EXEC SQL UPDATE tblstats SET deletes = deletes + 1, modtime = SYSDATE | |
830 | WHERE table_name = :tname; | |
831 | return MR_SUCCESS; | |
832 | } | |
833 | ||
834 | /* followup_gzcl: | |
835 | */ | |
836 | ||
837 | int followup_gzcl(struct query *q, struct save_queue *sq, struct validate *v, | |
838 | int (*action)(int, char *[], void *), void *actarg, | |
839 | client *cl) | |
840 | { | |
841 | int i, status; | |
842 | char **argv; | |
843 | ||
844 | while (sq_get_data(sq, &argv)) | |
845 | { | |
846 | mr_trim_args(q->vcnt, argv); | |
847 | ||
848 | for (i = 1; i < 8; i += 2) | |
849 | { | |
850 | status = fix_ace(argv[i], &argv[i + 1]); | |
851 | if (status && status != MR_NO_MATCH) | |
852 | return status; | |
853 | } | |
854 | } | |
855 | ||
856 | return followup_fix_modby(q, sq, v, action, actarg, cl); | |
857 | } | |
858 | ||
859 | ||
860 | /* followup_gsha: | |
861 | */ | |
862 | ||
863 | int followup_gsha(struct query *q, struct save_queue *sq, struct validate *v, | |
864 | int (*action)(int, char *[], void *), void *actarg, | |
865 | client *cl) | |
866 | { | |
867 | char **argv; | |
868 | int status; | |
869 | ||
870 | while (sq_get_data(sq, &argv)) | |
871 | { | |
872 | mr_trim_args(q->vcnt, argv); | |
873 | ||
874 | status = fix_ace(argv[1], &argv[2]); | |
875 | if (status && status != MR_NO_MATCH) | |
876 | return status; | |
877 | } | |
878 | ||
879 | return followup_fix_modby(q, sq, v, action, actarg, cl); | |
880 | } | |
881 | ||
882 | ||
883 | int _sdl_followup(struct query *q, char *argv[], client *cl) | |
884 | { | |
885 | if (atoi(argv[0])) | |
886 | EXEC SQL ALTER SESSION SET SQL_TRACE TRUE; | |
887 | else | |
888 | EXEC SQL ALTER SESSION SET SQL_TRACE FALSE; | |
889 | ||
890 | return MR_SUCCESS; | |
891 | } | |
892 | ||
893 | ||
894 | int trigger_dcm(struct query *q, char *argv[], client *cl) | |
895 | { | |
896 | pid_t pid; | |
897 | char prog[MAXPATHLEN]; | |
898 | ||
899 | sprintf(prog, "%s/startdcm", BIN_DIR); | |
900 | pid = vfork(); | |
901 | switch (pid) | |
902 | { | |
903 | case 0: | |
904 | execl(prog, "startdcm", 0); | |
905 | exit(1); | |
906 | ||
907 | case -1: | |
908 | return errno; | |
909 | ||
910 | default: | |
911 | return MR_SUCCESS; | |
912 | } | |
913 | } |