]> andersk Git - moira.git/blame_incremental - server/qsupport.dc
Further changes to prevent INGRES error 40100.
[moira.git] / server / qsupport.dc
... / ...
CommitLineData
1/*
2 * $Source$
3 * $Author$
4 * $Header$
5 *
6 * Copyright (C) 1987 by the Massachusetts Institute of Technology
7 * For copying and distribution information, please see the file
8 * <mit-copyright.h>.
9 *
10 */
11
12#ifndef lint
13static char *rcsid_qsupport_dc = "$Header$";
14#endif lint
15
16#include <mit-copyright.h>
17#include "query.h"
18#include "mr_server.h"
19#include <ctype.h>
20#ifdef GDSS
21#include "gdss.h"
22#endif /* GDSS */
23EXEC SQL INCLUDE sqlca;
24EXEC SQL INCLUDE sqlda;
25#include "qrtn.h"
26
27extern char *whoami, *strsave();
28extern int ingres_errno, mr_errcode;
29
30EXEC SQL BEGIN DECLARE SECTION;
31extern char stmt_buf[];
32EXEC SQL END DECLARE SECTION;
33
34/* Specialized Access Routines */
35
36/* access_user - verify that client name equals specified login name
37 *
38 * - since field validation routines are called first, a users_id is
39 * now in argv[0] instead of the login name.
40 */
41
42EXEC SQL WHENEVER SQLERROR CALL ingerr;
43
44access_user(q, argv, cl)
45 struct query *q;
46 char *argv[];
47 client *cl;
48{
49 if (cl->users_id != *(int *)argv[0])
50 return(MR_PERM);
51 else
52 return(MR_SUCCESS);
53}
54
55
56
57/* access_login - verify that client name equals specified login name
58 *
59 * argv[0...n] contain search info. q->
60 */
61
62access_login(q, argv, cl)
63 struct query *q;
64 char *argv[];
65 client *cl;
66{
67 EXEC SQL BEGIN DECLARE SECTION;
68 int id;
69 char qual[256];
70 EXEC SQL END DECLARE SECTION;
71
72 build_qual(q->qual, q->argc, argv, qual);
73 if (!strncmp(q->name,"get_user_account",strlen("get_user_account"))) {
74 EXEC SQL SELECT users_id INTO :id FROM users u, strings str WHERE :qual;
75 } else {
76 EXEC SQL SELECT users_id INTO :id FROM users u WHERE :qual;
77 }
78
79 if (sqlca.sqlerrd[2] != 1 || id != cl->users_id)
80 return(MR_PERM);
81 else
82 return(MR_SUCCESS);
83}
84
85
86
87/* access_list - check access for most list operations
88 *
89 * Inputs: argv[0] - list_id
90 * q - query name
91 * argv[2] - member ID (only for queries "amtl" and "dmfl")
92 * argv[7] - group IID (only for query "ulis")
93 * cl - client name
94 *
95 * - check that client is a member of the access control list
96 * - OR, if the query is add_member_to_list or delete_member_from_list
97 * and the list is public, allow access if client = member
98 */
99
100access_list(q, argv, cl)
101 struct query *q;
102 char *argv[];
103 client *cl;
104{
105 EXEC SQL BEGIN DECLARE SECTION;
106 int list_id, acl_id, flags, gid;
107 char acl_type[9];
108 EXEC SQL END DECLARE SECTION;
109 char *client_type;
110 int client_id, status;
111
112 list_id = *(int *)argv[0];
113 EXEC SQL SELECT acl_id, acl_type, gid, publicflg
114 INTO :acl_id, :acl_type, :gid, :flags
115 FROM list
116 WHERE list_id = :list_id;
117
118 if (sqlca.sqlerrd[2] != 1)
119 return(MR_INTERNAL);
120
121 /* parse client structure */
122 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
123 return(status);
124
125 /* if amtl or dmfl and list is public allow client to add or delete self */
126 if (((!strcmp("amtl", q->shortname) && flags) ||
127 (!strcmp("dmfl", q->shortname))) &&
128 (!strcmp("USER", argv[1]))) {
129 if (*(int *)argv[2] == client_id) return(MR_SUCCESS);
130 /* if update_list, don't allow them to change the GID */
131 } else if (!strcmp("ulis", q->shortname)) {
132 if ((!strcmp(argv[7], UNIQUE_GID) && (gid != -1)) ||
133 (strcmp(argv[7], UNIQUE_GID) && (gid != atoi(argv[7]))))
134 return(MR_PERM);
135 }
136
137 /* check for client in access control list */
138 status = find_member(acl_type, acl_id, client_type, client_id, 0);
139 if (!status) return(MR_PERM);
140
141 return(MR_SUCCESS);
142}
143
144
145/* access_visible_list - allow access to list only if it is not hidden,
146 * or if the client is on the ACL
147 *
148 * Inputs: argv[0] - list_id
149 * cl - client identifier
150 */
151
152access_visible_list(q, argv, cl)
153 struct query *q;
154 char *argv[];
155 client *cl;
156{
157 EXEC SQL BEGIN DECLARE SECTION;
158 int list_id, acl_id, flags ;
159 char acl_type[9];
160 EXEC SQL END DECLARE SECTION;
161 char *client_type;
162 int client_id, status;
163
164 list_id = *(int *)argv[0];
165 EXEC SQL SELECT hidden, acl_id, acl_type
166 INTO :flags, :acl_id, :acl_type
167 FROM list
168 WHERE list_id = :list_id;
169 if (sqlca.sqlerrd[2] != 1)
170 return(MR_INTERNAL);
171 if (!flags)
172 return(MR_SUCCESS);
173
174 /* parse client structure */
175 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
176 return(status);
177
178 /* check for client in access control list */
179 status = find_member(acl_type, acl_id, client_type, client_id, 0);
180 if (!status)
181 return(MR_PERM);
182
183 return(MR_SUCCESS);
184}
185
186
187/* access_vis_list_by_name - allow access to list only if it is not hidden,
188 * or if the client is on the ACL
189 *
190 * Inputs: argv[0] - list name
191 * cl - client identifier
192 */
193
194access_vis_list_by_name(q, argv, cl)
195 struct query *q;
196 char *argv[];
197 client *cl;
198{
199 EXEC SQL BEGIN DECLARE SECTION;
200 int acl_id, flags, rowcount;
201 char acl_type[9], *listname;
202 EXEC SQL END DECLARE SECTION;
203 char *client_type;
204 int client_id, status;
205
206 listname = argv[0];
207 EXEC SQL SELECT hidden, acl_id, acl_type INTO :flags, :acl_id, :acl_type
208 FROM list WHERE name = :listname;
209
210 rowcount=sqlca.sqlerrd[2];
211 if (rowcount > 1)
212 return(MR_WILDCARD);
213 if (rowcount == 0)
214 return(MR_NO_MATCH);
215 if (!flags)
216 return(MR_SUCCESS);
217
218 /* parse client structure */
219 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
220 return(status);
221
222 /* check for client in access control list */
223 status = find_member(acl_type, acl_id, client_type, client_id, 0);
224 if (!status)
225 return(MR_PERM);
226
227 return(MR_SUCCESS);
228}
229
230
231/* access_member - allow user to access member of type "USER" and name matches
232 * username, or to access member of type "LIST" and list is one that user is
233 * on the acl of, or the list is visible.
234 */
235
236access_member(q, argv, cl)
237 struct query *q;
238 char *argv[];
239 client *cl;
240{
241 if (!strcmp(argv[0], "LIST") || !strcmp(argv[0], "RLIST"))
242 return(access_visible_list(q, &argv[1], cl));
243
244 if (!strcmp(argv[0], "USER") || !strcmp(argv[0], "RUSER")) {
245 if (cl->users_id == *(int *)argv[1])
246 return(MR_SUCCESS);
247 }
248
249 if (!strcmp(argv[0], "KERBEROS") || !strcmp(argv[0], "RKERBERO")) {
250 if (cl->client_id == *(int *)argv[1])
251 return(MR_SUCCESS);
252 }
253
254 return(MR_PERM);
255}
256
257
258/* access_qgli - special access routine for Qualified_get_lists. Allows
259 * access iff argv[0] == "TRUE" and argv[2] == "FALSE".
260 */
261
262access_qgli(q, argv, cl)
263 struct query *q;
264 char *argv[];
265 client *cl;
266{
267 if (!strcmp(argv[0], "TRUE") && !strcmp(argv[2], "FALSE"))
268 return(MR_SUCCESS);
269 return(MR_PERM);
270}
271
272
273/* access_service - allow access if user is on ACL of service. Don't
274 * allow access if a wildcard is used.
275 */
276
277access_service(q, argv, cl)
278 struct query *q;
279 char *argv[];
280 client *cl;
281{
282 EXEC SQL BEGIN DECLARE SECTION;
283 int acl_id;
284 char *name, acl_type[9];
285 EXEC SQL END DECLARE SECTION;
286 int client_id, status;
287 char *client_type, *c;
288
289 name = argv[0];
290 for(c=name;*c;c++) if(islower(*c)) *c = toupper(*c); /* uppercasify */
291 EXEC SQL SELECT acl_id, acl_type INTO :acl_id, :acl_type FROM servers
292 WHERE name = :name;
293 if (sqlca.sqlerrd[2] > 1)
294 return(MR_PERM);
295
296 /* parse client structure */
297 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
298 return(status);
299
300 /* check for client in access control list */
301 status = find_member(acl_type, acl_id, client_type, client_id, 0);
302 if (!status) return(MR_PERM);
303
304 return(MR_SUCCESS);
305}
306
307
308/* access_filesys - verify that client is owner or on owners list of filesystem
309 * named by argv[0]
310 */
311
312access_filesys(q, argv, cl)
313 struct query *q;
314 char *argv[];
315 client *cl;
316{
317 EXEC SQL BEGIN DECLARE SECTION;
318 int users_id, list_id;
319 char *name;
320 EXEC SQL END DECLARE SECTION;
321 int status, client_id;
322 char *client_type;
323
324 name = argv[0];
325 EXEC SQL SELECT owner, owners INTO :users_id, :list_id FROM filesys
326 WHERE label = :name;
327
328 if (sqlca.sqlerrd[2] != 1)
329 return(MR_PERM);
330 if (users_id == cl->users_id)
331 return(MR_SUCCESS);
332 if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS)
333 return(status);
334 status = find_member("LIST", list_id, client_type, client_id, 0);
335 if (status)
336 return(MR_SUCCESS);
337 else
338 return(MR_PERM);
339}
340
341
342\f
343/* Setup Routines */
344
345/* Setup routine for add_user
346 *
347 * Inputs: argv[0] - login
348 * argv[1] - uid
349 *
350 * Description:
351 *
352 * - if argv[1] == UNIQUE_UID then set argv[1] = next(uid)
353 * - if argv[0] == UNIQUE_LOGIN then set argv[0] = "#<uid>"
354 */
355
356setup_ausr(q, argv, cl)
357 struct query *q;
358 register char *argv[];
359 client *cl;
360{
361 int row;
362 EXEC SQL BEGIN DECLARE SECTION;
363 int nuid;
364 EXEC SQL END DECLARE SECTION;
365
366 if (!strcmp(q->shortname, "uusr") || !strcmp(q->shortname, "uuac"))
367 row = 2;
368 else
369 row = 1;
370 if (!strcmp(argv[row], UNIQUE_UID) || atoi(argv[row]) == -1) {
371 if (set_next_object_id("uid", "users", 1))
372 return(MR_INGRES_ERR);
373 EXEC SQL SELECT value INTO :nuid FROM numvalues WHERE name = 'uid';
374 if (sqlca.sqlerrd[2] != 1)
375 return(MR_INTERNAL);
376 sprintf(argv[row], "%d", nuid);
377 }
378
379 if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[row]) == -1) {
380 sprintf(argv[0], "#%s", argv[row]);
381 }
382
383 if((mr_errcode=prefetch_value(q,argv,cl))!=MR_SUCCESS)
384 return(mr_errcode);
385
386 return(MR_SUCCESS);
387}
388
389
390/* setup_dusr - verify that the user is no longer being referenced
391 * and may safely be deleted.
392 */
393
394int setup_dusr(q, argv)
395 struct query *q;
396 char **argv;
397{
398 EXEC SQL BEGIN DECLARE SECTION;
399 int flag, id, cnt;
400 EXEC SQL END DECLARE SECTION;
401
402 id = *(int *)argv[0];
403
404 /* For now, only allow users to be deleted if their status is 0 */
405 EXEC SQL REPEATED SELECT status INTO :flag FROM users
406 WHERE users_id = :id;
407 if (flag != 0 && flag != 4)
408 return(MR_IN_USE);
409
410 EXEC SQL REPEATED DELETE FROM quota WHERE entity_id = :id AND type='USER';
411 EXEC SQL REPEATED DELETE FROM krbmap WHERE users_id = :id;
412 EXEC SQL REPEATED SELECT COUNT(member_id) INTO :cnt FROM imembers
413 WHERE member_id = :id AND member_type = 'USER';
414 if (cnt > 0)
415 return(MR_IN_USE);
416 EXEC SQL REPEATED SELECT COUNT(label) INTO :cnt FROM filesys
417 WHERE owner = :id;
418 if (cnt > 0)
419 return(MR_IN_USE);
420 EXEC SQL REPEATED SELECT COUNT(name) INTO :cnt FROM list
421 WHERE acl_id = :id AND acl_type = 'USER';
422 if (cnt > 0)
423 return(MR_IN_USE);
424 EXEC SQL REPEATED SELECT COUNT(name) INTO :cnt FROM servers
425 WHERE acl_id = :id AND acl_type = 'USER';
426 if (cnt > 0)
427 return(MR_IN_USE);
428 EXEC SQL REPEATED SELECT COUNT(acl_id) INTO :cnt FROM hostaccess
429 WHERE acl_id = :id AND acl_type = 'USER';
430 if (cnt > 0)
431 return(MR_IN_USE);
432 if (ingres_errno)
433 return(mr_errcode);
434 return(MR_SUCCESS);
435}
436
437
438/* setup_spop: verify that there is already a valid POP machine_id in the
439 * pop_id field. Also take care of keeping track of the post office usage.
440 */
441int setup_spop(q, argv)
442struct query *q;
443char **argv;
444{
445 EXEC SQL BEGIN DECLARE SECTION;
446 int id, mid, flag;
447 char type[9];
448 EXEC SQL END DECLARE SECTION;
449
450 id = *(int *)argv[0];
451 EXEC SQL REPEATED SELECT potype, pop_id INTO :type, :mid FROM users
452 WHERE users_id = :id;
453 if(sqlca.sqlerrd[2] = 0)
454 return(MR_MACHINE);
455 EXEC SQL REPEATED SELECT mach_id INTO :mid FROM machine
456 WHERE mach_id = :mid;
457 if (sqlca.sqlerrd[2] = 0)
458 return(MR_MACHINE);
459 if (strcmp(strtrim(type), "POP"))
460 set_pop_usage(mid, 1);
461 return(MR_SUCCESS);
462}
463
464
465/* setup_dpob: Take care of keeping track of the post office usage.
466 */
467int setup_dpob(q, argv)
468 struct query *q;
469 char **argv;
470{
471 EXEC SQL BEGIN DECLARE SECTION;
472 int id, user;
473 char type[9];
474 EXEC SQL END DECLARE SECTION;
475
476 user = *(int *)argv[0];
477 EXEC SQL REPEATED SELECT potype, pop_id INTO :type, :id FROM users
478 WHERE users_id = :user;
479 if (ingres_errno) return(mr_errcode);
480
481 if (!strcmp(strtrim(type), "POP"))
482 set_pop_usage(id, -1);
483 return(MR_SUCCESS);
484}
485
486
487/* setup_dmac - verify that the machine is no longer being referenced
488 * and may safely be deleted.
489 */
490
491int setup_dmac(q, argv)
492 struct query *q;
493 char **argv;
494{
495 EXEC SQL BEGIN DECLARE SECTION;
496 int flag, id, cnt;
497 EXEC SQL END DECLARE SECTION;
498
499 id = *(int *)argv[0];
500 EXEC SQL REPEATED SELECT COUNT(login) INTO :cnt FROM users
501 WHERE potype='POP' AND pop_id = :id;
502 if (cnt > 0)
503 return(MR_IN_USE);
504 EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM serverhosts
505 WHERE mach_id = :id;
506 if (cnt > 0)
507 return(MR_IN_USE);
508 EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM nfsphys
509 WHERE mach_id = :id;
510 if (cnt > 0)
511 return(MR_IN_USE);
512 EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM hostaccess
513 WHERE mach_id = :id;
514 if (cnt > 0)
515 return(MR_IN_USE);
516 EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM printcap
517 WHERE mach_id = :id;
518 if (cnt > 0)
519 return(MR_IN_USE);
520 EXEC SQL REPEATED SELECT COUNT(quotaserver) INTO :cnt FROM printcap
521 WHERE quotaserver = :id;
522 if (cnt > 0)
523 return(MR_IN_USE);
524 EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM palladium
525 WHERE mach_id = :id;
526 if (cnt > 0)
527 return(MR_IN_USE);
528
529 EXEC SQL REPEATED DELETE FROM mcmap WHERE mach_id = :id;
530 if (ingres_errno) return(mr_errcode);
531 return(MR_SUCCESS);
532}
533
534
535/* setup_dclu - verify that the cluster is no longer being referenced
536 * and may safely be deleted.
537 */
538
539int setup_dclu(q, argv)
540 struct query *q;
541 char **argv;
542{
543 EXEC SQL BEGIN DECLARE SECTION;
544 int id, cnt;
545 EXEC SQL END DECLARE SECTION;
546
547 id = *(int *)argv[0];
548 EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM mcmap
549 WHERE clu_id = :id;
550 if (cnt > 0)
551 return(MR_IN_USE);
552 EXEC SQL REPEATED SELECT COUNT(clu_id) INTO :cnt FROM svc
553 WHERE clu_id = :id;
554 if (cnt > 0)
555 return(MR_IN_USE);
556 if (ingres_errno)
557 return(mr_errcode);
558 return(MR_SUCCESS);
559}
560
561
562/* setup_alis - if argv[5] is non-zero and argv[6] is UNIQUE_ID, then allocate
563 * a new gid and put it in argv[6]. Otherwise if argv[6] is UNIQUE_ID but
564 * argv[5] is not, then remember that UNIQUE_ID is being stored by putting
565 * a -1 there. Remember that this is also used for ulis, with the indexes
566 * at 6 & 7. Also check that the list name does not contain uppercase
567 * characters, control characters, @, or :.
568 */
569
570static int badlistchars[] = {
571 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
572 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
573 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
574 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, /* 0 - ? */
575 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
576 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, /* P - _ */
577 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
578 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
579 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
580 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
581 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
582 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
583 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
584 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
585 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
586 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
587};
588
589int setup_alis(q, argv, cl)
590 struct query *q;
591 char *argv[];
592 client *cl;
593{
594 EXEC SQL BEGIN DECLARE SECTION;
595 int ngid;
596 EXEC SQL END DECLARE SECTION;
597 char *malloc();
598 unsigned char *p;
599 int idx;
600
601 if (!strcmp(q->shortname, "alis"))
602 idx = 0;
603 else if (!strcmp(q->shortname, "ulis"))
604 idx = 1;
605
606 for (p = (unsigned char *) argv[idx]; *p; p++)
607 if (badlistchars[*p])
608 return(MR_BAD_CHAR);
609
610 if (!strcmp(argv[6 + idx], UNIQUE_GID) || atoi(argv[6 + idx]) == -1) {
611 if (atoi(argv[5 + idx])) {
612 if (set_next_object_id("gid", "list", 1))
613 return(MR_INGRES_ERR);
614 EXEC SQL REPEATED SELECT value INTO :ngid FROM numvalues
615 WHERE name = 'gid';
616 if (ingres_errno) return(mr_errcode);
617 sprintf(argv[6 + idx], "%d", ngid);
618 } else {
619 strcpy(argv[6 + idx], "-1");
620 }
621 }
622
623 if((mr_errcode=prefetch_value(q,argv,cl))!=MR_SUCCESS)
624 return(mr_errcode);
625
626 return(MR_SUCCESS);
627}
628
629
630/* setup_dlis - verify that the list is no longer being referenced
631 * and may safely be deleted.
632 */
633
634int setup_dlis(q, argv)
635 struct query *q;
636 char *argv[];
637{
638 int flag, id, ec;
639
640 id = *(int *)argv[0];
641 sprintf(stmt_buf,"SELECT member_id FROM imembers WHERE member_id = %d AND member_type='LIST'",id);
642 if(ec=mr_select_any(stmt_buf)) {
643 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
644 }
645
646 sprintf(stmt_buf,"SELECT member_id FROM imembers WHERE list_id = %d",id);
647 if(ec=mr_select_any(stmt_buf)) {
648 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
649 }
650
651 sprintf(stmt_buf,"SELECT label FROM filesys WHERE owners = %d",id);
652 if(ec=mr_select_any(stmt_buf)) {
653 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
654 }
655
656 sprintf(stmt_buf,"SELECT tag FROM capacls WHERE list_id = %d",id);
657 if(ec=mr_select_any(stmt_buf)) {
658 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
659 }
660
661 sprintf(stmt_buf,"SELECT name FROM list WHERE acl_id = %d AND acl_type='LIST' AND list_id != %d",id,id);
662 if(ec=mr_select_any(stmt_buf)) {
663 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
664 }
665
666 sprintf(stmt_buf,"SELECT name FROM servers WHERE acl_id = %d AND acl_type='LIST'",id);
667 if(ec=mr_select_any(stmt_buf)) {
668 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
669 }
670
671 sprintf(stmt_buf,"SELECT entity_id FROM quota WHERE entity_id = %d AND type='GROUP'",id);
672 if(ec=mr_select_any(stmt_buf)) {
673 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
674 }
675
676 sprintf(stmt_buf,"SELECT acl_id FROM hostaccess WHERE acl_id = %d AND acl_type='LIST'",id);
677 if(ec=mr_select_any(stmt_buf)) {
678 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
679 }
680
681 sprintf(stmt_buf,"SELECT class FROM zephyr z \
682WHERE z.xmt_type = 'LIST' AND z.xmt_id = %d \
683OR z.sub_type = 'LIST' AND z.sub_id = %d \
684OR z.iws_type = 'LIST' AND z.iws_id = %d \
685OR z.iui_type = 'LIST' AND z.iui_id = %d",id,id,id,id);
686 if(ec=mr_select_any(stmt_buf)) {
687 if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec);
688 }
689
690 return(MR_SUCCESS);
691}
692
693
694/* setup_dsin - verify that the service is no longer being referenced
695 * and may safely be deleted.
696 */
697
698int setup_dsin(q, argv)
699 struct query *q;
700 char **argv;
701{
702 EXEC SQL BEGIN DECLARE SECTION;
703 int ec;
704 char *svrname;
705 EXEC SQL END DECLARE SECTION;
706
707 sprintf(stmt_buf,"SELECT service FROM serverhosts WHERE service = UPPERCASE('%s')",argv[0]);
708 if(ec=mr_select_any(stmt_buf)) {
709 if(ec==MR_EXISTS)
710 return(MR_IN_USE);
711 else
712 return(ec);
713 }
714
715 svrname=argv[0];
716 EXEC SQL SELECT inprogress INTO :ec FROM servers
717 WHERE name=UPPERCASE(:svrname);
718 if(ingres_errno)
719 return(mr_errcode);
720 if(ec)
721 return(MR_IN_USE);
722
723 return(MR_SUCCESS);
724}
725
726
727/* setup_dshi - verify that the service-host is no longer being referenced
728 * and may safely be deleted.
729 */
730
731int setup_dshi(q, argv)
732 struct query *q;
733 char **argv;
734{
735 EXEC SQL BEGIN DECLARE SECTION;
736 int id, ec;
737 char *svrname;
738 EXEC SQL END DECLARE SECTION;
739
740 svrname=argv[0];
741 id = *(int *)argv[1];
742
743 EXEC SQL SELECT inprogress INTO :ec FROM serverhosts
744 WHERE service=UPPERCASE(:svrname) AND mach_id = :id;
745 if(ingres_errno)
746 return(mr_errcode);
747 if(ec)
748 return(MR_IN_USE);
749
750
751 return(MR_SUCCESS);
752}
753
754
755/**
756 ** setup_add_filesys - verify existance of referenced file systems
757 **
758 ** Inputs: Add
759 ** argv[1] - type
760 ** argv[2] - mach_id
761 ** argv[3] - name
762 ** argv[5] - access
763 **
764 ** Description:
765 ** - for type = RVD:
766 ** * allow anything
767 ** - for type = NFS:
768 ** * extract directory prefix from name
769 ** * verify mach_id/dir in nfsphys
770 ** * verify access in {r, w, R, W}
771 **
772 ** Side effect: sets variable var_phys_id to the ID of the physical
773 ** filesystem (nfsphys_id for NFS, 0 for RVD)
774 **
775 ** Errors:
776 ** MR_NFS - specified directory not exported
777 ** MR_FILESYS_ACCESS - invalid filesys access
778 **
779 **/
780
781EXEC SQL BEGIN DECLARE SECTION;
782static int var_phys_id;
783EXEC SQL END DECLARE SECTION;
784
785setup_afil(q, argv, cl)
786 struct query *q;
787 char *argv[];
788 client *cl;
789{
790 char *type, *name;
791 int mach_id;
792 EXEC SQL BEGIN DECLARE SECTION;
793 int ok;
794 char ftype[32], *access;
795 EXEC SQL END DECLARE SECTION;
796
797 type = argv[1];
798 mach_id = *(int *)argv[2];
799 name = argv[3];
800 access = argv[5];
801 var_phys_id = 0;
802
803 sprintf(ftype, "fs_access_%s", type);
804 EXEC SQL SELECT COUNT(trans) INTO :ok FROM alias
805 WHERE name = :ftype AND type = 'TYPE' and trans = :access;
806 if (ingres_errno) return(mr_errcode);
807 if (ok == 0) return(MR_FILESYS_ACCESS);
808
809 if((mr_errcode=prefetch_value(q,argv,cl))!=MR_SUCCESS)
810 return(mr_errcode);
811
812 if (!strcmp(type, "NFS"))
813 return (check_nfs(mach_id, name, access));
814
815 return(MR_SUCCESS);
816}
817
818
819/* Verify the arguments, depending on the FStype. Also, if this is an
820 * NFS filesystem, then update any quotas for that filesystem to reflect
821 * the new phys_id.
822 */
823
824setup_ufil(q, argv, cl)
825 struct query *q;
826 char *argv[];
827 client *cl;
828{
829 int mach_id, status;
830 char *type, *name;
831 EXEC SQL BEGIN DECLARE SECTION;
832 int fid, total, who, ok;
833 char *entity, ftype[32], *access;
834 int var_phys_id = 0;
835 short int total_null;
836 EXEC SQL END DECLARE SECTION;
837
838 type = argv[2];
839 mach_id = *(int *)argv[3];
840 name = argv[4];
841 access = argv[6];
842 fid = *(int *)argv[0];
843 who = cl->client_id;
844 entity = cl->entity;
845
846 sprintf(ftype, "fs_access_%s", type);
847 EXEC SQL SELECT COUNT(trans) INTO :ok FROM alias
848 WHERE name = :ftype AND type='TYPE' AND trans = :access;
849 if (ingres_errno) return(mr_errcode);
850 if (ok == 0) return(MR_FILESYS_ACCESS);
851
852 EXEC SQL SELECT type INTO :ftype FROM filesys
853 WHERE filsys_id = :fid;
854 strtrim(ftype);
855 if (ingres_errno) return(mr_errcode);
856
857 if (!strcmp(type, "NFS")) {
858 status = check_nfs(mach_id, name, access);
859 EXEC SQL UPDATE quota SET phys_id = :var_phys_id
860 WHERE filsys_id = :fid;
861 if (ingres_errno) return(mr_errcode);
862 return(status);
863 } else if (!strcmp(type, "AFS") && strcmp(ftype, "AFS")) {
864 total = 0;
865 EXEC SQL REPEATED DELETE FROM quota
866 WHERE type = 'ANY' AND filsys_id = :fid;
867 EXEC SQL SELECT SUM (quota) INTO :total:total_null FROM quota
868 WHERE filsys_id = :fid AND phys_id != 0;
869 if (ingres_errno) return(mr_errcode);
870 if (!total_null && (total != 0)) {
871/*
872 * append quota (quota = total, filsys_id = fid,
873 * phys_id = 0, entity_id = 0, type = "ANY",
874 * modtime = "now", modby = who, modwith = entity)
875 */
876 EXEC SQL INSERT INTO quota (quota, filsys_id, phys_id, entity_id,
877 type, modtime, modby, modwith)
878 VALUES (:total, :fid, 0, 0,
879 'ANY', 'now', :who, :entity) ;
880 if (ingres_errno) return(mr_errcode);
881 }
882 } else {
883 EXEC SQL UPDATE quota SET phys_id = 0 WHERE filsys_id = :fid;
884 if (ingres_errno) return(mr_errcode);
885 }
886 return(MR_SUCCESS);
887}
888
889
890/* Find the NFS physical partition that the named directory is on.
891 * This is done by comparing the dir against the mount point of the
892 * partition. To make sure we get the correct match when there is
893 * more than one, we sort the query in reverse order by dir name.
894 */
895
896check_nfs(mach_id, name, access)
897 EXEC SQL BEGIN DECLARE SECTION;
898 int mach_id;
899 EXEC SQL END DECLARE SECTION;
900 char *name;
901 char *access;
902{
903 EXEC SQL BEGIN DECLARE SECTION;
904 char dir[81];
905 EXEC SQL END DECLARE SECTION;
906 char caccess;
907 register int status;
908 register char *cp1;
909 register char *cp2;
910
911 status = MR_NFS;
912 EXEC SQL DECLARE csr101 CURSOR FOR
913 SELECT nfsphys_id, TRIM (dir) FROM nfsphys
914 WHERE mach_id = :mach_id
915 ORDER BY 2 DESC;
916 EXEC SQL OPEN csr101;
917 while(1) {
918 EXEC SQL FETCH csr101 INTO :var_phys_id, :dir;
919 if(sqlca.sqlcode != 0) break;
920 cp1 = name;
921 cp2 = dir;
922 while (*cp2) {
923 if (*cp1++ != *cp2) break;
924 cp2++;
925 }
926 if (*cp2 == 0) {
927 status = MR_SUCCESS;
928 break;
929 }
930 }
931 EXEC SQL CLOSE csr101;
932 if (ingres_errno)
933 return(mr_errcode);
934 return(status);
935}
936
937
938/* setup_dfil: free any quota records and fsgroup info associated with
939 * a filesystem when it is deleted. Also adjust the allocation numbers.
940 */
941
942setup_dfil(q, argv, cl)
943 struct query *q;
944 char **argv;
945 client *cl;
946{
947 EXEC SQL BEGIN DECLARE SECTION;
948 int id, total, phys_id;
949 short int none;
950 EXEC SQL END DECLARE SECTION;
951
952 id = *(int *)argv[0];
953 EXEC SQL REPEATED SELECT SUM (quota) INTO :total:none FROM quota
954 WHERE filsys_id = :id;
955
956 if(none) total=0;
957
958 /** What if there are multiple phys_id's per f/s? (bad data) **/
959 EXEC SQL REPEATED SELECT phys_id INTO :phys_id FROM filesys
960 WHERE filsys_id = :id;
961 EXEC SQL REPEATED UPDATE nfsphys SET allocated = allocated - :total
962 WHERE nfsphys_id = :phys_id;
963
964 if(!none) {
965 EXEC SQL REPEATED DELETE FROM quota WHERE filsys_id = :id;
966 }
967 EXEC SQL REPEATED DELETE FROM fsgroup WHERE filsys_id = :id;
968 EXEC SQL REPEATED DELETE FROM fsgroup WHERE group_id = :id;
969 if (ingres_errno) return(mr_errcode);
970 return(MR_SUCCESS);
971}
972
973
974/* setup_dnfp: check to see that the nfs physical partition does not have
975 * any filesystems assigned to it before allowing it to be deleted.
976 */
977
978setup_dnfp(q, argv, cl)
979 struct query *q;
980 char **argv;
981 client *cl;
982{
983 EXEC SQL BEGIN DECLARE SECTION;
984 int id, cnt;
985 char *dir;
986 EXEC SQL END DECLARE SECTION;
987
988 id = *(int *)argv[0];
989 dir = argv[1];
990 EXEC SQL REPEATED SELECT label INTO :cnt FROM filesys fs, nfsphys np
991 WHERE fs.mach_id = :id AND fs.phys_id = np.nfsphys_id
992 AND np.mach_id = :id AND np.dir = :dir;
993 if (cnt > 0)
994 return(MR_IN_USE);
995 if (ingres_errno)
996 return(mr_errcode);
997 return(MR_SUCCESS);
998}
999
1000
1001/* setup_dqot: Remove allocation from nfsphys before deleting quota.
1002 * argv[0] = filsys_id
1003 * argv[1] = type if "update_quota" or "delete_quota"
1004 * argv[2 or 1] = users_id or list_id
1005 */
1006
1007setup_dqot(q, argv, cl)
1008 struct query *q;
1009 char **argv;
1010 client *cl;
1011{
1012 EXEC SQL BEGIN DECLARE SECTION;
1013 int quota, fs, id, physid;
1014 char *qtype;
1015 EXEC SQL END DECLARE SECTION;
1016
1017 fs = *(int *)argv[0];
1018 if (!strcmp(q->name, "update_quota") || !strcmp(q->name, "delete_quota")) {
1019 qtype = argv[1];
1020 id = *(int *)argv[2];
1021 } else {
1022 qtype = "USER";
1023 id = *(int *)argv[1];
1024 }
1025
1026 EXEC SQL REPEATED SELECT quota INTO :quota FROM quota
1027 WHERE type = :qtype AND entity_id = :id AND filsys_id = :fs;
1028 EXEC SQL REPEATED SELECT phys_id INTO :physid FROM filesys
1029 WHERE filsys_id = :fs;
1030 EXEC SQL REPEATED UPDATE nfsphys SET allocated = allocated - :quota
1031 WHERE nfsphys_id = :physid;
1032
1033 if (ingres_errno) return(mr_errcode);
1034 return(MR_SUCCESS);
1035}
1036
1037
1038/* setup_sshi: don't exclusive lock the machine table during
1039 * set_server_host_internal.
1040 */
1041/** Not allowed under (INGRES) SQL **/
1042setup_sshi(q, argv, cl)
1043 struct query *q;
1044 char **argv;
1045 client *cl;
1046{
1047#if 0
1048#ifsql INGRES
1049 EXEC SQL set lockmode session where readlock = system;
1050#endsql
1051#endif
1052 return(MR_SUCCESS);
1053}
1054
1055
1056/* setup add_kerberos_user_mapping: add the string to the string
1057 * table if necessary.
1058 */
1059
1060setup_akum(q, argv, cl)
1061struct query *q;
1062char **argv;
1063client *cl;
1064{
1065 EXEC SQL BEGIN DECLARE SECTION;
1066 int id, rowcount;
1067 char *name;
1068 EXEC SQL END DECLARE SECTION;
1069
1070 name = argv[1];
1071 if (name_to_id(name, "STRING", &id) != MR_SUCCESS) {
1072 if (q->type != APPEND) return(MR_STRING);
1073 EXEC SQL SELECT value INTO :id FROM numvalues
1074 WHERE name = 'strings_id';
1075 id++;
1076 EXEC SQL UPDATE numvalues SET value = :id
1077 WHERE name = 'strings_id';
1078 EXEC SQL INSERT INTO strings (string_id, string) VALUES (:id, :name);
1079 cache_entry(name, "STRING", id);
1080 }
1081 if (ingres_errno) return(mr_errcode);
1082 *(int *)argv[1] = id;
1083 return(MR_SUCCESS);
1084}
1085
1086
1087\f
1088/* FOLLOWUP ROUTINES */
1089
1090/* generic set_modtime routine. This takes the table name from the query,
1091 * and will update the modtime, modby, and modwho fields in the entry in
1092 * the table whose name field matches argv[0].
1093 */
1094
1095set_modtime(q, argv, cl)
1096 struct query *q;
1097 char *argv[];
1098 client *cl;
1099{
1100 char *name, *entity, *table;
1101 int who;
1102
1103 entity = cl->entity;
1104 who = cl->client_id;
1105 table = q->rtable;
1106 name = argv[0];
1107
1108 sprintf(stmt_buf,"UPDATE %s SET modtime = 'now', modby = %d, modwith = '%s' WHERE %s.name = LEFT('%s',SIZE(%s.name))",table,who,entity,table,name,table);
1109 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
1110
1111 return(MR_SUCCESS);
1112}
1113
1114/* generic set_modtime_by_id routine. This takes the table name from
1115 * the query, and the id name from the validate record,
1116 * and will update the modtime, modby, and modwho fields in the entry in
1117 * the table whose id matches argv[0].
1118 */
1119
1120set_modtime_by_id(q, argv, cl)
1121 struct query *q;
1122 char **argv;
1123 client *cl;
1124{
1125 char *entity, *table, *id_name;
1126 int who, id;
1127
1128 entity = cl->entity;
1129 who = cl->client_id;
1130 table = q->rtable;
1131 id_name = q->validate->object_id;
1132
1133 id = *(int *)argv[0];
1134 sprintf(stmt_buf,"UPDATE %s SET modtime = 'now', modby = %d, \
1135modwith = '%s' WHERE %s.%s = %d",table,who,entity,table,id_name,id);
1136 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
1137 return(MR_SUCCESS);
1138}
1139
1140
1141/* Sets the finger modtime on a user record. The users_id will be in argv[0].
1142 */
1143
1144set_finger_modtime(q, argv, cl)
1145 struct query *q;
1146 char *argv[];
1147 client *cl;
1148{
1149 EXEC SQL BEGIN DECLARE SECTION;
1150 int users_id, who;
1151 char *entity;
1152 EXEC SQL END DECLARE SECTION;
1153
1154 entity = cl->entity;
1155 who = cl->client_id;
1156 users_id = *(int *)argv[0];
1157
1158 EXEC SQL UPDATE users SET fmodtime='now', fmodby = :who, fmodwith = :entity
1159 WHERE users.users_id = :users_id;
1160
1161 return(MR_SUCCESS);
1162}
1163
1164
1165/* Sets the pobox modtime on a user record. The users_id will be in argv[0].
1166 */
1167
1168set_pobox_modtime(q, argv, cl)
1169 struct query *q;
1170 char **argv;
1171 client *cl;
1172{
1173 EXEC SQL BEGIN DECLARE SECTION;
1174 int users_id, who;
1175 char *entity;
1176 EXEC SQL END DECLARE SECTION;
1177
1178 entity = cl->entity;
1179 who = cl->client_id;
1180 users_id = *(int *)argv[0];
1181
1182 EXEC SQL UPDATE users SET pmodtime='now', pmodby = :who, pmodwith = :entity
1183 WHERE users.users_id = :users_id;
1184
1185 return(MR_SUCCESS);
1186}
1187
1188
1189/* Like set_modtime, but uppercases the name first.
1190 */
1191
1192set_uppercase_modtime(q, argv, cl)
1193 struct query *q;
1194 char **argv;
1195 client *cl;
1196{
1197 char *name, *entity, *table;
1198 int who;
1199
1200 entity = cl->entity;
1201 who = cl->client_id;
1202 table = q->rtable;
1203 name = argv[0];
1204
1205 sprintf(stmt_buf,"UPDATE %s SET modtime = 'now', modby = %d, modwith = '%s' WHERE %s.name = UPPERCASE(LEFT('%s',SIZE(%s.name)))",table,who,entity,table,name,table);
1206 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
1207
1208 return(MR_SUCCESS);
1209}
1210
1211
1212/* Sets the modtime on the machine whose mach_id is in argv[0]. This routine
1213 * is necessary for add_machine_to_cluster becuase the table that query
1214 * operates on is "mcm", not "machine".
1215 */
1216
1217set_mach_modtime_by_id(q, argv, cl)
1218 struct query *q;
1219 char **argv;
1220 client *cl;
1221{
1222 EXEC SQL BEGIN DECLARE SECTION;
1223 char *entity;
1224 int who, id;
1225 EXEC SQL END DECLARE SECTION;
1226
1227 entity = cl->entity;
1228 who = cl->client_id;
1229 id = *(int *)argv[0];
1230 EXEC SQL UPDATE machine SET modtime='now', modby = :who, modwith = :entity
1231 WHERE machine.mach_id = :id;
1232
1233 return(MR_SUCCESS);
1234}
1235
1236
1237/* Sets the modtime on the cluster whose mach_id is in argv[0]. This routine
1238 * is necessary for add_cluster_data and delete_cluster_data becuase the
1239 * table that query operates on is "svc", not "cluster".
1240 */
1241
1242set_cluster_modtime_by_id(q, argv, cl)
1243 struct query *q;
1244 char **argv;
1245 client *cl;
1246{
1247 EXEC SQL BEGIN DECLARE SECTION;
1248 char *entity;
1249 int who, id;
1250 EXEC SQL END DECLARE SECTION;
1251
1252 entity = cl->entity;
1253 who = cl->client_id;
1254
1255 id = *(int *)argv[0];
1256 EXEC SQL UPDATE cluster SET modtime='now', modby = :who, modwith = :entity
1257 WHERE cluster.clu_id = :id;
1258 return(MR_SUCCESS);
1259}
1260
1261
1262/* sets the modtime on the serverhost where the service name is in argv[0]
1263 * and the mach_id is in argv[1].
1264 */
1265
1266set_serverhost_modtime(q, argv, cl)
1267 struct query *q;
1268 char **argv;
1269 client *cl;
1270{
1271 EXEC SQL BEGIN DECLARE SECTION;
1272 char *entity, *serv;
1273 int who, id;
1274 EXEC SQL END DECLARE SECTION;
1275
1276 entity = cl->entity;
1277 who = cl->client_id;
1278
1279 serv = argv[0];
1280 id = *(int *)argv[1];
1281 EXEC SQL UPDATE serverhosts
1282 SET modtime = 'now', modby = :who, modwith = :entity
1283 WHERE service = :serv AND mach_id = :id;
1284 return(MR_SUCCESS);
1285}
1286
1287
1288/* sets the modtime on the nfsphys where the mach_id is in argv[0] and the
1289 * directory name is in argv[1].
1290 */
1291
1292set_nfsphys_modtime(q, argv, cl)
1293 struct query *q;
1294 char **argv;
1295 client *cl;
1296{
1297 EXEC SQL BEGIN DECLARE SECTION;
1298 char *entity, *dir;
1299 int who, id;
1300 EXEC SQL END DECLARE SECTION;
1301
1302 entity = cl->entity;
1303 who = cl->client_id;
1304
1305 id = *(int *)argv[0];
1306 dir = argv[1];
1307 EXEC SQL UPDATE nfsphys SET modtime = 'now', modby = :who, modwith = :entity
1308 WHERE dir = :dir AND mach_id = :id;
1309 return(MR_SUCCESS);
1310}
1311
1312
1313/* sets the modtime on a filesystem, where argv[0] contains the filesys
1314 * label.
1315 */
1316
1317set_filesys_modtime(q, argv, cl)
1318 struct query *q;
1319 char *argv[];
1320 client *cl;
1321{
1322 EXEC SQL BEGIN DECLARE SECTION;
1323 char *label, *entity;
1324 int who;
1325 EXEC SQL END DECLARE SECTION;
1326
1327 entity = cl->entity;
1328 who = cl->client_id;
1329
1330 label = argv[0];
1331 if (!strcmp(q->shortname, "ufil"))
1332 label = argv[1];
1333
1334 EXEC SQL UPDATE filesys SET modtime = 'now', modby = :who,
1335 modwith = :entity, phys_id = :var_phys_id
1336 WHERE label = LEFT(:label,SIZE(label));
1337 return(MR_SUCCESS);
1338}
1339
1340
1341/* sets the modtime on a zephyr class, where argv[0] contains the class
1342 * name.
1343 */
1344
1345set_zephyr_modtime(q, argv, cl)
1346 struct query *q;
1347 char *argv[];
1348 client *cl;
1349{
1350 EXEC SQL BEGIN DECLARE SECTION;
1351 char *class, *entity;
1352 int who;
1353 EXEC SQL END DECLARE SECTION;
1354
1355 entity = cl->entity;
1356 who = cl->client_id;
1357
1358 class = argv[0];
1359
1360 EXEC SQL UPDATE zephyr SET modtime = 'now', modby = :who, modwith = :entity
1361 WHERE class = LEFT(:class,SIZE(class));
1362
1363 return(MR_SUCCESS);
1364}
1365
1366
1367/* fixes the modby field. This will be the second to last thing in the
1368 * argv, the argv length is determined from the query structure. It is
1369 * passed as a pointer to an integer. This will either turn it into a
1370 * username, or # + the users_id.
1371 */
1372followup_fix_modby(q, sq, v, action, actarg, cl)
1373 struct query *q;
1374 register struct save_queue *sq;
1375 struct validate *v;
1376 register int (*action)();
1377 register int actarg;
1378 client *cl;
1379{
1380 register int i, j;
1381 char **argv, *malloc();
1382 int id, status;
1383
1384 i = q->vcnt - 2;
1385 while (sq_get_data(sq, &argv)) {
1386 id = atoi(argv[i]);
1387 if (id > 0)
1388 status = id_to_name(id, "USER", &argv[i]);
1389 else
1390 status = id_to_name(-id, "STRING", &argv[i]);
1391 if (status && status != MR_NO_MATCH)
1392 return(status);
1393 (*action)(q->vcnt, argv, actarg);
1394 for (j = 0; j < q->vcnt; j++)
1395 free(argv[j]);
1396 free(argv);
1397 }
1398 sq_destroy(sq);
1399 return(MR_SUCCESS);
1400}
1401
1402
1403/* After retrieving a user account, fix the modby field and signature.
1404 * The modby field is the second to last thing in the
1405 * argv, the argv length is determined from the query structure. It is
1406 * passed as a pointer to an integer. This will either turn it into a
1407 * username, or # + the users_id. Only "gua*" queries have a signature,
1408 * these are ones with U_END return values. "gub*" queries also use this
1409 * routine but don't have a signature.
1410 */
1411followup_guax(q, sq, v, action, actarg, cl)
1412 struct query *q;
1413 register struct save_queue *sq;
1414 struct validate *v;
1415 register int (*action)();
1416 register int actarg;
1417 client *cl;
1418{
1419 register int i, j;
1420 char **argv, *malloc();
1421#ifdef GDSS
1422 unsigned char sigbuf[256];
1423 char *kname;
1424 SigInfo si;
1425 EXEC SQL BEGIN DECLARE SECTION;
1426 int timestamp, who;
1427 char *login;
1428 varchar struct { short data_size; char data_buf[257];} rsig;
1429 EXEC SQL END DECLARE SECTION;
1430#endif /* GDSS */
1431 int id, status;
1432
1433 i = q->vcnt - 2;
1434 while (sq_get_data(sq, &argv)) {
1435#ifdef DEBUG
1436 com_err(whoami, 0, "argv[SIGNATURE] = \"%s\"", argv[U_SIGNATURE]);
1437#endif /* DEBUG */
1438 id = atoi(argv[i]);
1439 if (id > 0)
1440 status = id_to_name(id, "USER", &argv[i]);
1441 else
1442 status = id_to_name(-id, "STRING", &argv[i]);
1443 if (status && status != MR_NO_MATCH)
1444 return(status);
1445#ifdef GDSS
1446 if (q->vcnt == U_END && strlen(argv[U_SIGNATURE])) {
1447 login = argv[U_NAME];
1448 EXEC SQL REPEATED SELECT signature, sigdate, sigwho
1449 INTO :rsig, :timestamp, :who FROM users
1450 WHERE login = :login;
1451 /** What about (INGRES) error handling? **/
1452 kname = malloc(1);
1453 status = id_to_name(who, "STRING", &kname);
1454 si.timestamp = timestamp;
1455 si.SigInfoVersion = 0; /* XXXXX this isn't used */
1456 kname_parse(si.pname, si.pinst, si.prealm, kname);
1457 free(kname);
1458 rsig.data_buf[rsig.data_size] = 0;
1459 si.rawsig = (unsigned char *)strsave(rsig.data_buf);
1460#ifdef DEBUG
1461 com_err(whoami, 0, "rawsig length = %d, sig=\"%s\"", strlen(si.rawsig), si.rawsig);
1462#endif /* DEBUG */
1463 GDSS_Recompose(&si, sigbuf);
1464 free(si.rawsig);
1465 free(argv[U_SIGNATURE]);
1466 argv[U_SIGNATURE] = strsave(sigbuf);
1467#ifdef DEBUG
1468 com_err(whoami, 0, "generated signature length %d", strlen(sigbuf));
1469#endif /* DEBUG */
1470 }
1471#endif /* GDSS */
1472 (*action)(q->vcnt, argv, actarg);
1473 for (j = 0; j < q->vcnt; j++)
1474 free(argv[j]);
1475 free(argv);
1476 }
1477 sq_destroy(sq);
1478 return(MR_SUCCESS);
1479}
1480
1481
1482/**
1483 ** followup_ausr - add finger and pobox entries, set_user_modtime
1484 **
1485 ** Inputs:
1486 ** argv[0] - login (add_user)
1487 ** argv[3] - last name
1488 ** argv[4] - first name
1489 ** argv[5] - middle name
1490 **
1491 **/
1492
1493followup_ausr(q, argv, cl)
1494 struct query *q;
1495 char *argv[];
1496 client *cl;
1497{
1498 EXEC SQL BEGIN DECLARE SECTION;
1499 int who, status, id;
1500 char *login, *entity, *src, *dst, *name;
1501 char fullname[129];
1502 EXEC SQL END DECLARE SECTION;
1503#ifdef GDSS
1504 char databuf[32], *kname_unparse();
1505 EXEC SQL BEGIN DECLARE SECTION;
1506 char rawsig[128];
1507 int sigwho, timestamp;
1508 EXEC SQL END DECLARE SECTION;
1509 SigInfo si;
1510#endif /* GDSS */
1511
1512 /* build fullname */
1513 if (strlen(argv[4]) && strlen(argv[5]))
1514 sprintf(fullname, "%s %s %s", argv[4], argv[5], argv[3]);
1515 else if (strlen(argv[4]))
1516 sprintf(fullname, "%s %s", argv[4], argv[3]);
1517 else
1518 sprintf(fullname, "%s", argv[3]);
1519
1520#ifdef GDSS
1521 if (q->vcnt == U_END && *argv[U_SIGNATURE]) {
1522 sprintf(databuf, "%s:%s", argv[U_NAME], argv[U_MITID]);
1523 /* skip bytes for timestamp & kname */
1524 si.rawsig = (unsigned char *) rawsig;
1525 status = GDSS_Verify(databuf, strlen(databuf), argv[U_SIGNATURE], &si);
1526 if (strlen(rawsig) > mr_sig_length) {
1527 com_err(whoami, 0, "GDSS signature would be truncated."); /** untested **/
1528 return(MR_INTERNAL);
1529 }
1530 if (status == 0) {
1531 name = kname_unparse(si.pname, si.pinst, si.prealm);
1532 status = name_to_id(name, "STRING", &sigwho);
1533 if (status == MR_NO_MATCH) {
1534 EXEC SQL REPEATED SELECT value INTO :sigwho FROM numvalues
1535 WHERE name='strings_id';
1536 sigwho++;
1537 EXEC SQL REPEATED UPDATE numvalues SET value = :sigwho
1538 WHERE name='strings_id';
1539 EXEC SQL INSERT INTO strings (string_id, string)
1540 VALUES (:sigwho, :name);
1541 } else if (status)
1542 return(gdss2et(status));
1543 timestamp = si.timestamp;
1544 } else
1545 return(gdss2et(status));
1546 } else {
1547 rawsig[0] = 0;
1548 sigwho = 0;
1549 timestamp = 0;
1550 }
1551#endif /* GDSS */
1552
1553 login = argv[0];
1554 who = cl->client_id;
1555 entity = cl->entity;
1556
1557 /* create finger entry, pobox & set modtime on user */
1558#ifdef GDSS
1559 EXEC SQL REPEATED UPDATE users
1560 SET modtime='now', modby=:who, modwith = :entity,
1561 fullname = :fullname, affiliation = type,
1562 signature = :rawsig, sigdate = :timestamp, sigwho = :sigwho,
1563 fmodtime='now', fmodby = :who, fmodwith = :entity,
1564 potype='NONE', pmodtime='now', pmodby = :who, pmodwith = :entity
1565 WHERE login = :login;
1566#else /* GDSS */
1567 EXEC SQL REPEATED UPDATE users
1568 SET modtime='now', modby=:who, modwith = :entity,
1569 fullname = :fullname, affiliation = type,
1570 fmodtime='now', fmodby = :who, fmodwith = :entity,
1571 potype='NONE', pmodtime='now', pmodby = :who, pmodwith = :entity
1572 WHERE login = :login;
1573#endif /* GDSS */
1574
1575 return(MR_SUCCESS);
1576}
1577
1578
1579/**
1580 ** followup_uusr - do signature, set_user_modtime
1581 **
1582 ** Inputs:
1583 ** argv[0] - login (add_user)
1584 ** argv[U_SIGNATURE] - sig
1585 **
1586 **/
1587
1588followup_uuac(q, argv, cl)
1589 struct query *q;
1590 char *argv[];
1591 client *cl;
1592{
1593 EXEC SQL BEGIN DECLARE SECTION;
1594 int who, status, id;
1595 char *entity, *name;
1596 EXEC SQL END DECLARE SECTION;
1597#ifdef GDSS
1598 char databuf[32], *kname_unparse();
1599 EXEC SQL BEGIN DECLARE SECTION;
1600 char rawsig[128];
1601 char *login;
1602 int sigwho, timestamp;
1603 EXEC SQL END DECLARE SECTION;
1604 SigInfo si;
1605#endif /* GDSS */
1606
1607 id = *(int *)argv[0];
1608 who = cl->client_id;
1609 entity = cl->entity;
1610
1611#ifdef GDSS
1612 if (q->vcnt == U_MODTIME && *argv[U_SIGNATURE + 1]) {
1613 login = malloc(1);
1614 status = id_to_name(id, "USER", &login);
1615 sprintf(databuf, "%s:%s", login, argv[U_MITID+1]);
1616 free(login);
1617 /* skip bytes for timestamp & kname */
1618 si.rawsig = (unsigned char *) rawsig;
1619#ifdef DEBUG
1620 com_err(whoami, 0, "verifying sig");
1621#endif /* DEBUG */
1622 status = GDSS_Verify(databuf, strlen(databuf), argv[U_SIGNATURE+1], &si);
1623#ifdef DEBUG
1624 com_err(whoami, 0, "verified");
1625#endif /* DEBUG */
1626 if (strlen(rawsig) > mr_sig_length) {
1627 com_err(whoami, 0, "GDSS signature would be truncated."); /** untested **/
1628 return(MR_INTERNAL);
1629 }
1630 if (status == 0) {
1631 name = kname_unparse(si.pname, si.pinst, si.prealm);
1632 status = name_to_id(name, "STRING", &sigwho);
1633 if (status == MR_NO_MATCH) {
1634 EXEC SQL REPEATED SELECT value INTO :sigwho FROM numvalues
1635 WHERE name='strings_id';
1636 sigwho++;
1637 EXEC SQL REPEATED UPDATE numvalues SET value = :sigwho
1638 WHERE name='strings_id';
1639 EXEC SQL INSERT INTO strings (string_id, string)
1640 VALUES (:sigwho, :name);
1641 } else if (status)
1642 return(gdss2et(status));
1643 timestamp = si.timestamp;
1644 } else
1645 return(gdss2et(status));
1646 } else {
1647 rawsig[0] = 0;
1648 sigwho = 0;
1649 timestamp = 0;
1650 }
1651#endif /* GDSS */
1652
1653 /* create finger entry, pobox & set modtime on user */
1654
1655#ifdef GDSS
1656 EXEC SQL REPEATED UPDATE users SET modtime='now', modby = :who, modwith = :entity,
1657 signature = :rawsig, sigdate = :timestamp, sigwho = :sigwho
1658 WHERE users_id = :id;
1659#else /* GDSS */
1660 EXEC SQL REPEATED UPDATE users SET modtime='now', modby = :who, modwith = :entity
1661 WHERE users_id = :id;
1662#endif /* GDSS */
1663 return(MR_SUCCESS);
1664}
1665
1666
1667/* followup_gpob: fixes argv[2] based on the IDs currently there and the
1668 * type in argv[1]. Then completes the upcall to the user.
1669 *
1670 * argv[2] is of the form "123:234" where the first integer is the machine
1671 * ID if it is a pop box, and the second is the string ID if it is an SMTP
1672 * box. argv[1] should be "POP", "SMTP", or "NONE". Boxes of type NONE
1673 * are skipped.
1674 */
1675
1676followup_gpob(q, sq, v, action, actarg, cl)
1677 register struct query *q;
1678 register struct save_queue *sq;
1679 register struct validate *v;
1680 register int (*action)();
1681 int actarg;
1682 client *cl;
1683{
1684 char **argv, *index();
1685 char *ptype, *p;
1686 int mid, sid, status, i;
1687
1688 /* for each row */
1689 while (sq_get_data(sq, &argv)) {
1690 mr_trim_args(2, argv);
1691 ptype = argv[1];
1692 p = index(argv[2], ':');
1693 *p++ = 0;
1694 mid = atoi(argv[2]);
1695 sid = atoi(p);
1696
1697 if (!strcmp(ptype, "POP")) {
1698 status = id_to_name(mid, "MACHINE", &argv[2]);
1699 if (status == MR_NO_MATCH)
1700 return(MR_MACHINE);
1701 } else if (!strcmp(ptype, "SMTP")) {
1702 status = id_to_name(sid, "STRING", &argv[2]);
1703 if (status == MR_NO_MATCH)
1704 return(MR_STRING);
1705 } else /* ptype == "NONE" */ {
1706 goto skip;
1707 }
1708 if (status) return(status);
1709
1710 if (!strcmp(q->shortname, "gpob")) {
1711 sid = atoi(argv[4]);
1712 if (sid > 0)
1713 status = id_to_name(sid, "USER", &argv[4]);
1714 else
1715 status = id_to_name(-sid, "STRING", &argv[4]);
1716 }
1717 if (status && status != MR_NO_MATCH) return(status);
1718
1719 (*action)(q->vcnt, argv, actarg);
1720 skip:
1721 /* free saved data */
1722 for (i = 0; i < q->vcnt; i++)
1723 free(argv[i]);
1724 free(argv);
1725 }
1726
1727 sq_destroy(sq);
1728 return (MR_SUCCESS);
1729}
1730
1731
1732/* followup_glin: fix the ace_name in argv[8]. argv[7] will contain the
1733 * ace_type: "LIST", "USER", or "NONE". Decode the id in argv[8] into the
1734 * proper name based on the type, and repace that string in the argv.
1735 * Also fixes the modby field by called followup_fix_modby.
1736 */
1737
1738followup_glin(q, sq, v, action, actarg, cl)
1739 register struct query *q;
1740 register struct save_queue *sq;
1741 register struct validate *v;
1742 register int (*action)();
1743 int actarg;
1744 client *cl;
1745{
1746 char **argv, *malloc(), *realloc(), *type;
1747 int id, i, idx, status;
1748
1749 idx = 8;
1750 if (!strcmp(q->shortname, "gsin"))
1751 idx = 12;
1752
1753 while (sq_get_data(sq, &argv)) {
1754 mr_trim_args(q->vcnt, argv);
1755
1756 id = atoi(argv[i = q->vcnt - 2]);
1757 if (id > 0)
1758 status = id_to_name(id, "USER", &argv[i]);
1759 else
1760 status = id_to_name(-id, "STRING", &argv[i]);
1761 if (status && status != MR_NO_MATCH)
1762 return(status);
1763
1764 id = atoi(argv[idx]);
1765 type = argv[idx - 1];
1766
1767 if (!strcmp(type, "LIST")) {
1768 status = id_to_name(id, "LIST", &argv[idx]);
1769 } else if (!strcmp(type, "USER")) {
1770 status = id_to_name(id, "USER", &argv[idx]);
1771 } else if (!strcmp(type, "KERBEROS")) {
1772 status = id_to_name(id, "STRING", &argv[idx]);
1773 } else if (!strcmp(type, "NONE")) {
1774 status = 0;
1775 free(argv[idx]);
1776 argv[idx] = strsave("NONE");
1777 } else {
1778 status = 0;
1779 free(argv[idx]);
1780 argv[idx] = strsave("???");
1781 }
1782 if (status && status != MR_NO_MATCH)
1783 return(status);
1784
1785 if (!strcmp(q->shortname, "glin") && atoi(argv[6]) == -1) {
1786 argv[6] = realloc(argv[6], strlen(UNIQUE_GID) + 1);
1787 strcpy(argv[6], UNIQUE_GID);
1788 }
1789
1790 /* send the data */
1791 (*action)(q->vcnt, argv, actarg);
1792
1793 /* free saved data */
1794 for (i = 0; i < q->vcnt; i++)
1795 free(argv[i]);
1796 free(argv);
1797 }
1798
1799 sq_destroy(sq);
1800 return (MR_SUCCESS);
1801}
1802
1803
1804/* followup_gqot: Fix the entity name, directory name & modby fields
1805 * argv[0] = filsys_id
1806 * argv[1] = type
1807 * argv[2] = entity_id
1808 * argv[3] = ascii(quota)
1809 */
1810
1811followup_gqot(q, sq, v, action, actarg, cl)
1812 struct query *q;
1813 register struct save_queue *sq;
1814 struct validate *v;
1815 register int (*action)();
1816 register int actarg;
1817 client *cl;
1818{
1819 register int j;
1820 char **argv, *malloc();
1821 EXEC SQL BEGIN DECLARE SECTION;
1822 int id;
1823 char *name, *label;
1824 EXEC SQL END DECLARE SECTION;
1825 int status, idx;
1826
1827 if (!strcmp(q->name, "get_quota") ||
1828 !strcmp(q->name, "get_quota_by_filesys"))
1829 idx = 4;
1830 else
1831 idx = 3;
1832 while (sq_get_data(sq, &argv)) {
1833 if (idx == 4) {
1834 switch (argv[1][0]) {
1835 case 'U':
1836 status = id_to_name(atoi(argv[2]), "USER", &argv[2]);
1837 break;
1838 case 'G':
1839 case 'L':
1840 status = id_to_name(atoi(argv[2]), "LIST", &argv[2]);
1841 break;
1842 case 'A':
1843 free(argv[2]);
1844 argv[2] = strsave("system:anyuser");
1845 break;
1846 default:
1847 id = atoi(argv[2]);
1848 argv[2] = malloc(8);
1849 sprintf(argv[2], "%d", id);
1850 }
1851 }
1852 id = atoi(argv[idx]);
1853 free(argv[idx]);
1854 argv[idx] = malloc(256);
1855 name = argv[idx];
1856 if (id == 0) {
1857 label = argv[0];
1858 EXEC SQL REPEATED SELECT name INTO :name FROM filesys
1859 WHERE label = :label;
1860 } else {
1861 EXEC SQL REPEATED SELECT dir INTO :name FROM nfsphys
1862 WHERE nfsphys_id = :id;
1863 }
1864 if (sqlca.sqlerrd[2] != 1) {
1865 sprintf(argv[idx], "#%d", id);
1866 }
1867
1868 id = atoi(argv[idx+3]);
1869 if (id > 0)
1870 status = id_to_name(id, "USER", &argv[idx+3]);
1871 else
1872 status = id_to_name(-id, "STRING", &argv[idx+3]);
1873 if (status && status != MR_NO_MATCH)
1874 return(status);
1875 (*action)(q->vcnt, argv, actarg);
1876 for (j = 0; j < q->vcnt; j++)
1877 free(argv[j]);
1878 free(argv);
1879 }
1880 sq_destroy(sq);
1881 return(MR_SUCCESS);
1882}
1883
1884
1885/* followup_aqot: Add allocation to nfsphys after creating quota.
1886 * argv[0] = filsys_id
1887 * argv[1] = type if "add_quota" or "update_quota"
1888 * argv[2 or 1] = id
1889 * argv[3 or 2] = ascii(quota)
1890 */
1891
1892followup_aqot(q, argv, cl)
1893 struct query *q;
1894 char **argv;
1895 client *cl;
1896{
1897 EXEC SQL BEGIN DECLARE SECTION;
1898 int quota, id, fs, who, physid;
1899 char *entity, *qtype, *table_name;
1900 EXEC SQL END DECLARE SECTION;
1901 char incr_qual[60];
1902 char *incr_argv[2];
1903 int status;
1904
1905 table_name=q->rtable;
1906 fs = *(int *)argv[0];
1907 EXEC SQL REPEATED SELECT phys_id INTO :physid FROM filesys
1908 WHERE filsys_id = :fs;
1909 if(ingres_errno)
1910 return(mr_errcode);
1911
1912 if (!strcmp(q->shortname, "aqot") || !strcmp(q->shortname, "uqot")) {
1913 qtype = argv[1];
1914 id = *(int *)argv[2];
1915 quota = atoi(argv[3]);
1916 sprintf(incr_qual,"q.filsys_id = %d",fs);
1917 } else {
1918 qtype = "USER";
1919 id = *(int *)argv[1];
1920 quota = atoi(argv[2]);
1921 sprintf(incr_qual,"q.filsys_id=%d AND q.type='%s' AND q.entity_id=%d",
1922 fs,qtype,id);
1923 }
1924
1925 /* quota case of incremental_{before|after} only looks at slot 1 */
1926 incr_argv[1]=qtype;
1927
1928 /* Follows one of many possible gross hacks to fix these particular
1929 * conflicts between what is possible in the query table and what
1930 * is possible in SQL.
1931 */
1932 if(q->type==APPEND) {
1933 incremental_clear_before();
1934 EXEC SQL INSERT INTO quota
1935 (filsys_id, type, entity_id, quota, phys_id)
1936 VALUES (:fs, :qtype, :id, :quota, :physid);
1937 incremental_after(table_name, incr_qual, incr_argv);
1938 } else {
1939 incremental_before(table_name, incr_qual, incr_argv);
1940 EXEC SQL UPDATE quota SET quota = :quota
1941 WHERE filsys_id = :fs AND type = :qtype AND entity_id = :id;
1942 status = mr_errcode;
1943 incremental_after(table_name, incr_qual, incr_argv);
1944 }
1945
1946 if (ingres_errno)
1947 return(mr_errcode);
1948 flush_name(argv[0], q->rtable);
1949 if(q->type==APPEND) {
1950 EXEC SQL UPDATE tblstats SET appends = appends + 1, modtime = 'now'
1951 WHERE table_name = :table_name;
1952 } else {
1953 EXEC SQL UPDATE tblstats SET updates = updates + 1, modtime = 'now'
1954 WHERE table_name = :table_name;
1955 }
1956
1957 /* Proceed with original followup */
1958 who = cl->client_id;
1959 entity = cl->entity;
1960
1961 EXEC SQL REPEATED UPDATE quota
1962 SET modtime = 'now', modby = :who, modwith = :entity
1963 WHERE filsys_id = :fs and type = :qtype and entity_id = :id;
1964 EXEC SQL REPEATED UPDATE nfsphys SET allocated = allocated + :quota
1965 WHERE nfsphys_id = :physid;
1966 if (ingres_errno) return(mr_errcode);
1967 return(MR_SUCCESS);
1968}
1969
1970
1971/* Necessitated by the requirement of a correlation name by the incremental
1972 * routines, since query table deletes don't provide one.
1973 */
1974followup_dqot(q,argv,cl)
1975 struct query *q;
1976 char **argv;
1977 struct client *cl;
1978{
1979 char *qtype;
1980 int id, fs;
1981 char *incr_argv[2];
1982 EXEC SQL BEGIN DECLARE SECTION;
1983 char incr_qual[80];
1984 char *tblname;
1985 EXEC SQL END DECLARE SECTION;
1986
1987 fs = *(int *)argv[0];
1988 if (!strcmp(q->shortname, "dqot")) {
1989 qtype = argv[1];
1990 id = *(int *)argv[2];
1991 } else {
1992 qtype = "USER";
1993 id = *(int *)argv[1];
1994 }
1995 sprintf(incr_qual,"q.filsys_id=%d AND q.type='%s' AND q.entity_id=%d",
1996 fs,qtype,id);
1997
1998 /* quota case of incremental_{before|after} only looks at slot 1 */
1999 incr_argv[1]=qtype;
2000
2001 incremental_before(q->rtable, incr_qual, incr_argv);
2002 EXEC SQL DELETE FROM quota q WHERE :incr_qual;
2003 incremental_clear_after();
2004
2005 if (ingres_errno)
2006 return(mr_errcode);
2007 flush_name(argv[0], q->rtable);
2008
2009 tblname = q->rtable;
2010 EXEC SQL UPDATE tblstats SET deletes = deletes + 1, modtime = 'now'
2011 WHERE table_name = :tblname;
2012 return(MR_SUCCESS);
2013}
2014
2015
2016followup_gpce(q, sq, v, action, actarg, cl)
2017 struct query *q;
2018 register struct save_queue *sq;
2019 struct validate *v;
2020 register int (*action)();
2021 register int actarg;
2022 client *cl;
2023{
2024 register int i, j;
2025 char **argv, *malloc();
2026 int id, status;
2027
2028 i = q->vcnt - 2;
2029 while (sq_get_data(sq, &argv)) {
2030 id = atoi(argv[PCAP_QSERVER]);
2031 status = id_to_name(id, "MACHINE", &argv[PCAP_QSERVER]);
2032 if (status) return (status);
2033 id = atoi(argv[i]);
2034 if (id > 0)
2035 status = id_to_name(id, "USER", &argv[i]);
2036 else
2037 status = id_to_name(-id, "STRING", &argv[i]);
2038 if (status && status != MR_NO_MATCH)
2039 return(status);
2040 (*action)(q->vcnt, argv, actarg);
2041 for (j = 0; j < q->vcnt; j++)
2042 free(argv[j]);
2043 free(argv);
2044 }
2045 sq_destroy(sq);
2046 return(MR_SUCCESS);
2047}
2048
2049
2050/* followup_gzcl:
2051 */
2052
2053followup_gzcl(q, sq, v, action, actarg, cl)
2054 register struct query *q;
2055 register struct save_queue *sq;
2056 register struct validate *v;
2057 register int (*action)();
2058 int actarg;
2059 client *cl;
2060{
2061 int id, i, status;
2062 char **argv;
2063
2064 while (sq_get_data(sq, &argv)) {
2065 mr_trim_args(q->vcnt, argv);
2066
2067 id = atoi(argv[i = q->vcnt - 2]);
2068 if (id > 0)
2069 status = id_to_name(id, "USER", &argv[i]);
2070 else
2071 status = id_to_name(-id, "STRING", &argv[i]);
2072 if (status && status != MR_NO_MATCH)
2073 return(status);
2074
2075 for (i = 1; i < 8; i+=2) {
2076 id = atoi(argv[i+1]);
2077 if (!strcmp(argv[i], "LIST")) {
2078 status = id_to_name(id, "LIST", &argv[i+1]);
2079 } else if (!strcmp(argv[i], "USER")) {
2080 status = id_to_name(id, "USER", &argv[i+1]);
2081 } else if (!strcmp(argv[i], "KERBEROS")) {
2082 status = id_to_name(id, "STRING", &argv[i+1]);
2083 } else if (!strcmp(argv[i], "NONE")) {
2084 status = 0;
2085 free(argv[i+1]);
2086 argv[i+1] = strsave("NONE");
2087 } else {
2088 status = 0;
2089 free(argv[i+1]);
2090 argv[i+1] = strsave("???");
2091 }
2092 if (status && status != MR_NO_MATCH)
2093 return(status);
2094 }
2095
2096 /* send the data */
2097 (*action)(q->vcnt, argv, actarg);
2098
2099 /* free saved data */
2100 for (i = 0; i < q->vcnt; i++)
2101 free(argv[i]);
2102 free(argv);
2103 }
2104 sq_destroy(sq);
2105 return(MR_SUCCESS);
2106}
2107
2108
2109/* followup_gsha:
2110 */
2111
2112followup_gsha(q, sq, v, action, actarg, cl)
2113 register struct query *q;
2114 register struct save_queue *sq;
2115 register struct validate *v;
2116 register int (*action)();
2117 int actarg;
2118 client *cl;
2119{
2120 char **argv;
2121 int i, id, status;
2122
2123 while (sq_get_data(sq, &argv)) {
2124 mr_trim_args(q->vcnt, argv);
2125
2126 id = atoi(argv[4]);
2127 if (id > 0)
2128 status = id_to_name(id, "USER", &argv[4]);
2129 else
2130 status = id_to_name(-id, "STRING", &argv[4]);
2131 if (status && status != MR_NO_MATCH)
2132 return(status);
2133
2134 id = atoi(argv[2]);
2135 if (!strcmp(argv[1], "LIST")) {
2136 status = id_to_name(id, "LIST", &argv[2]);
2137 } else if (!strcmp(argv[1], "USER")) {
2138 status = id_to_name(id, "USER", &argv[2]);
2139 } else if (!strcmp(argv[1], "KERBEROS")) {
2140 status = id_to_name(id, "STRING", &argv[2]);
2141 } else if (!strcmp(argv[1], "NONE")) {
2142 status = 0;
2143 free(argv[2]);
2144 argv[2] = strsave("NONE");
2145 } else {
2146 status = 0;
2147 free(argv[2]);
2148 argv[2] = strsave("???");
2149 }
2150 if (status && status != MR_NO_MATCH)
2151 return(status);
2152
2153 /* send the data */
2154 (*action)(q->vcnt, argv, actarg);
2155
2156 /* free saved data */
2157 for (i = 0; i < q->vcnt; i++)
2158 free(argv[i]);
2159 free(argv);
2160 }
2161 sq_destroy(sq);
2162 return(MR_SUCCESS);
2163}
2164
2165
2166\f
2167/* Special query routines */
2168
2169/* set_pobox - this does all of the real work.
2170 * argv = user_id, type, box
2171 * if type is POP, then box should be a machine, and its ID should be put in
2172 * pop_id. If type is SMTP, then box should be a string and its ID should
2173 * be put in box_id. If type is NONE, then box doesn't matter.
2174 */
2175
2176int set_pobox(q, argv, cl)
2177 struct query *q;
2178 char **argv;
2179 client *cl;
2180{
2181 EXEC SQL BEGIN DECLARE SECTION;
2182 int user, id;
2183 char *box, potype[9];
2184 EXEC SQL END DECLARE SECTION;
2185 int status;
2186
2187 box = argv[2];
2188 user = *(int *)argv[0];
2189
2190 EXEC SQL REPEATED SELECT pop_id, potype INTO :id, :potype FROM users
2191 WHERE users_id = :user;
2192 if (ingres_errno) return(mr_errcode);
2193 if (!strcmp(strtrim(potype), "POP"))
2194 set_pop_usage(id, -1);
2195
2196 if (!strcmp(argv[1], "POP")) {
2197 status = name_to_id(box, "MACHINE", &id);
2198 if (status == MR_NO_MATCH)
2199 return(MR_MACHINE);
2200 else if (status)
2201 return(status);
2202 EXEC SQL REPEATED UPDATE users SET potype = 'POP', pop_id = :id
2203 WHERE users_id = :user;
2204 set_pop_usage(id, 1);
2205 } else if (!strcmp(argv[1], "SMTP")) {
2206 if (index(box, '/') || index(box, '|'))
2207 return(MR_BAD_CHAR);
2208 status = name_to_id(box, "STRING", &id);
2209 if (status == MR_NO_MATCH) {
2210 EXEC SQL REPEATED SELECT value INTO :id FROM numvalues
2211 WHERE name='strings_id';
2212 id++;
2213 EXEC SQL REPEATED UPDATE numvalues SET value = :id
2214 WHERE name='strings_id';
2215 EXEC SQL INSERT INTO strings (string_id, string)
2216 VALUES (:id, :box);
2217 } else if (status)
2218 return(status);
2219 EXEC SQL REPEATED UPDATE users SET potype='SMTP', box_id = :id
2220 WHERE users_id = :user;
2221 } else /* argv[1] == "NONE" */ {
2222 EXEC SQL REPEATED UPDATE users SET potype='NONE'
2223 WHERE users_id = :user;
2224 }
2225
2226 set_pobox_modtime(q, argv, cl);
2227 EXEC SQL REPEATED UPDATE tblstats SET updates = updates+1, modtime='now'
2228 WHERE table_name='users';
2229 if (ingres_errno) return(mr_errcode);
2230 return(MR_SUCCESS);
2231}
2232
2233
2234/* get_list_info: passed a wildcard list name, returns lots of stuff about
2235 * each list. This is tricky: first build a queue of all requested
2236 * data. Rest of processing consists of fixing gid, ace_name, and modby.
2237 */
2238
2239get_list_info(q, aargv, cl, action, actarg)
2240 register struct query *q;
2241 char **aargv;
2242 client *cl;
2243 register int (*action)();
2244 int actarg;
2245{
2246 char *argv[13], *malloc(), *realloc();
2247 EXEC SQL BEGIN DECLARE SECTION;
2248 char *name, acl_type[9], listname[33], active[5], public[5], hidden[5];
2249 char maillist[5], grouplist[5], gid_str[6], acl_name[256], desc[256];
2250 char modtime[27], modby[256], modwith[9];
2251 int id, rowcount, acl_id, hid, modby_id;
2252 char qual[80];
2253 EXEC SQL END DECLARE SECTION;
2254 int returned, status;
2255 struct save_queue *sq, *sq_create();
2256
2257 returned = rowcount = 0;
2258 name = aargv[0];
2259 convert_wildcards(name);
2260
2261 sq = sq_create();
2262 sprintf(qual,"name LIKE '%s' ESCAPE '*'",name);
2263 optimize_sql_stmt(qual);
2264 EXEC SQL DECLARE csr102 CURSOR FOR SELECT list_id FROM list
2265 WHERE :qual;
2266 EXEC SQL OPEN csr102;
2267 while(1)
2268 {
2269 EXEC SQL FETCH csr102 INTO :id;
2270 if(sqlca.sqlcode!=0) break;
2271 sq_save_data(sq, id);
2272 rowcount++;
2273 }
2274 EXEC SQL CLOSE csr102;
2275
2276 if (ingres_errno) return(mr_errcode);
2277 if (rowcount == 0)
2278 return(MR_NO_MATCH);
2279
2280 argv[0] = listname; argv[1] = active; argv[2] = public; argv[3] = hidden;
2281 argv[4] = maillist; argv[5] = grouplist; argv[6] = gid_str;
2282 argv[7] = acl_type; argv[9] = desc; argv[10] = modtime; argv[12] = modwith;
2283
2284 while (sq_get_data(sq, &id)) {
2285 if (id == 0)
2286 continue;
2287 argv[6] = gid_str;
2288 EXEC SQL REPEATED SELECT name, CHAR(active), CHAR(publicflg),
2289 CHAR(hidden), hidden, CHAR(maillist), CHAR(grouplist), CHAR(gid),
2290 TRIM(acl_type), acl_id, description, CHAR(modtime), modby, modwith
2291 INTO :listname, :active, :public, :hidden, :hid, :maillist,
2292 :grouplist, :gid_str, :acl_type, :acl_id, :desc,
2293 :modtime, :modby_id, :modwith
2294 FROM list WHERE list_id = :id;
2295
2296 if (ingres_errno) return(mr_errcode);
2297
2298 if (atoi(gid_str) == -1)
2299 argv[6] = UNIQUE_GID;
2300
2301 argv[8] = malloc(0);
2302 if (!strcmp(acl_type, "LIST")) {
2303 status = id_to_name(acl_id, "LIST", &argv[8]);
2304 } else if (!strcmp(acl_type, "USER")) {
2305 status = id_to_name(acl_id, "USER", &argv[8]);
2306 } else if (!strcmp(acl_type, "KERBEROS")) {
2307 status = id_to_name(acl_id, "STRING", &argv[8]);
2308 } else if (!strcmp(acl_type, "NONE")) {
2309 status = 0;
2310 free(argv[8]);
2311 argv[8] = strsave("NONE");
2312 } else {
2313 status = 0;
2314 free(argv[8]);
2315 argv[8] = strsave("???");
2316 }
2317 if (status && status != MR_NO_MATCH) return(status);
2318
2319 argv[11] = malloc(0);
2320 if (modby_id > 0)
2321 status = id_to_name(modby_id, "USER", &argv[11]);
2322 else
2323 status = id_to_name(-modby_id, "STRING", &argv[11]);
2324 if (status && status != MR_NO_MATCH) return(status);
2325
2326 mr_trim_args(q->vcnt, argv);
2327 returned++;
2328 (*action)(q->vcnt, argv, actarg);
2329 free(argv[8]);
2330 free(argv[11]);
2331 }
2332
2333 sq_destroy(sq);
2334 if (ingres_errno) return(mr_errcode);
2335 return (MR_SUCCESS);
2336}
2337
2338
2339/* Add_member_to_list: do list flattening as we go! MAXLISTDEPTH is
2340 * how many different ancestors a member is allowed to have.
2341 */
2342
2343#define MAXLISTDEPTH 1024
2344
2345int add_member_to_list(q, argv, cl)
2346 struct query *q;
2347 char **argv;
2348 client *cl;
2349{
2350 EXEC SQL BEGIN DECLARE SECTION;
2351 int id, lid, mid, error, who, ref, rowcnt;
2352 char *mtype, dtype[9], *entity;
2353 EXEC SQL END DECLARE SECTION;
2354 int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a;
2355 int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d;
2356 int status;
2357 char *dtypes[MAXLISTDEPTH];
2358 char *iargv[3], *buf;
2359
2360 lid = *(int *)argv[0];
2361 mtype = argv[1];
2362 mid = *(int *)argv[2];
2363 /* if the member is already a direct member of the list, punt */
2364 EXEC SQL REPEATED SELECT COUNT(list_id) INTO :rowcnt FROM imembers
2365 WHERE list_id = :lid AND member_id = :mid
2366 AND member_type = :mtype AND direct = 1;
2367 if (rowcnt > 0)
2368 return(MR_EXISTS);
2369 if (!strcasecmp(mtype, "STRING")) {
2370 buf = malloc(0);
2371 status = id_to_name(mid, "STRING", &buf);
2372 if (status) return(status);
2373 if (index(buf, '/') || index(buf, '|')) {
2374 free(buf);
2375 return(MR_BAD_CHAR);
2376 }
2377 free(buf);
2378 }
2379
2380 ancestors[0] = lid;
2381 aref[0] = 1;
2382 acount = 1;
2383 EXEC SQL DECLARE csr103 CURSOR FOR
2384 SELECT list_id, ref_count FROM imembers
2385 WHERE member_id = :lid AND member_type='LIST';
2386 EXEC SQL OPEN csr103;
2387 while(1) {
2388 EXEC SQL FETCH csr103 INTO :id, :ref;
2389 if(sqlca.sqlcode != 0) break;
2390 aref[acount] = ref;
2391 ancestors[acount++] = id;
2392 if (acount >= MAXLISTDEPTH) break;
2393 }
2394 EXEC SQL CLOSE csr103;
2395 if (ingres_errno) return(mr_errcode);
2396 if (acount >= MAXLISTDEPTH) {
2397 return(MR_INTERNAL);
2398 }
2399 descendants[0] = mid;
2400 dtypes[0] = mtype;
2401 dref[0] = 1;
2402 dcount = 1;
2403 error = 0;
2404 if (!strcmp(mtype, "LIST")) {
2405 EXEC SQL DECLARE csr104 CURSOR FOR
2406 SELECT member_id, member_type, ref_count
2407 FROM imembers
2408 WHERE list_id = :mid;
2409 EXEC SQL OPEN csr104;
2410 while(1) {
2411 EXEC SQL FETCH csr104 INTO :id, :dtype, :ref;
2412 if(sqlca.sqlcode != 0) break;
2413 switch (dtype[0]) {
2414 case 'L':
2415 dtypes[dcount] = "LIST";
2416 break;
2417 case 'U':
2418 dtypes[dcount] = "USER";
2419 break;
2420 case 'S':
2421 dtypes[dcount] = "STRING";
2422 break;
2423 case 'K':
2424 dtypes[dcount] = "KERBEROS";
2425 break;
2426 default:
2427 error++;
2428 break;
2429 }
2430 dref[dcount] = ref;
2431 descendants[dcount++] = id;
2432 if (dcount >= MAXLISTDEPTH) {
2433 error++;
2434 break;
2435 }
2436 }
2437 EXEC SQL CLOSE csr104;
2438 if (ingres_errno) return(mr_errcode);
2439 if (error)
2440 return(MR_INTERNAL);
2441 }
2442 for (a = 0; a < acount; a++) {
2443 lid = ancestors[a];
2444 for (d = 0; d < dcount; d++) {
2445 mid = descendants[d];
2446 mtype = dtypes[d];
2447 if (mid == lid && !strcmp(mtype, "LIST")) {
2448 return(MR_LISTLOOP);
2449 }
2450 EXEC SQL REPEATED SELECT COUNT(ref_count) INTO :rowcnt
2451 FROM imembers
2452 WHERE list_id = :lid AND member_id = :mid
2453 AND member_type = :mtype;
2454 ref = aref[a] * dref[d];
2455 if (rowcnt > 0) {
2456 if (a == 0 && d == 0) {
2457 EXEC SQL UPDATE imembers
2458 SET ref_count = ref_count+:ref, direct=1
2459 WHERE list_id = :lid AND member_id = :mid
2460 AND member_type = :mtype;
2461 } else {
2462 EXEC SQL UPDATE imembers
2463 SET ref_count = ref_count+:ref
2464 WHERE list_id = :lid AND member_id = :mid
2465 AND member_type = :mtype;
2466 }
2467 } else {
2468 incremental_clear_before();
2469 if (a == 0 && d == 0) {
2470 EXEC SQL INSERT INTO imembers
2471 (list_id, member_id, direct, member_type, ref_count)
2472 VALUES (:lid, :mid, 1, :mtype, 1);
2473 } else {
2474 EXEC SQL INSERT INTO imembers
2475 (list_id, member_id, member_type, ref_count)
2476 VALUES (:lid, :mid, :mtype, 1);
2477 }
2478 iargv[0] = (char *)lid;
2479 iargv[1] = mtype;
2480 iargv[2] = (char *)mid;
2481 incremental_after("members", 0, iargv);
2482 }
2483 }
2484 }
2485 lid = *(int *)argv[0];
2486 entity = cl->entity;
2487 who = cl->client_id;
2488 EXEC SQL REPEATED UPDATE list
2489 SET modtime='now', modby = :who, modwith = :entity
2490 WHERE list_id = :lid;
2491 if (ingres_errno) return(mr_errcode);
2492 return(MR_SUCCESS);
2493}
2494
2495
2496/* Delete_member_from_list: do list flattening as we go!
2497 */
2498
2499int delete_member_from_list(q, argv, cl)
2500 struct query *q;
2501 char **argv;
2502 client *cl;
2503{
2504 EXEC SQL BEGIN DECLARE SECTION;
2505 int id, lid, mid, cnt, error, who, ref;
2506 char *mtype, dtype[9], *entity;
2507 EXEC SQL END DECLARE SECTION;
2508 int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a;
2509 int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d;
2510 char *dtypes[MAXLISTDEPTH];
2511 char *iargv[3];
2512
2513 lid = *(int *)argv[0];
2514 mtype = argv[1];
2515 mid = *(int *)argv[2];
2516 /* if the member is not a direct member of the list, punt */
2517 EXEC SQL REPEATED SELECT COUNT(list_id) INTO :cnt FROM imembers
2518 WHERE list_id = :lid AND member_id = :mid
2519 AND member_type = :mtype AND direct = 1;
2520 if (ingres_errno) return(mr_errcode);
2521 if (cnt == 0)
2522 return(MR_NO_MATCH);
2523 ancestors[0] = lid;
2524 aref[0] = 1;
2525 acount = 1;
2526 EXEC SQL DECLARE csr105 CURSOR FOR
2527 SELECT list_id, ref_count FROM imembers
2528 WHERE member_id = :lid AND member_type = 'LIST';
2529 EXEC SQL OPEN csr105;
2530 while(1) {
2531 EXEC SQL FETCH csr105 INTO :id, :ref;
2532 if(sqlca.sqlcode!=0) break;
2533 aref[acount] = ref;
2534 ancestors[acount++] = id;
2535 if (acount >= MAXLISTDEPTH) break;
2536 }
2537 EXEC SQL CLOSE csr105;
2538 if (ingres_errno)
2539 return(mr_errcode);
2540 if (acount >= MAXLISTDEPTH)
2541 return(MR_INTERNAL);
2542 descendants[0] = mid;
2543 dtypes[0] = mtype;
2544 dref[0] = 1;
2545 dcount = 1;
2546 error = 0;
2547 if (!strcmp(mtype, "LIST")) {
2548 EXEC SQL DECLARE csr106 CURSOR FOR
2549 SELECT member_id, member_type, ref_count FROM imembers
2550 WHERE list_id = :mid;
2551 EXEC SQL OPEN csr106;
2552 while(1) {
2553 EXEC SQL FETCH csr106 INTO :id, :dtype, :ref;
2554 if(sqlca.sqlcode!=0) break;
2555 switch (dtype[0]) {
2556 case 'L':
2557 dtypes[dcount] = "LIST";
2558 break;
2559 case 'U':
2560 dtypes[dcount] = "USER";
2561 break;
2562 case 'S':
2563 dtypes[dcount] = "STRING";
2564 break;
2565 case 'K':
2566 dtypes[dcount] = "KERBEROS";
2567 break;
2568 default:
2569 error++;
2570 break;
2571 }
2572 dref[dcount] = ref;
2573 descendants[dcount++] = id;
2574 if (dcount >= MAXLISTDEPTH) break;
2575 }
2576 EXEC SQL CLOSE csr106;
2577 if (ingres_errno)
2578 return(mr_errcode);
2579 if (error)
2580 return(MR_INTERNAL);
2581 }
2582 for (a = 0; a < acount; a++) {
2583 lid = ancestors[a];
2584 for (d = 0; d < dcount; d++) {
2585 mid = descendants[d];
2586 mtype = dtypes[d];
2587 if (mid == lid && !strcmp(mtype, "LIST")) {
2588 return(MR_LISTLOOP);
2589 }
2590 EXEC SQL REPEATED SELECT ref_count INTO :cnt FROM imembers
2591 WHERE list_id = :lid AND member_id = :mid AND member_type = :mtype;
2592 ref = aref[a] * dref[d];
2593 if (cnt <= ref) {
2594 iargv[0] = (char *)lid;
2595 iargv[1] = mtype;
2596 iargv[2] = (char *)mid;
2597 incremental_before("members", 0, iargv);
2598 EXEC SQL DELETE FROM imembers
2599 WHERE list_id = :lid AND member_id = :mid
2600 AND member_type= :mtype;
2601 incremental_clear_after();
2602 } else if (a == 0 && d == 0) {
2603 EXEC SQL UPDATE imembers
2604 SET ref_count = ref_count - :ref, direct = 0
2605 WHERE list_id = :lid AND member_id = :mid
2606 AND member_type = :mtype;
2607 } else {
2608 EXEC SQL UPDATE imembers
2609 SET ref_count = ref_count - :ref
2610 WHERE list_id = :lid AND member_id = :mid
2611 AND member_type = :mtype;
2612 }
2613 }
2614 }
2615 lid = *(int *)argv[0];
2616 entity = cl->entity;
2617 who = cl->client_id;
2618 EXEC SQL UPDATE list SET modtime = 'now', modby = :who, modwith = :entity
2619 WHERE list_id = :lid;
2620 if (ingres_errno) return(mr_errcode);
2621 return(MR_SUCCESS);
2622}
2623
2624
2625/* get_ace_use - given a type and a name, return a type and a name.
2626 * The ace_type is one of "LIST", "USER", "RLIST", or "RUSER" in argv[0],
2627 * and argv[1] will contain the ID of the entity in question. The R*
2628 * types mean to recursively look at every containing list, not just
2629 * when the object in question is a direct member. On return, the
2630 * usage type will be one of LIST, SERVICE, FILESYS, QUOTA, QUERY, or ZEPHYR.
2631 */
2632
2633int get_ace_use(q, argv, cl, action, actarg)
2634 struct query *q;
2635 char *argv[];
2636 client *cl;
2637 int (*action)();
2638 int actarg;
2639{
2640 int found = 0;
2641 EXEC SQL BEGIN DECLARE SECTION;
2642 char *atype;
2643 int aid, listid, id;
2644 EXEC SQL END DECLARE SECTION;
2645 struct save_queue *sq, *sq_create();
2646
2647 atype = argv[0];
2648 aid = *(int *)argv[1];
2649 if (!strcmp(atype, "LIST") || !strcmp(atype, "USER") ||
2650 !strcmp(atype, "KERBEROS")) {
2651 return(get_ace_internal(atype, aid, action, actarg));
2652 }
2653
2654 sq = sq_create();
2655 if (!strcmp(atype, "RLIST")) {
2656 sq_save_data(sq, aid);
2657 /* get all the list_id's of containing lists */
2658 EXEC SQL DECLARE csr107 CURSOR FOR
2659 SELECT list_id FROM imembers
2660 WHERE member_type='LIST' AND member_id = :aid;
2661 EXEC SQL OPEN csr107;
2662 while(1) {
2663 EXEC SQL FETCH csr107 INTO :listid;
2664 if(sqlca.sqlcode != 0) break;
2665 sq_save_unique_data(sq, listid);
2666 }
2667 EXEC SQL CLOSE csr107;
2668 /* now process each one */
2669 while (sq_get_data(sq, &id)) {
2670 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2671 found++;
2672 }
2673 }
2674
2675 if (!strcmp(atype, "RUSER")) {
2676 EXEC SQL DECLARE csr108 CURSOR FOR
2677 SELECT list_id FROM imembers
2678 WHERE member_type='USER' AND member_id = :aid;
2679 EXEC SQL OPEN csr108;
2680 while(1) {
2681 EXEC SQL FETCH csr108 INTO :listid;
2682 if(sqlca.sqlcode != 0) break;
2683 sq_save_data(sq, listid);
2684 }
2685 EXEC SQL CLOSE csr108;
2686 /* now process each one */
2687 while (sq_get_data(sq, &id)) {
2688 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2689 found++;
2690 }
2691 if (get_ace_internal("USER", aid, action, actarg) == MR_SUCCESS)
2692 found++;
2693 }
2694
2695 if (!strcmp(atype, "RKERBERO")) {
2696 EXEC SQL DECLARE csr109 CURSOR FOR
2697 SELECT list_id FROM imembers
2698 WHERE member_type='KERBEROS' AND member_id = :aid;
2699 EXEC SQL OPEN csr109;
2700 while(1) {
2701 EXEC SQL FETCH csr109 INTO :listid;
2702 if(sqlca.sqlcode != 0) break;
2703 sq_save_data(sq, listid);
2704 }
2705 EXEC SQL CLOSE csr109;
2706 /* now process each one */
2707 while (sq_get_data(sq, &id)) {
2708 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2709 found++;
2710 }
2711 if (get_ace_internal("KERBEROS", aid, action, actarg) == MR_SUCCESS)
2712 found++;
2713 }
2714
2715 sq_destroy(sq);
2716 if (ingres_errno) return(mr_errcode);
2717 if (!found) return(MR_NO_MATCH);
2718 return(MR_SUCCESS);
2719}
2720
2721
2722/* This looks up a single list or user for ace use. atype must be "USER"
2723 * or "LIST", and aid is the ID of the corresponding object. This is used
2724 * by get_ace_use above.
2725 */
2726
2727get_ace_internal(atype, aid, action, actarg)
2728 EXEC SQL BEGIN DECLARE SECTION;
2729 char *atype;
2730 int aid;
2731 EXEC SQL END DECLARE SECTION;
2732 int (*action)();
2733 int actarg;
2734{
2735 char *rargv[2];
2736 int found = 0;
2737 EXEC SQL BEGIN DECLARE SECTION;
2738 char name[33];
2739 EXEC SQL END DECLARE SECTION;
2740
2741 rargv[1] = name;
2742 if (!strcmp(atype, "LIST")) {
2743 rargv[0] = "FILESYS";
2744 EXEC SQL DECLARE csr110 CURSOR FOR
2745 SELECT label FROM filesys
2746 WHERE owners = :aid;
2747 EXEC SQL OPEN csr110;
2748 while(1) {
2749 EXEC SQL FETCH csr110 INTO :name;
2750 if(sqlca.sqlcode != 0) break;
2751 (*action)(2, rargv, actarg);
2752 found++;
2753 }
2754 EXEC SQL CLOSE csr110;
2755
2756 rargv[0] = "QUERY";
2757 EXEC SQL DECLARE csr111 CURSOR FOR
2758 SELECT capability FROM capacls
2759 WHERE list_id = :aid ;
2760 EXEC SQL OPEN csr111;
2761 while(1) {
2762 EXEC SQL FETCH csr111 INTO :name ;
2763 if(sqlca.sqlcode != 0) break;
2764 (*action)(2, rargv, actarg);
2765 found++;
2766 }
2767 EXEC SQL CLOSE csr111;
2768 } else if (!strcmp(atype, "USER")) {
2769 rargv[0] = "FILESYS";
2770 EXEC SQL DECLARE csr112 CURSOR FOR
2771 SELECT label FROM filesys
2772 WHERE owner = :aid;
2773 EXEC SQL OPEN csr112;
2774 while(1) {
2775 EXEC SQL FETCH csr112 INTO :name ;
2776 if(sqlca.sqlcode != 0) break;
2777 (*action)(2, rargv, actarg);
2778 found++;
2779 }
2780 EXEC SQL CLOSE csr112;
2781 }
2782
2783 rargv[0] = "LIST";
2784 EXEC SQL DECLARE csr113 CURSOR FOR
2785 SELECT name FROM list
2786 WHERE acl_type = :atype AND acl_id = :aid;
2787 EXEC SQL OPEN csr113;
2788 while(1) {
2789 EXEC SQL FETCH csr113 INTO :name;
2790 if(sqlca.sqlcode != 0) break;
2791 (*action)(2, rargv, actarg);
2792 found++;
2793 }
2794 EXEC SQL CLOSE csr113;
2795
2796 rargv[0] = "SERVICE";
2797 EXEC SQL DECLARE csr114 CURSOR FOR
2798 SELECT name FROM servers
2799 WHERE acl_type = :atype AND acl_id = :aid;
2800 EXEC SQL OPEN csr114;
2801 while(1) {
2802 EXEC SQL FETCH csr114 INTO :name;
2803 if(sqlca.sqlcode != 0) break;
2804 (*action)(2, rargv, actarg);
2805 found++;
2806 }
2807 EXEC SQL CLOSE csr114;
2808
2809 rargv[0] = "HOSTACCESS";
2810 EXEC SQL DECLARE csr115 CURSOR FOR
2811 SELECT name FROM machine m, hostaccess ha
2812 WHERE m.mach_id = ha.mach_id AND ha.acl_type = :atype
2813 AND ha.acl_id = :aid;
2814 EXEC SQL OPEN csr115;
2815 while(1) {
2816 EXEC SQL FETCH csr115 INTO :name;
2817 if(sqlca.sqlcode != 0) break;
2818 (*action)(2, rargv, actarg);
2819 found++;
2820 }
2821 EXEC SQL CLOSE csr115;
2822
2823 rargv[0] = "ZEPHYR";
2824 EXEC SQL DECLARE csr116 CURSOR FOR
2825 SELECT class FROM zephyr z
2826 WHERE z.xmt_type = :atype AND z.xmt_id = :aid
2827 OR z.sub_type = :atype AND z.sub_id = :aid
2828 OR z.iws_type = :atype AND z.iws_id = :aid
2829 OR z.iui_type = :atype AND z.iui_id = :aid;
2830 EXEC SQL OPEN csr116;
2831 while(1) {
2832 EXEC SQL FETCH csr116 INTO :name;
2833 if(sqlca.sqlcode != 0) break;
2834 (*action)(2, rargv, actarg);
2835 found++;
2836 }
2837 EXEC SQL CLOSE csr116;
2838
2839 if (!found) return(MR_NO_MATCH);
2840 return(MR_SUCCESS);
2841}
2842
2843
2844/* get_lists_of_member - given a type and a name, return the name and flags
2845 * of all of the lists of the given member. The member_type is one of
2846 * "LIST", "USER", "STRING", "RLIST", "RUSER", or "RSTRING" in argv[0],
2847 * and argv[1] will contain the ID of the entity in question. The R*
2848 * types mean to recursively look at every containing list, not just
2849 * when the object in question is a direct member.
2850 */
2851
2852int get_lists_of_member(q, argv, cl, action, actarg)
2853 struct query *q;
2854 char *argv[];
2855 client *cl;
2856 int (*action)();
2857 int actarg;
2858{
2859 int found = 0, direct = 1;
2860 char *rargv[6];
2861 EXEC SQL BEGIN DECLARE SECTION;
2862 char *atype;
2863 int aid, listid, id;
2864 char name[33], active[5], public[5], hidden[5], maillist[5], grouplist[5];
2865 EXEC SQL END DECLARE SECTION;
2866
2867 atype = argv[0];
2868 aid = *(int *)argv[1];
2869 if (!strcmp(atype, "RLIST")) {
2870 atype = "LIST";
2871 direct = 0;
2872 }
2873 if (!strcmp(atype, "RUSER")) {
2874 atype = "USER";
2875 direct = 0;
2876 }
2877 if (!strcmp(atype, "RSTRING")) {
2878 atype = "STRING";
2879 direct = 0;
2880 }
2881 if (!strcmp(atype, "RKERBEROS")) {
2882 atype = "KERBEROS";
2883 direct = 0;
2884 }
2885
2886 rargv[0] = name;
2887 rargv[1] = active;
2888 rargv[2] = public;
2889 rargv[3] = hidden;
2890 rargv[4] = maillist;
2891 rargv[5] = grouplist;
2892 if (direct) {
2893 EXEC SQL DECLARE csr117a CURSOR FOR
2894 SELECT l.name, CHAR(l.active), CHAR(l.publicflg), CHAR(l.hidden),
2895 CHAR(l.maillist), CHAR(l.grouplist)
2896 FROM list l, imembers im
2897 WHERE l.list_id = im.list_id AND im.direct = 1
2898 AND im.member_type = :atype AND im.member_id = :aid;
2899 EXEC SQL OPEN csr117a;
2900 while(1) {
2901 EXEC SQL FETCH csr117a
2902 INTO :name, :active, :public, :hidden, :maillist, :grouplist;
2903 if(sqlca.sqlcode != 0) break;
2904 (*action)(6, rargv, actarg);
2905 found++;
2906 }
2907 EXEC SQL CLOSE csr117a;
2908 } else {
2909 EXEC SQL DECLARE csr117b CURSOR FOR
2910 SELECT l.name, CHAR(l.active), CHAR(l.publicflg), CHAR(l.hidden),
2911 CHAR(l.maillist), CHAR(l.grouplist)
2912 FROM list l, imembers im
2913 WHERE l.list_id = im.list_id
2914 AND im.member_type = :atype AND im.member_id = :aid;
2915 EXEC SQL OPEN csr117b;
2916 while(1) {
2917 EXEC SQL FETCH csr117b
2918 INTO :name, :active, :public, :hidden, :maillist, :grouplist;
2919 if(sqlca.sqlcode != 0) break;
2920 (*action)(6, rargv, actarg);
2921 found++;
2922 }
2923 EXEC SQL CLOSE csr117b;
2924 }
2925
2926 if (ingres_errno) return(mr_errcode);
2927 if (!found) return(MR_NO_MATCH);
2928 return(MR_SUCCESS);
2929}
2930
2931
2932/* qualified_get_lists: passed "TRUE", "FALSE", or "DONTCARE" for each of
2933 * the five flags associated with each list. It will return the name of
2934 * each list that meets the quailifications. It does this by building a
2935 * where clause based on the arguments, then doing a retrieve.
2936 */
2937
2938static char *lflags[5] = { "active", "publicflg", "hidden", "maillist", "grouplist" };
2939
2940int qualified_get_lists(q, argv, cl, action, actarg)
2941 struct query *q;
2942 char *argv[];
2943 client *cl;
2944 int (*action)();
2945 int actarg;
2946{
2947 return(qualified_get(q, argv, action, actarg, "l.list_id != 0",
2948 "l", "name", lflags));
2949}
2950
2951
2952/* get_members_of_list - this gets only direct members */
2953
2954get_members_of_list(q, argv, cl, action, actarg)
2955 struct query *q;
2956 char *argv[];
2957 client *cl;
2958 int (*action)();
2959 int actarg;
2960{
2961 return(gmol_internal(q, argv, cl, action, actarg, 1));
2962}
2963
2964/* get_end_members_of_list - this gets direct or indirect members */
2965
2966get_end_members_of_list(q, argv, cl, action, actarg)
2967 struct query *q;
2968 char *argv[];
2969 client *cl;
2970 int (*action)();
2971 int actarg;
2972{
2973 return(gmol_internal(q, argv, cl, action, actarg, 0));
2974}
2975
2976/** gmol_internal - optimized query for retrieval of list members
2977 ** used by both get_members_of_list and get_end_members_of_list
2978 **
2979 ** Inputs:
2980 ** argv[0] - list_id
2981 **
2982 ** Description:
2983 ** - retrieve USER members, then LIST members, then STRING members
2984 **/
2985
2986gmol_internal(q, argv, cl, action, actarg, flag)
2987 struct query *q;
2988 char *argv[];
2989 client *cl;
2990 int (*action)();
2991 int actarg;
2992 int flag;
2993{
2994 EXEC SQL BEGIN DECLARE SECTION;
2995 int list_id, member_id, direct;
2996 char member_name[129], member_type[9];
2997 EXEC SQL END DECLARE SECTION;
2998 char *targv[2];
2999 int members;
3000 struct save_queue *sq;
3001
3002 /* true/false flag indicates whether to display only direct members. */
3003 if (flag)
3004 direct = 0;
3005 else
3006 direct = -1;
3007
3008 list_id = *(int *)argv[0];
3009 members = 0;
3010 sq = sq_create();
3011
3012 EXEC SQL DECLARE csr118 CURSOR FOR
3013 SELECT member_type, member_id FROM imembers
3014 WHERE list_id = :list_id AND direct > :direct;
3015 EXEC SQL OPEN csr118;
3016 while(1) {
3017 EXEC SQL FETCH csr118 INTO :member_type, :member_id;
3018 if (sqlca.sqlcode != 0) break;
3019 if (members++ > 49)
3020 break;
3021 sq_save_data(sq, ((int)member_type[0] << 24) | (member_id & 0xffffff));
3022 }
3023 EXEC SQL CLOSE csr118;
3024
3025 if (members <= 49) {
3026 targv[1] = malloc(0);
3027 while (sq_remove_data(sq, &member_id)) {
3028 switch (member_id >> 24) {
3029 case 'U':
3030 targv[0] = "USER";
3031 id_to_name(member_id & 0xffffff, "USER", &targv[1]);
3032 (*action)(2, targv, actarg);
3033 break;
3034 case 'L':
3035 targv[0] = "LIST";
3036 id_to_name(member_id & 0xffffff, "LIST", &targv[1]);
3037 (*action)(2, targv, actarg);
3038 break;
3039 case 'S':
3040 targv[0] = "STRING";
3041 id_to_name(member_id & 0xffffff, "STRING", &targv[1]);
3042 (*action)(2, targv, actarg);
3043 break;
3044 case 'K':
3045 targv[0] = "KERBEROS";
3046 id_to_name(member_id & 0xffffff, "STRING", &targv[1]);
3047 (*action)(2, targv, actarg);
3048 break;
3049 default:
3050 sq_destroy(sq);
3051 return(MR_INTERNAL);
3052 }
3053 }
3054 free(targv[1]);
3055 sq_destroy(sq);
3056 return(MR_SUCCESS);
3057 }
3058 sq_destroy(sq);
3059
3060 targv[1] = member_name;
3061 targv[0] = "USER";
3062 EXEC SQL DECLARE csr119 CURSOR FOR
3063 SELECT u.login FROM users u, imembers im
3064 WHERE im.list_id = :list_id AND im.member_type = 'USER'
3065 AND im.member_id = u.users_id AND im.direct > :direct
3066 ORDER BY 1;
3067 EXEC SQL OPEN csr119;
3068 while(1) {
3069 EXEC SQL FETCH csr119 INTO :member_name;
3070 if(sqlca.sqlcode != 0) break;
3071 (*action)(2, targv, actarg);
3072 }
3073 EXEC SQL CLOSE csr119;
3074 if (ingres_errno) return(mr_errcode);
3075
3076 targv[0] = "LIST";
3077 EXEC SQL DECLARE csr120 CURSOR FOR
3078 SELECT l.name FROM list l, imembers im
3079 WHERE im.list_id = :list_id AND im.member_type='LIST'
3080 AND im.member_id = l.list_id AND im.direct > :direct
3081 ORDER BY 1;
3082 EXEC SQL OPEN csr120;
3083 while(1) {
3084 EXEC SQL FETCH csr120 INTO :member_name;
3085 if(sqlca.sqlcode != 0) break;
3086 (*action)(2, targv, actarg);
3087 }
3088 EXEC SQL CLOSE csr120;
3089 if (ingres_errno) return(mr_errcode);
3090
3091 targv[0] = "STRING";
3092 EXEC SQL DECLARE csr121 CURSOR FOR
3093 SELECT CHAR(str.string) FROM strings str, imembers im
3094 WHERE im.list_id = :list_id AND im.member_type='STRING'
3095 AND im.member_id = str.string_id AND im.direct > :direct
3096 ORDER BY 1;
3097 EXEC SQL OPEN csr121;
3098 while(1) {
3099 EXEC SQL FETCH csr121 INTO :member_name;
3100 if(sqlca.sqlcode != 0) break;
3101 (*action)(2, targv, actarg);
3102 }
3103 EXEC SQL CLOSE csr121;
3104 if (ingres_errno) return(mr_errcode);
3105
3106 targv[0] = "KERBEROS";
3107 EXEC SQL DECLARE csr122 CURSOR FOR
3108 SELECT CHAR(str.string) FROM strings str, imembers im
3109 WHERE im.list_id = :list_id AND im.member_type='KERBEROS'
3110 AND im.member_id = str.string_id
3111 AND im.direct > :direct
3112 ORDER BY 1;
3113 EXEC SQL OPEN csr122;
3114 while(1) {
3115 EXEC SQL FETCH csr122 INTO :member_name;
3116 if(sqlca.sqlcode != 0) break;
3117 (*action)(2, targv, actarg);
3118 }
3119 EXEC SQL CLOSE csr122;
3120 if (ingres_errno) return(mr_errcode);
3121
3122 return(MR_SUCCESS);
3123}
3124
3125
3126/* count_members_of_list: this is a simple query, but it cannot be done
3127 * through the dispatch table.
3128 */
3129
3130int count_members_of_list(q, argv, cl, action, actarg)
3131 struct query *q;
3132 char *argv[];
3133 client *cl;
3134 int (*action)();
3135 int actarg;
3136{
3137 EXEC SQL BEGIN DECLARE SECTION;
3138 int list, ct = 0;
3139 EXEC SQL END DECLARE SECTION;
3140 char *rargv[1], countbuf[5];
3141
3142 list = *(int *)argv[0];
3143 rargv[0] = countbuf;
3144 EXEC SQL REPEATED SELECT count (*) INTO :ct FROM imembers
3145 WHERE list_id = :list AND direct=1;
3146 if (ingres_errno) return(mr_errcode);
3147 sprintf(countbuf, "%d", ct);
3148 (*action)(1, rargv, actarg);
3149 return(MR_SUCCESS);
3150}
3151
3152
3153/* qualified_get_server: passed "TRUE", "FALSE", or "DONTCARE" for each of
3154 * the three flags associated with each service. It will return the name of
3155 * each service that meets the quailifications. It does this by building a
3156 * where clause based on the arguments, then doing a retrieve.
3157 */
3158
3159static char *sflags[3] = { "enable", "inprogress", "harderror" };
3160
3161int qualified_get_server(q, argv, cl, action, actarg)
3162 struct query *q;
3163 char *argv[];
3164 client *cl;
3165 int (*action)();
3166 int actarg;
3167{
3168 return(qualified_get(q, argv, action, actarg, "s.name != ''",
3169 "s", "name", sflags));
3170}
3171
3172
3173/* generic qualified get routine, used by qualified_get_lists,
3174 * qualified_get_server, and qualified_get_serverhost.
3175 * Args:
3176 * start - a simple where clause, must not be empty
3177 * range - the name of the range variable
3178 * field - the field to return
3179 * flags - an array of strings, names of the flag variables
3180 */
3181
3182int qualified_get(q, argv, action, actarg, start, range, field, flags)
3183 struct query *q;
3184 char *argv[];
3185 int (*action)();
3186 int actarg;
3187 char *start;
3188 char *range;
3189 char *field;
3190 char *flags[];
3191{
3192 char name[33], qual[256];
3193 int rowcount=0, i;
3194 char *rargv[1], buf[32];
3195
3196 strcpy(qual, start);
3197 for (i = 0; i < q->argc; i++) {
3198 if (!strcmp(argv[i], "TRUE")) {
3199 sprintf(buf, " AND %s.%s != 0", range, flags[i]);
3200 (void) strcat(qual, buf);
3201 } else if (!strcmp(argv[i], "FALSE")) {
3202 sprintf(buf, " AND %s.%s = 0", range, flags[i]);
3203 (void) strcat(qual, buf);
3204 }
3205 }
3206
3207 rargv[0] = SQLDA->sqlvar[0].sqldata;
3208 sprintf(stmt_buf,"SELECT CHAR(%s.%s) FROM %s %s WHERE %s",range,field,q->rtable,range,qual);
3209 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3210 if(sqlca.sqlcode)
3211 return(MR_INTERNAL);
3212 EXEC SQL DECLARE csr123 CURSOR FOR stmt;
3213 EXEC SQL OPEN csr123;
3214 while(1) {
3215 EXEC SQL FETCH csr123 USING DESCRIPTOR :SQLDA;
3216 if(sqlca.sqlcode != 0) break;
3217 rowcount++;
3218 (*action)(1, rargv, actarg);
3219 }
3220 EXEC SQL CLOSE csr123;
3221 if (ingres_errno) return(mr_errcode);
3222 if (rowcount == 0)
3223 return(MR_NO_MATCH);
3224 return(MR_SUCCESS);
3225}
3226
3227
3228/* qualified_get_serverhost: passed "TRUE", "FALSE", or "DONTCARE" for each of
3229 * the five flags associated with each serverhost. It will return the name of
3230 * each service and host that meets the quailifications. It does this by
3231 * building a where clause based on the arguments, then doing a retrieve.
3232 */
3233
3234static char *shflags[6] = { "service", "enable", "override", "success",
3235 "inprogress", "hosterror" };
3236
3237int qualified_get_serverhost(q, argv, cl, action, actarg)
3238 struct query *q;
3239 char *argv[];
3240 client *cl;
3241 int (*action)();
3242 int actarg;
3243{
3244 EXEC SQL BEGIN DECLARE SECTION;
3245 char sname[33], mname[33], qual[256];
3246 EXEC SQL END DECLARE SECTION;
3247 char *rargv[2], buf[32];
3248 int i, rowcount;
3249
3250 sprintf(qual, "m.mach_id = sh.mach_id AND sh.service = uppercase('%s')",
3251 argv[0]);
3252 for (i = 1; i < q->argc; i++) {
3253 if (!strcmp(argv[i], "TRUE")) {
3254 sprintf(buf, " AND sh.%s != 0", shflags[i]);
3255 strcat(qual, buf);
3256 } else if (!strcmp(argv[i], "FALSE")) {
3257 sprintf(buf, " AND sh.%s = 0", shflags[i]);
3258 strcat(qual, buf);
3259 }
3260 }
3261
3262 rargv[0] = sname;
3263 rargv[1] = mname;
3264 EXEC SQL DECLARE csr124 CURSOR FOR
3265 SELECT sh.service, m.name FROM serverhosts sh, machine m
3266 WHERE :qual;
3267 EXEC SQL OPEN csr124;
3268 while(1) {
3269 EXEC SQL FETCH csr124 INTO :sname, :mname;
3270 if(sqlca.sqlcode != 0) break;
3271 rowcount++;
3272 (*action)(2, rargv, actarg);
3273 }
3274 EXEC SQL CLOSE csr124;
3275
3276 if (ingres_errno) return(mr_errcode);
3277 if (rowcount == 0)
3278 return(MR_NO_MATCH);
3279 return(MR_SUCCESS);
3280}
3281
3282
3283/* register_user - change user's login name and allocate a pobox, group,
3284 * filesystem, and quota for them. The user's status must start out as 0,
3285 * and is left as 2. Arguments are: user's UID, new login name, and user's
3286 * type for filesystem allocation (MR_FS_STUDENT, MR_FS_FACULTY,
3287 * MR_FS_STAFF, MR_FS_MISC).
3288 */
3289
3290register_user(q, argv, cl)
3291 struct query *q;
3292 char **argv;
3293 client *cl;
3294{
3295 EXEC SQL BEGIN DECLARE SECTION;
3296 char *login, dir[65], *entity, directory[129], machname[33];
3297 int who, rowcount, mid, uid, users_id, flag, utype, nid, list_id, quota;
3298 int size, alloc, pid, ostatus, nstatus, gidval, fsidval, npidval;
3299 static int m_id = 0, def_quota = 0;
3300 EXEC SQL END DECLARE SECTION;
3301 char buffer[256], *aargv[3];
3302
3303 entity = cl->entity;
3304 who = cl->client_id;
3305
3306 uid = atoi(argv[0]);
3307 login = argv[1];
3308 utype = atoi(argv[2]);
3309
3310 /* find user */
3311 EXEC SQL REPEATED SELECT users_id, status INTO :users_id, :ostatus
3312 FROM users
3313 WHERE uid = :uid AND (status=0 OR status=5 OR status=6);
3314
3315 if (sqlca.sqlerrd[2] == 0)
3316 return(MR_NO_MATCH);
3317 if (sqlca.sqlerrd[2] > 1)
3318 return(MR_NOT_UNIQUE);
3319
3320 /* check new login name */
3321 EXEC SQL REPEATED SELECT COUNT(login) INTO :rowcount FROM users
3322 WHERE login = LEFT(:login,SIZE(login)) AND users_id != :users_id;
3323 if (ingres_errno) return(mr_errcode);
3324 if (rowcount > 0) return(MR_IN_USE);
3325 EXEC SQL REPEATED SELECT COUNT(name) INTO :rowcount FROM list
3326 WHERE name = LEFT(:login,SIZE(name));
3327 if (ingres_errno) return(mr_errcode);
3328 if (rowcount > 0) return(MR_IN_USE);
3329 EXEC SQL REPEATED SELECT COUNT(label) INTO :rowcount FROM filesys
3330 WHERE label = LEFT(:login,SIZE(label));
3331 if (ingres_errno) return(mr_errcode);
3332 if (rowcount > 0) return(MR_IN_USE);
3333 com_err(whoami, 0, "login name OK");
3334
3335 /* choose place for pobox, put in mid */
3336 EXEC SQL DECLARE csr130 CURSOR FOR
3337 SELECT sh.mach_id, m.name FROM serverhosts sh, machine m
3338 WHERE sh.service='POP' AND sh.mach_id=m.mach_id
3339 AND sh.value2 - sh.value1 =
3340 (SELECT MAX(value2 - value1) FROM serverhosts
3341 WHERE service = 'POP');
3342 EXEC SQL OPEN csr130;
3343 EXEC SQL FETCH csr130 INTO :mid, :machname;
3344 if (sqlca.sqlerrd[2] == 0) {
3345 EXEC SQL CLOSE csr130;
3346 if (ingres_errno) return(mr_errcode);
3347 return(MR_NO_POBOX);
3348 } else {
3349 EXEC SQL CLOSE csr130;
3350 if (ingres_errno) return(mr_errcode);
3351 }
3352
3353 /* change login name, set pobox */
3354 sprintf(buffer, "u.users_id = %d", users_id);
3355 incremental_before("users", buffer, 0);
3356 nstatus = 2;
3357 if (ostatus == 5 || ostatus == 6)
3358 nstatus = 1;
3359 EXEC SQL REPEATED UPDATE users SET login = :login, status = :nstatus,
3360 modtime='now', modby = :who, modwith = :entity, potype='POP',
3361 pop_id = :mid, pmodtime='now', pmodby = :who, pmodwith = :entity
3362 WHERE users_id = :users_id;
3363
3364 if (ingres_errno) return(mr_errcode);
3365 if (sqlca.sqlerrd[2] != 1)
3366 return(MR_INTERNAL);
3367 set_pop_usage(mid, 1);
3368 com_err(whoami, 0, "set login name to %s and pobox to %s", login,
3369 strtrim(machname));
3370 incremental_after("users", buffer, 0);
3371
3372 /* create group list */
3373 if (set_next_object_id("gid", "list", 1))
3374 return(MR_NO_ID);
3375 if (set_next_object_id("list_id", "list", 0))
3376 return(MR_NO_ID);
3377 EXEC SQL REPEATED SELECT value INTO :list_id FROM numvalues
3378 WHERE name='list_id';
3379 if (ingres_errno) return(mr_errcode);
3380 if (sqlca.sqlerrd[2] != 1)
3381 return(MR_INTERNAL);
3382 incremental_clear_before();
3383 EXEC SQL SELECT value INTO :gidval FROM numvalues WHERE name = 'gid';
3384 EXEC SQL REPEATED INSERT INTO list
3385 (name, list_id, active, publicflg, hidden, maillist, grouplist,
3386 gid, description, acl_type, acl_id,
3387 modtime, modby, modwith)
3388 VALUES (:login, :list_id, 1, 0, 0, 0, 1,
3389 :gidval, 'User Group', 'USER', :users_id,
3390 'now', :who, :entity);
3391 if (ingres_errno) return(mr_errcode);
3392 if (sqlca.sqlerrd[2] != 1)
3393 return(MR_INTERNAL);
3394 sprintf(buffer, "l.list_id = %d", list_id);
3395 incremental_after("list", buffer, 0);
3396 aargv[0] = (char *) list_id;
3397 aargv[1] = "USER";
3398 aargv[2] = (char *) users_id;
3399 incremental_clear_before();
3400 EXEC SQL REPEATED INSERT INTO imembers
3401 (list_id, member_type, member_id, ref_count, direct)
3402 VALUES (:list_id, 'USER', :users_id, 1, 1);
3403 if (ingres_errno) return(mr_errcode);
3404 if (sqlca.sqlerrd[2] != 1)
3405 return(MR_INTERNAL);
3406 incremental_after("members", 0, aargv);
3407
3408 if (m_id == 0) {
3409 /* Cell Name (I know, it shouldn't be hard coded...) */
3410 strcpy(machname, "ATHENA.MIT.EDU");
3411 EXEC SQL SELECT mach_id INTO :m_id FROM machine
3412 WHERE name = :machname;
3413 }
3414
3415 /* create filesystem */
3416 if (set_next_object_id("filsys_id", "filesys", 0))
3417 return(MR_NO_ID);
3418 incremental_clear_before();
3419 if (islower(login[0]) && islower(login[1])) {
3420 sprintf(directory, "/afs/athena.mit.edu/user/%c/%c/%s",
3421 login[0], login[1], login);
3422 } else {
3423 sprintf(directory, "/afs/athena.mit.edu/user/other/%s", login);
3424 }
3425
3426 EXEC SQL SELECT value INTO :fsidval FROM numvalues
3427 WHERE numvalues.name='filsys_id';
3428 EXEC SQL REPEATED INSERT INTO filesys
3429 (filsys_id, phys_id, label, type, mach_id, name,
3430 mount, access, comments, owner, owners, createflg,
3431 lockertype, modtime, modby, modwith)
3432 VALUES
3433 (:fsidval, 0, :login, 'AFS', :m_id, :directory,
3434 '/mit/'+:login, 'w', 'User Locker', :users_id, :list_id, 1,
3435 'HOMEDIR', 'now', :who, :entity);
3436
3437 if (ingres_errno) return(mr_errcode);
3438 if (sqlca.sqlerrd[2] != 1)
3439 return(MR_INTERNAL);
3440 sprintf(buffer,"fs.filsys_id = %d",fsidval);
3441 incremental_after("filesys", buffer, 0);
3442
3443 /* set quota */
3444 if (def_quota == 0) {
3445 EXEC SQL REPEATED SELECT value INTO :def_quota FROM numvalues
3446 WHERE name='def_quota';
3447 if (ingres_errno) return(mr_errcode);
3448 if (sqlca.sqlerrd[2] != 1)
3449 return(MR_NO_QUOTA);
3450
3451 }
3452 incremental_clear_before();
3453 EXEC SQL REPEATED INSERT INTO quota
3454 (entity_id, filsys_id, type, quota, phys_id, modtime, modby, modwith)
3455 VALUES
3456 (0, :fsidval, 'ANY', :def_quota, 0, 'now', :who, :entity);
3457 if (ingres_errno) return(mr_errcode);
3458 if (sqlca.sqlerrd[2] != 1)
3459 return(MR_INTERNAL);
3460 aargv[0] = login;
3461 aargv[1] = "ANY";
3462 aargv[2] = login;
3463 sprintf(buffer, "q.entity_id = 0 and q.filsys_id = %d and q.type = 'ANY'", fsidval);
3464 incremental_after("quota", buffer, aargv);
3465 com_err(whoami, 0, "quota of %d assigned", def_quota);
3466 if (ingres_errno) return(mr_errcode);
3467
3468 cache_entry(login, "USER", users_id);
3469
3470 EXEC SQL REPEATED UPDATE tblstats SET updates=updates+1, modtime='now'
3471 WHERE table_name='users';
3472 EXEC SQL REPEATED UPDATE tblstats SET appends=appends+1, modtime='now'
3473 WHERE table_name='list' OR table_name='filesys' OR table_name='quota';
3474 if (ingres_errno) return(mr_errcode);
3475 return(MR_SUCCESS);
3476}
3477
3478
3479
3480/** set_pop_usage - incr/decr usage count for pop server in serverhosts talbe
3481 **
3482 ** Inputs:
3483 ** id of machine
3484 ** delta (will be +/- 1)
3485 **
3486 ** Description:
3487 ** - incr/decr value field in serverhosts table for pop/mach_id
3488 **
3489 **/
3490
3491static int set_pop_usage(id, cnt)
3492 EXEC SQL BEGIN DECLARE SECTION;
3493 int id;
3494 int cnt;
3495 EXEC SQL END DECLARE SECTION;
3496{
3497 EXEC SQL REPEATED UPDATE serverhosts SET value1 = value1 + :cnt
3498 WHERE serverhosts.service = 'POP' AND serverhosts.mach_id = :id;
3499
3500 if (ingres_errno) return(mr_errcode);
3501 return(MR_SUCCESS);
3502}
3503
3504
3505\f
3506/* Validation Routines */
3507
3508validate_row(q, argv, v)
3509 register struct query *q;
3510 char *argv[];
3511 register struct validate *v;
3512{
3513 EXEC SQL BEGIN DECLARE SECTION;
3514 char *name;
3515 char qual[128];
3516 int rowcount;
3517 EXEC SQL END DECLARE SECTION;
3518
3519 /* build where clause */
3520 build_qual(v->qual, v->argc, argv, qual);
3521
3522 if (log_flags & LOG_VALID)
3523 /* tell the logfile what we're doing */
3524 com_err(whoami, 0, "validating row: %s", qual);
3525
3526 /* look for the record */
3527 sprintf(stmt_buf,"SELECT COUNT (*) FROM %s WHERE %s",q->rtable,qual);
3528 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3529 if(sqlca.sqlcode)
3530 return(MR_INTERNAL);
3531 EXEC SQL DECLARE csr126 CURSOR FOR stmt;
3532 EXEC SQL OPEN csr126;
3533 EXEC SQL FETCH csr126 USING DESCRIPTOR :SQLDA;
3534 EXEC SQL CLOSE csr126;
3535 rowcount = *(int *)SQLDA->sqlvar[0].sqldata;
3536
3537 if (ingres_errno) return(mr_errcode);
3538 if (rowcount == 0) return(MR_NO_MATCH);
3539 if (rowcount > 1) return(MR_NOT_UNIQUE);
3540 return(MR_EXISTS);
3541}
3542
3543validate_fields(q, argv, vo, n)
3544 struct query *q;
3545 register char *argv[];
3546 register struct valobj *vo;
3547 register int n;
3548{
3549 register int status;
3550
3551 while (--n >= 0) {
3552 switch (vo->type) {
3553 case V_NAME:
3554 if (log_flags & LOG_VALID)
3555 com_err(whoami, 0, "validating %s in %s: %s",
3556 vo->namefield, vo->table, argv[vo->index]);
3557 status = validate_name(argv, vo);
3558 break;
3559
3560 case V_ID:
3561 if (log_flags & LOG_VALID)
3562 com_err(whoami, 0, "validating %s in %s: %s",
3563 vo->idfield, vo->table, argv[vo->index]);
3564 status = validate_id(q, argv, vo);
3565 break;
3566
3567 case V_DATE:
3568 if (log_flags & LOG_VALID)
3569 com_err(whoami, 0, "validating date: %s", argv[vo->index]);
3570 status = validate_date(argv, vo);
3571 break;
3572
3573 case V_TYPE:
3574 if (log_flags & LOG_VALID)
3575 com_err(whoami, 0, "validating %s type: %s",
3576 vo->table, argv[vo->index]);
3577 status = validate_type(argv, vo);
3578 break;
3579
3580 case V_TYPEDATA:
3581 if (log_flags & LOG_VALID)
3582 com_err(whoami, 0, "validating typed data (%s): %s",
3583 argv[vo->index - 1], argv[vo->index]);
3584 status = validate_typedata(q, argv, vo);
3585 break;
3586
3587 case V_RENAME:
3588 if (log_flags & LOG_VALID)
3589 com_err(whoami, 0, "validating rename %s in %s",
3590 argv[vo->index], vo->table);
3591 status = validate_rename(argv, vo);
3592 break;
3593
3594 case V_CHAR:
3595 if (log_flags & LOG_VALID)
3596 com_err(whoami, 0, "validating chars: %s", argv[vo->index]);
3597 status = validate_chars(argv[vo->index]);
3598 break;
3599
3600 case V_SORT:
3601 status = MR_EXISTS;
3602 break;
3603
3604 case V_LOCK:
3605 status = lock_table(vo);
3606 break;
3607
3608 case V_WILD:
3609 status = convert_wildcards(argv[vo->index]);
3610 break;
3611
3612 case V_UPWILD:
3613 status = convert_wildcards_uppercase(argv[vo->index]);
3614 break;
3615
3616 }
3617
3618 if (status != MR_EXISTS) return(status);
3619 vo++;
3620 }
3621
3622 if (ingres_errno) return(mr_errcode);
3623 return(MR_SUCCESS);
3624}
3625
3626
3627/* validate_chars: verify that there are no illegal characters in
3628 * the string. Legal characters are printing chars other than
3629 * ", *, ?, \, [ and ].
3630 */
3631static int illegalchars[] = {
3632 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
3633 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
3634 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
3635 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
3636 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* : - O */
3637 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* P - _ */
3638 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
3639 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
3640 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3641 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3642 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3643 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3644 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3645 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3646 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3647 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3648};
3649
3650validate_chars(s)
3651register char *s;
3652{
3653 while (*s)
3654 if (illegalchars[*s++])
3655 return(MR_BAD_CHAR);
3656 return(MR_EXISTS);
3657}
3658
3659
3660validate_id(q, argv, vo)
3661 struct query *q;
3662 char *argv[];
3663 register struct valobj *vo;
3664{
3665 EXEC SQL BEGIN DECLARE SECTION;
3666 char *name, *tbl, *namefield, *idfield;
3667 int id, rowcount;
3668 EXEC SQL END DECLARE SECTION;
3669 int status;
3670 register char *c;
3671
3672 name = argv[vo->index];
3673 tbl = vo->table;
3674 namefield = vo->namefield;
3675 idfield = vo->idfield;
3676
3677 if ((!strcmp(tbl, "users") && !strcmp(namefield, "login")) ||
3678 !strcmp(tbl, "machine") ||
3679 !strcmp(tbl, "filesys") ||
3680 !strcmp(tbl, "list") ||
3681 !strcmp(tbl, "cluster") ||
3682 !strcmp(tbl, "strings")) {
3683 if (!strcmp(tbl, "machine"))
3684 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3685 status = name_to_id(name, tbl, &id);
3686 if (status == 0) {
3687 *(int *)argv[vo->index] = id;
3688 return(MR_EXISTS);
3689 } else if (status == MR_NO_MATCH && !strcmp(tbl, "strings") &&
3690 (q->type == APPEND || q->type == UPDATE)) {
3691 EXEC SQL SELECT value INTO :id FROM numvalues
3692 WHERE name = 'strings_id';
3693 id++;
3694 EXEC SQL UPDATE numvalues SET value = :id WHERE name = 'strings_id';
3695 EXEC SQL INSERT INTO strings (string_id, string) VALUES (:id, :name);
3696 cache_entry(name, "STRING", id);
3697 *(int *)argv[vo->index] = id;
3698 return(MR_EXISTS);
3699 } else if (status == MR_NO_MATCH || status == MR_NOT_UNIQUE)
3700 return(vo->error);
3701 else
3702 return(status);
3703 }
3704
3705 if (!strcmp(namefield, "uid")) {
3706 sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s = %s",idfield,tbl,namefield,name);
3707 } else {
3708 sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s = '%s'",idfield,tbl,namefield,name);
3709 }
3710 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3711 if(sqlca.sqlcode)
3712 return(MR_INTERNAL);
3713 EXEC SQL DECLARE csr127 CURSOR FOR stmt;
3714 EXEC SQL OPEN csr127;
3715 rowcount=0;
3716 EXEC SQL FETCH csr127 USING DESCRIPTOR :SQLDA;
3717 if(sqlca.sqlcode == 0) {
3718 rowcount++;
3719 EXEC SQL FETCH csr127 USING DESCRIPTOR :SQLDA;
3720 if(sqlca.sqlcode == 0) rowcount++;
3721 }
3722 EXEC SQL CLOSE csr127;
3723 if (ingres_errno)
3724 return(mr_errcode);
3725
3726 if (rowcount != 1) return(vo->error);
3727 bcopy(SQLDA->sqlvar[0].sqldata,argv[vo->index],sizeof(int));
3728 return(MR_EXISTS);
3729}
3730
3731validate_name(argv, vo)
3732 char *argv[];
3733 register struct valobj *vo;
3734{
3735 EXEC SQL BEGIN DECLARE SECTION;
3736 char *name, *tbl, *namefield;
3737 int rowcount;
3738 EXEC SQL END DECLARE SECTION;
3739 register char *c;
3740
3741 name = argv[vo->index];
3742 tbl = vo->table;
3743 namefield = vo->namefield;
3744 if (!strcmp(tbl, "servers") && !strcmp(namefield, "name")) {
3745 for (c = name; *c; c++)
3746 if (islower(*c))
3747 *c = toupper(*c);
3748 }
3749 sprintf(stmt_buf,"SELECT DISTINCT COUNT(*) FROM %s WHERE %s.%s = '%s'",
3750 tbl,tbl,namefield,name);
3751 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3752 if(sqlca.sqlcode)
3753 return(MR_INTERNAL);
3754 EXEC SQL DECLARE csr128 CURSOR FOR stmt;
3755 EXEC SQL OPEN csr128;
3756 EXEC SQL FETCH csr128 USING DESCRIPTOR :SQLDA;
3757 rowcount = *(int *)SQLDA->sqlvar[0].sqldata;
3758 EXEC SQL CLOSE csr128;
3759
3760 if (ingres_errno) return(mr_errcode);
3761 return ((rowcount == 1) ? MR_EXISTS : vo->error);
3762}
3763
3764validate_date(argv, vo)
3765 char *argv[];
3766 struct valobj *vo;
3767{
3768 EXEC SQL BEGIN DECLARE SECTION;
3769 char *idate;
3770 double dd;
3771 int errorno;
3772 EXEC SQL END DECLARE SECTION;
3773
3774 idate = argv[vo->index];
3775 EXEC SQL SELECT interval('years',date(:idate)-date('today')) INTO :dd;
3776
3777 if (sqlca.sqlcode != 0 || dd > 5.0) return(MR_DATE);
3778 return(MR_EXISTS);
3779}
3780
3781
3782validate_rename(argv, vo)
3783char *argv[];
3784struct valobj *vo;
3785{
3786 EXEC SQL BEGIN DECLARE SECTION;
3787 char *name, *tbl, *namefield, *idfield;
3788 int id;
3789 EXEC SQL END DECLARE SECTION;
3790 int status;
3791 register char *c;
3792
3793 c = name = argv[vo->index];
3794 while (*c)
3795 if (illegalchars[*c++])
3796 return(MR_BAD_CHAR);
3797 tbl = vo->table;
3798 /* minor kludge to upcasify machine names */
3799 if (!strcmp(tbl, "machine"))
3800 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3801 namefield = vo->namefield;
3802 idfield = vo->idfield;
3803 id = -1;
3804 if (idfield == 0) {
3805 if (!strcmp(argv[vo->index], argv[vo->index - 1]))
3806 return(MR_EXISTS);
3807 sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s = LEFT('%s',SIZE(%s))",
3808 namefield,tbl,namefield,name,namefield);
3809 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3810 if(sqlca.sqlcode)
3811 return(MR_INTERNAL);
3812 EXEC SQL DECLARE csr129 CURSOR FOR stmt;
3813 EXEC SQL OPEN csr129;
3814 EXEC SQL FETCH csr129 USING DESCRIPTOR :SQLDA;
3815 if(sqlca.sqlcode == 0) id=1; else id=0;
3816 EXEC SQL CLOSE csr129;
3817
3818 if (ingres_errno) return(mr_errcode);
3819 if (id)
3820 return(vo->error);
3821 else
3822 return(MR_EXISTS);
3823 }
3824 status = name_to_id(name, tbl, &id);
3825 if (status == MR_NO_MATCH || id == *(int *)argv[vo->index - 1])
3826 return(MR_EXISTS);
3827 else
3828 return(vo->error);
3829}
3830
3831
3832validate_type(argv, vo)
3833 char *argv[];
3834 register struct valobj *vo;
3835{
3836 EXEC SQL BEGIN DECLARE SECTION;
3837 char *typename;
3838 char *val;
3839 int cnt;
3840 EXEC SQL END DECLARE SECTION;
3841 register char *c;
3842
3843 typename = vo->table;
3844 c = val = argv[vo->index];
3845 while (*c) {
3846 if (illegalchars[*c++])
3847 return(MR_BAD_CHAR);
3848 }
3849
3850 /* uppercase type fields */
3851 for (c = val; *c; c++) if (islower(*c)) *c = toupper(*c);
3852
3853 EXEC SQL SELECT COUNT(trans) INTO :cnt FROM alias
3854 WHERE name = :typename AND type='TYPE' AND trans = :val;
3855 if (ingres_errno) return(mr_errcode);
3856 return (cnt ? MR_EXISTS : vo->error);
3857}
3858
3859/* validate member or type-specific data field */
3860
3861validate_typedata(q, argv, vo)
3862 register struct query *q;
3863 register char *argv[];
3864 register struct valobj *vo;
3865{
3866 EXEC SQL BEGIN DECLARE SECTION;
3867 char *name;
3868 char *field_type;
3869 char data_type[129];
3870 int id;
3871 EXEC SQL END DECLARE SECTION;
3872 int status;
3873 char *index();
3874 register char *c;
3875
3876 /* get named object */
3877 name = argv[vo->index];
3878
3879 /* get field type string (known to be at index-1) */
3880 field_type = argv[vo->index-1];
3881
3882 /* get corresponding data type associated with field type name */
3883 EXEC SQL SELECT trans INTO :data_type FROM alias
3884 WHERE name = :field_type AND type='TYPEDATA';
3885 if (ingres_errno) return(mr_errcode);
3886 if (sqlca.sqlerrd[2] != 1) return(MR_TYPE);
3887
3888 /* now retrieve the record id corresponding to the named object */
3889 if (index(data_type, ' '))
3890 *index(data_type, ' ') = 0;
3891 if (!strcmp(data_type, "user")) {
3892 /* USER */
3893 status = name_to_id(name, data_type, &id);
3894 if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
3895 return(MR_USER);
3896 if (status) return(status);
3897 } else if (!strcmp(data_type, "list")) {
3898 /* LIST */
3899 status = name_to_id(name, data_type, &id);
3900 if (status && status == MR_NOT_UNIQUE)
3901 return(MR_LIST);
3902 if (status == MR_NO_MATCH) {
3903 /* if idfield is non-zero, then if argv[0] matches the string
3904 * that we're trying to resolve, we should get the value of
3905 * numvalues.[idfield] for the id.
3906 */
3907 if (vo->idfield && !strcmp(argv[0], argv[vo->index])) {
3908 set_next_object_id(q->validate->object_id, q->rtable, 0);
3909 name = vo->idfield;
3910 EXEC SQL REPEATED SELECT value INTO :id FROM numvalues
3911 WHERE name = :name;
3912 if (sqlca.sqlerrd[2] != 1) return(MR_LIST);
3913 } else
3914 return(MR_LIST);
3915 } else if (status) return(status);
3916 } else if (!strcmp(data_type, "machine")) {
3917 /* MACHINE */
3918 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3919 status = name_to_id(name, data_type, &id);
3920 if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
3921 return(MR_MACHINE);
3922 if (status) return(status);
3923 } else if (!strcmp(data_type, "string")) {
3924 /* STRING */
3925 status = name_to_id(name, data_type, &id);
3926 if (status && status == MR_NOT_UNIQUE)
3927 return(MR_STRING);
3928 if (status == MR_NO_MATCH) {
3929 if (q->type != APPEND && q->type != UPDATE) return(MR_STRING);
3930 EXEC SQL SELECT value INTO :id FROM numvalues WHERE name = 'strings_id';
3931 id++;
3932 EXEC SQL UPDATE numvalues SET value = :id WHERE name = 'strings_id';
3933 EXEC SQL INSERT INTO strings (string_id, string) VALUES (:id, :name);
3934 cache_entry(name, "STRING", id);
3935 } else if (status) return(status);
3936 } else if (!strcmp(data_type, "none")) {
3937 id = 0;
3938 } else {
3939 return(MR_TYPE);
3940 }
3941
3942 /* now set value in argv */
3943 *(int *)argv[vo->index] = id;
3944
3945 return (MR_EXISTS);
3946}
3947
3948
3949/* Lock the table named by the validation object */
3950
3951lock_table(vo)
3952struct valobj *vo;
3953{
3954 sprintf(stmt_buf,"UPDATE %s SET modtime='now' WHERE %s.%s = 0",
3955 vo->table,vo->table,vo->idfield);
3956 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
3957 if (ingres_errno) return(mr_errcode);
3958 if (sqlca.sqlerrd[2] != 1)
3959 return(vo->error);
3960 else
3961 return(MR_EXISTS);
3962}
3963
3964
3965/* Check the database at startup time. For now this just resets the
3966 * inprogress flags that the DCM uses.
3967 */
3968
3969sanity_check_database()
3970{
3971}
3972
3973
3974/* Dynamic SQL support routines */
3975MR_SQLDA_T *mr_alloc_SQLDA()
3976{
3977 MR_SQLDA_T *it;
3978 short *null_indicators;
3979 register int j;
3980
3981 if((it=(MR_SQLDA_T *)malloc(sizeof(MR_SQLDA_T)))==NULL) {
3982 com_err(whoami, MR_NO_MEM, "setting up SQLDA");
3983 exit(1);
3984 }
3985
3986 if((null_indicators=(short *)calloc(QMAXARGS,sizeof(short)))==NULL) {
3987 com_err(whoami, MR_NO_MEM, "setting up SQLDA null indicators");
3988 exit(1);
3989 }
3990
3991 for(j=0; j<QMAXARGS; j++) {
3992 if((it->sqlvar[j].sqldata=malloc(sizeof(short)+QMAXARGSIZE))==NULL) {
3993 com_err(whoami, MR_NO_MEM, "setting up SQLDA variables");
3994 exit(1);
3995 }
3996 it->sqlvar[j].sqllen=QMAXARGSIZE;
3997 it->sqlvar[j].sqlind=null_indicators+j;
3998 null_indicators[j]=0;
3999 }
4000 it->sqln=QMAXARGS;
4001 return it;
4002}
4003
4004
4005/* Use this after FETCH USING DESCRIPTOR one or more
4006 * result columns may contain NULLs. This routine is
4007 * not currently needed, since db/schema creates all
4008 * columns with a NOT NULL WITH DEFAULT clause.
4009 *
4010 * This is currently dead flesh, since no Moira columns
4011 * allow null values; all use default values.
4012 */
4013mr_fix_nulls_in_SQLDA(da)
4014 MR_SQLDA_T *da;
4015{
4016 register IISQLVAR *var;
4017 register int j;
4018 int *intp;
4019
4020 for(j=0, var=da->sqlvar; j<da->sqld; j++, var++) {
4021 switch(var->sqltype) {
4022 case -IISQ_CHA_TYPE:
4023 if(*var->sqlind)
4024 *var->sqldata='\0';
4025 break;
4026 case -IISQ_INT_TYPE:
4027 if(*var->sqlind) {
4028 intp=(int *)var->sqldata;
4029 *intp=0;
4030 }
4031 break;
4032 }
4033 }
4034}
4035
4036/* prefetch_value():
4037 * This routine fetches an appropriate value from the numvalues table.
4038 * It is a little hack to get around the fact that SQL doesn't let you
4039 * do something like INSERT INTO table (foo) VALUES (other_table.bar).
4040 *
4041 * It is called from the query table as (*v->pre_rtn)(q,Argv,cl) or
4042 * from within a setup_...() routine with the appropriate arguments.
4043 *
4044 * Correct functioning of this routine may depend on the assumption
4045 * that this query is an APPEND.
4046 */
4047
4048prefetch_value(q,argv,cl)
4049 struct query *q;
4050 char **argv;
4051 client *cl;
4052{
4053 EXEC SQL BEGIN DECLARE SECTION;
4054 char *name = q->validate->object_id;
4055 int value;
4056 EXEC SQL END DECLARE SECTION;
4057 int status, limit, argc;
4058
4059 /* set next object id, limiting it if necessary */
4060 if(!strcmp(name, "uid") || !strcmp(name, "gid"))
4061 limit = 1; /* So far as I know, this isn't needed. Just CMA. */
4062 else
4063 limit = 0;
4064 if((status = set_next_object_id(name, q->rtable, limit)) != MR_SUCCESS)
4065 return(status);
4066
4067 /* fetch object id */
4068 EXEC SQL SELECT value INTO :value FROM numvalues WHERE name=:name;
4069 if(ingres_errno) return(mr_errcode);
4070 if(sqlca.sqlerrd[2] != 1) return(MR_INTERNAL);
4071
4072 argc = q->argc + q->vcnt; /* end of Argv for APPENDs */
4073 sprintf(argv[argc],"%d",value); /** Could save this step by changing tlist from %s to %d **/
4074
4075 return(MR_SUCCESS);
4076}
4077
4078/* prefetch_filesys():
4079 * Fetches the phys_id from filesys based on the filsys_id in argv[0].
4080 * Appends the filsys_id and the phys_id to the argv so they can be
4081 * referenced in an INSERT into a table other than filesys. Also
4082 * see comments at prefetch_value().
4083 *
4084 * Assumes the existence of a row where filsys_id = argv[0], since a
4085 * filesys label has already been resolved to a filsys_id.
4086 */
4087prefetch_filesys(q,argv,cl)
4088 struct query *q;
4089 char **argv;
4090 client *cl;
4091{
4092 EXEC SQL BEGIN DECLARE SECTION;
4093 int fid,phid;
4094 EXEC SQL END DECLARE SECTION;
4095 int argc;
4096
4097 fid = *(int *)argv[0];
4098 EXEC SQL SELECT phys_id INTO :phid FROM filesys WHERE filsys_id = :fid;
4099 if(ingres_errno) return(mr_errcode);
4100
4101 argc=q->argc+q->vcnt;
4102 sprintf(argv[argc++],"%d",phid);
4103 sprintf(argv[argc],"%d",fid);
4104
4105 return(MR_SUCCESS);
4106}
4107
4108/* Convert normal Unix-style wildcards to SQL voodoo */
4109convert_wildcards(arg)
4110 char *arg;
4111{
4112 static char buffer[QMAXARGSIZE];
4113 register char *s, *d;
4114
4115 for(d=buffer,s=arg;*s;s++) {
4116 switch(*s) {
4117 case '*': *d++='%'; *d++='%'; break;
4118 case '?': *d++='_'; break;
4119 case '_':
4120 case '[':
4121 case ']': *d++='*'; *d++ = *s; break;
4122 case '%': *d++='*'; *d++='%'; *d++='%'; break;
4123 default: *d++ = *s; break;
4124 }
4125 }
4126 *d='\0';
4127
4128 /* Copy back into argv */
4129 strcpy(arg,buffer);
4130
4131 return(MR_EXISTS);
4132}
4133
4134/* This version includes uppercase conversion, for things like gmac.
4135 * This is necessary because "LIKE" doesn't work with "uppercase()".
4136 * Including it in a wildcard routine saves making two passes over
4137 * the argument string.
4138 */
4139convert_wildcards_uppercase(arg)
4140 char *arg;
4141{
4142 static char buffer[QMAXARGSIZE];
4143 register char *s, *d;
4144
4145 for(d=buffer,s=arg;*s;s++) {
4146 switch(*s) {
4147 case '*': *d++='%'; *d++='%'; break;
4148 case '?': *d++='_'; break;
4149 case '_':
4150 case '[':
4151 case ']': *d++='*'; *d++ = *s; break;
4152 case '%': *d++='*'; *d++='%'; *d++='%'; break;
4153 default: *d++=toupper(*s); break; /* This is the only diff. */
4154 }
4155 }
4156 *d='\0';
4157
4158 /* Copy back into argv */
4159 strcpy(arg,buffer);
4160
4161 return(MR_EXISTS);
4162}
4163
4164
4165/* Looks like it's time to build an abstraction barrier, Yogi */
4166mr_select_any(stmt)
4167 EXEC SQL BEGIN DECLARE SECTION;
4168 char *stmt;
4169 EXEC SQL END DECLARE SECTION;
4170{
4171 int result=0;
4172
4173 EXEC SQL PREPARE stmt FROM :stmt;
4174 EXEC SQL DESCRIBE stmt INTO :SQLDA;
4175 if(SQLDA->sqld==0) /* Not a SELECT */
4176 return(MR_INTERNAL);
4177 EXEC SQL DECLARE csr CURSOR FOR stmt;
4178 EXEC SQL OPEN csr;
4179 EXEC SQL FETCH csr USING DESCRIPTOR :SQLDA;
4180 if(sqlca.sqlcode==0)
4181 result=MR_EXISTS;
4182 else if((sqlca.sqlcode<0) && mr_errcode)
4183 result=mr_errcode;
4184 else
4185 result=0;
4186 EXEC SQL CLOSE csr;
4187 return(result);
4188}
4189
4190
4191/* eof:qsupport.dc */
This page took 0.078381 seconds and 5 git commands to generate.