]> andersk Git - moira.git/blame_incremental - server/qsupport.dc
stuff for hosttable in moira
[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 1, 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 if (ingres_errno)
917 return(mr_errcode);
918 EXEC SQL OPEN csr101;
919 if (ingres_errno)
920 return(mr_errcode);
921 while(1) {
922 EXEC SQL FETCH csr101 INTO :var_phys_id, :dir;
923 if(sqlca.sqlcode != 0) break;
924 cp1 = name;
925 cp2 = dir;
926 while (*cp2) {
927 if (*cp1++ != *cp2) break;
928 cp2++;
929 }
930 if (*cp2 == 0) {
931 status = MR_SUCCESS;
932 break;
933 }
934 }
935 EXEC SQL CLOSE csr101;
936 if (ingres_errno)
937 return(mr_errcode);
938 return(status);
939}
940
941
942/* setup_dfil: free any quota records and fsgroup info associated with
943 * a filesystem when it is deleted. Also adjust the allocation numbers.
944 */
945
946setup_dfil(q, argv, cl)
947 struct query *q;
948 char **argv;
949 client *cl;
950{
951 EXEC SQL BEGIN DECLARE SECTION;
952 int id, total, phys_id;
953 short int none;
954 EXEC SQL END DECLARE SECTION;
955
956 id = *(int *)argv[0];
957 EXEC SQL REPEATED SELECT SUM (quota) INTO :total:none FROM quota
958 WHERE filsys_id = :id;
959
960 if(none) total=0;
961
962 /** What if there are multiple phys_id's per f/s? (bad data) **/
963 EXEC SQL REPEATED SELECT phys_id INTO :phys_id FROM filesys
964 WHERE filsys_id = :id;
965 EXEC SQL REPEATED UPDATE nfsphys SET allocated = allocated - :total
966 WHERE nfsphys_id = :phys_id;
967
968 if(!none) {
969 EXEC SQL REPEATED DELETE FROM quota WHERE filsys_id = :id;
970 }
971 EXEC SQL REPEATED DELETE FROM fsgroup WHERE filsys_id = :id;
972 EXEC SQL REPEATED DELETE FROM fsgroup WHERE group_id = :id;
973 if (ingres_errno) return(mr_errcode);
974 return(MR_SUCCESS);
975}
976
977
978/* setup_dnfp: check to see that the nfs physical partition does not have
979 * any filesystems assigned to it before allowing it to be deleted.
980 */
981
982setup_dnfp(q, argv, cl)
983 struct query *q;
984 char **argv;
985 client *cl;
986{
987 EXEC SQL BEGIN DECLARE SECTION;
988 int id, cnt;
989 char *dir;
990 EXEC SQL END DECLARE SECTION;
991
992 id = *(int *)argv[0];
993 dir = argv[1];
994 EXEC SQL REPEATED SELECT fs.tid INTO :cnt FROM filesys fs, nfsphys np
995 WHERE fs.mach_id = :id AND fs.phys_id = np.nfsphys_id
996 AND np.mach_id = :id AND np.dir = :dir;
997 if (cnt > 0)
998 return(MR_IN_USE);
999 if (ingres_errno)
1000 return(mr_errcode);
1001 return(MR_SUCCESS);
1002}
1003
1004
1005/* setup_dqot: Remove allocation from nfsphys before deleting quota.
1006 * argv[0] = filsys_id
1007 * argv[1] = type if "update_quota" or "delete_quota"
1008 * argv[2 or 1] = users_id or list_id
1009 */
1010
1011setup_dqot(q, argv, cl)
1012 struct query *q;
1013 char **argv;
1014 client *cl;
1015{
1016 EXEC SQL BEGIN DECLARE SECTION;
1017 int quota, fs, id, physid;
1018 char *qtype;
1019 EXEC SQL END DECLARE SECTION;
1020
1021 fs = *(int *)argv[0];
1022 if (!strcmp(q->name, "update_quota") || !strcmp(q->name, "delete_quota")) {
1023 qtype = argv[1];
1024 id = *(int *)argv[2];
1025 } else {
1026 qtype = "USER";
1027 id = *(int *)argv[1];
1028 }
1029
1030 EXEC SQL REPEATED SELECT quota INTO :quota FROM quota
1031 WHERE type = :qtype AND entity_id = :id AND filsys_id = :fs;
1032 EXEC SQL REPEATED SELECT phys_id INTO :physid FROM filesys
1033 WHERE filsys_id = :fs;
1034 EXEC SQL REPEATED UPDATE nfsphys SET allocated = allocated - :quota
1035 WHERE nfsphys_id = :physid;
1036
1037 if (ingres_errno) return(mr_errcode);
1038 return(MR_SUCCESS);
1039}
1040
1041
1042/* setup_sshi: don't exclusive lock the machine table during
1043 * set_server_host_internal.
1044 */
1045/** Not allowed under (INGRES) SQL **/
1046setup_sshi(q, argv, cl)
1047 struct query *q;
1048 char **argv;
1049 client *cl;
1050{
1051#if 0
1052#ifsql INGRES
1053 EXEC SQL set lockmode session where readlock = system;
1054#endsql
1055#endif
1056 return(MR_SUCCESS);
1057}
1058
1059
1060/* setup add_kerberos_user_mapping: add the string to the string
1061 * table if necessary.
1062 */
1063
1064setup_akum(q, argv, cl)
1065struct query *q;
1066char **argv;
1067client *cl;
1068{
1069 EXEC SQL BEGIN DECLARE SECTION;
1070 int id, rowcount;
1071 char *name;
1072 EXEC SQL END DECLARE SECTION;
1073
1074 name = argv[1];
1075 if (name_to_id(name, "STRING", &id) != MR_SUCCESS) {
1076 if (q->type != APPEND) return(MR_STRING);
1077 id=add_string(name);
1078 cache_entry(name, "STRING", id);
1079 }
1080 if (ingres_errno) return(mr_errcode);
1081 *(int *)argv[1] = id;
1082 return(MR_SUCCESS);
1083}
1084
1085
1086\f
1087/* FOLLOWUP ROUTINES */
1088
1089/* generic set_modtime routine. This takes the table name from the query,
1090 * and will update the modtime, modby, and modwho fields in the entry in
1091 * the table whose name field matches argv[0].
1092 */
1093
1094set_modtime(q, argv, cl)
1095 struct query *q;
1096 char *argv[];
1097 client *cl;
1098{
1099 char *name, *entity, *table;
1100 int who;
1101
1102 entity = cl->entity;
1103 who = cl->client_id;
1104 table = q->rtable;
1105 name = argv[0];
1106
1107 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);
1108 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
1109
1110 return(MR_SUCCESS);
1111}
1112
1113/* generic set_modtime_by_id routine. This takes the table name from
1114 * the query, and the id name from the validate record,
1115 * and will update the modtime, modby, and modwho fields in the entry in
1116 * the table whose id matches argv[0].
1117 */
1118
1119set_modtime_by_id(q, argv, cl)
1120 struct query *q;
1121 char **argv;
1122 client *cl;
1123{
1124 char *entity, *table, *id_name;
1125 int who, id;
1126
1127 entity = cl->entity;
1128 who = cl->client_id;
1129 table = q->rtable;
1130 id_name = q->validate->object_id;
1131
1132 id = *(int *)argv[0];
1133 sprintf(stmt_buf,"UPDATE %s SET modtime = 'now', modby = %d, \
1134modwith = '%s' WHERE %s.%s = %d",table,who,entity,table,id_name,id);
1135 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
1136 return(MR_SUCCESS);
1137}
1138
1139
1140/* Sets the finger modtime on a user record. The users_id will be in argv[0].
1141 */
1142
1143set_finger_modtime(q, argv, cl)
1144 struct query *q;
1145 char *argv[];
1146 client *cl;
1147{
1148 EXEC SQL BEGIN DECLARE SECTION;
1149 int users_id, who;
1150 char *entity;
1151 EXEC SQL END DECLARE SECTION;
1152
1153 entity = cl->entity;
1154 who = cl->client_id;
1155 users_id = *(int *)argv[0];
1156
1157 EXEC SQL UPDATE users SET fmodtime='now', fmodby = :who, fmodwith = :entity
1158 WHERE users.users_id = :users_id;
1159
1160 return(MR_SUCCESS);
1161}
1162
1163
1164/* Sets the pobox modtime on a user record. The users_id will be in argv[0].
1165 */
1166
1167set_pobox_modtime(q, argv, cl)
1168 struct query *q;
1169 char **argv;
1170 client *cl;
1171{
1172 EXEC SQL BEGIN DECLARE SECTION;
1173 int users_id, who;
1174 char *entity;
1175 EXEC SQL END DECLARE SECTION;
1176
1177 entity = cl->entity;
1178 who = cl->client_id;
1179 users_id = *(int *)argv[0];
1180
1181 EXEC SQL UPDATE users SET pmodtime='now', pmodby = :who, pmodwith = :entity
1182 WHERE users.users_id = :users_id;
1183
1184 return(MR_SUCCESS);
1185}
1186
1187
1188/* Like set_modtime, but uppercases the name first.
1189 */
1190
1191set_uppercase_modtime(q, argv, cl)
1192 struct query *q;
1193 char **argv;
1194 client *cl;
1195{
1196 char *name, *entity, *table;
1197 int who;
1198
1199 entity = cl->entity;
1200 who = cl->client_id;
1201 table = q->rtable;
1202 name = argv[0];
1203
1204 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);
1205 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
1206
1207 return(MR_SUCCESS);
1208}
1209
1210
1211/* Sets the modtime on the machine whose mach_id is in argv[0]. This routine
1212 * is necessary for add_machine_to_cluster becuase the table that query
1213 * operates on is "mcm", not "machine".
1214 */
1215
1216set_mach_modtime_by_id(q, argv, cl)
1217 struct query *q;
1218 char **argv;
1219 client *cl;
1220{
1221 EXEC SQL BEGIN DECLARE SECTION;
1222 char *entity;
1223 int who, id;
1224 EXEC SQL END DECLARE SECTION;
1225
1226 entity = cl->entity;
1227 who = cl->client_id;
1228 id = *(int *)argv[0];
1229 EXEC SQL UPDATE machine SET modtime='now', modby = :who, modwith = :entity
1230 WHERE machine.mach_id = :id;
1231
1232 return(MR_SUCCESS);
1233}
1234
1235
1236/* Sets the modtime on the cluster whose mach_id is in argv[0]. This routine
1237 * is necessary for add_cluster_data and delete_cluster_data becuase the
1238 * table that query operates on is "svc", not "cluster".
1239 */
1240
1241set_cluster_modtime_by_id(q, argv, cl)
1242 struct query *q;
1243 char **argv;
1244 client *cl;
1245{
1246 EXEC SQL BEGIN DECLARE SECTION;
1247 char *entity;
1248 int who, id;
1249 EXEC SQL END DECLARE SECTION;
1250
1251 entity = cl->entity;
1252 who = cl->client_id;
1253
1254 id = *(int *)argv[0];
1255 EXEC SQL UPDATE cluster SET modtime='now', modby = :who, modwith = :entity
1256 WHERE cluster.clu_id = :id;
1257 return(MR_SUCCESS);
1258}
1259
1260
1261/* sets the modtime on the serverhost where the service name is in argv[0]
1262 * and the mach_id is in argv[1].
1263 */
1264
1265set_serverhost_modtime(q, argv, cl)
1266 struct query *q;
1267 char **argv;
1268 client *cl;
1269{
1270 EXEC SQL BEGIN DECLARE SECTION;
1271 char *entity, *serv;
1272 int who, id;
1273 EXEC SQL END DECLARE SECTION;
1274
1275 entity = cl->entity;
1276 who = cl->client_id;
1277
1278 serv = argv[0];
1279 id = *(int *)argv[1];
1280 EXEC SQL UPDATE serverhosts
1281 SET modtime = 'now', modby = :who, modwith = :entity
1282 WHERE service = :serv AND mach_id = :id;
1283 return(MR_SUCCESS);
1284}
1285
1286
1287/* sets the modtime on the nfsphys where the mach_id is in argv[0] and the
1288 * directory name is in argv[1].
1289 */
1290
1291set_nfsphys_modtime(q, argv, cl)
1292 struct query *q;
1293 char **argv;
1294 client *cl;
1295{
1296 EXEC SQL BEGIN DECLARE SECTION;
1297 char *entity, *dir;
1298 int who, id;
1299 EXEC SQL END DECLARE SECTION;
1300
1301 entity = cl->entity;
1302 who = cl->client_id;
1303
1304 id = *(int *)argv[0];
1305 dir = argv[1];
1306 EXEC SQL UPDATE nfsphys SET modtime = 'now', modby = :who, modwith = :entity
1307 WHERE dir = :dir AND mach_id = :id;
1308 return(MR_SUCCESS);
1309}
1310
1311
1312/* sets the modtime on a filesystem, where argv[0] contains the filesys
1313 * label.
1314 */
1315
1316set_filesys_modtime(q, argv, cl)
1317 struct query *q;
1318 char *argv[];
1319 client *cl;
1320{
1321 EXEC SQL BEGIN DECLARE SECTION;
1322 char *label, *entity;
1323 int who;
1324 EXEC SQL END DECLARE SECTION;
1325
1326 entity = cl->entity;
1327 who = cl->client_id;
1328
1329 label = argv[0];
1330 if (!strcmp(q->shortname, "ufil"))
1331 label = argv[1];
1332
1333 EXEC SQL UPDATE filesys SET modtime = 'now', modby = :who,
1334 modwith = :entity, phys_id = :var_phys_id
1335 WHERE label = LEFT(:label,SIZE(label));
1336 return(MR_SUCCESS);
1337}
1338
1339
1340/* sets the modtime on a zephyr class, where argv[0] contains the class
1341 * name.
1342 */
1343
1344set_zephyr_modtime(q, argv, cl)
1345 struct query *q;
1346 char *argv[];
1347 client *cl;
1348{
1349 EXEC SQL BEGIN DECLARE SECTION;
1350 char *class, *entity;
1351 int who;
1352 EXEC SQL END DECLARE SECTION;
1353
1354 entity = cl->entity;
1355 who = cl->client_id;
1356
1357 class = argv[0];
1358
1359 EXEC SQL UPDATE zephyr SET modtime = 'now', modby = :who, modwith = :entity
1360 WHERE class = LEFT(:class,SIZE(class));
1361
1362 return(MR_SUCCESS);
1363}
1364
1365
1366/* fixes the modby field. This will be the second to last thing in the
1367 * argv, the argv length is determined from the query structure. It is
1368 * passed as a pointer to an integer. This will either turn it into a
1369 * username, or # + the users_id.
1370 */
1371followup_fix_modby(q, sq, v, action, actarg, cl)
1372 struct query *q;
1373 register struct save_queue *sq;
1374 struct validate *v;
1375 register int (*action)();
1376 register int actarg;
1377 client *cl;
1378{
1379 register int i, j;
1380 char **argv, *malloc();
1381 int id, status;
1382
1383 i = q->vcnt - 2;
1384 while (sq_get_data(sq, &argv)) {
1385 id = atoi(argv[i]);
1386 if (id > 0)
1387 status = id_to_name(id, "USER", &argv[i]);
1388 else
1389 status = id_to_name(-id, "STRING", &argv[i]);
1390 if (status && status != MR_NO_MATCH)
1391 return(status);
1392 (*action)(q->vcnt, argv, actarg);
1393 for (j = 0; j < q->vcnt; j++)
1394 free(argv[j]);
1395 free(argv);
1396 }
1397 sq_destroy(sq);
1398 return(MR_SUCCESS);
1399}
1400
1401
1402/* After retrieving a user account, fix the modby field and signature.
1403 * The modby field is the second to last thing in the
1404 * argv, the argv length is determined from the query structure. It is
1405 * passed as a pointer to an integer. This will either turn it into a
1406 * username, or # + the users_id. Only "gua*" queries have a signature,
1407 * these are ones with U_END return values. "gub*" queries also use this
1408 * routine but don't have a signature.
1409 */
1410followup_guax(q, sq, v, action, actarg, cl)
1411 struct query *q;
1412 register struct save_queue *sq;
1413 struct validate *v;
1414 register int (*action)();
1415 register int actarg;
1416 client *cl;
1417{
1418 register int i, j;
1419 char **argv, *malloc();
1420#ifdef GDSS
1421 unsigned char sigbuf[256];
1422 char *kname;
1423 SigInfo si;
1424 EXEC SQL BEGIN DECLARE SECTION;
1425 int timestamp, who;
1426 char *login;
1427 varchar struct { short data_size; char data_buf[257];} rsig;
1428 EXEC SQL END DECLARE SECTION;
1429#endif /* GDSS */
1430 int id, status;
1431
1432 i = q->vcnt - 2;
1433 while (sq_get_data(sq, &argv)) {
1434#ifdef DEBUG
1435 com_err(whoami, 0, "argv[SIGNATURE] = \"%s\"", argv[U_SIGNATURE]);
1436#endif /* DEBUG */
1437 id = atoi(argv[i]);
1438 if (id > 0)
1439 status = id_to_name(id, "USER", &argv[i]);
1440 else
1441 status = id_to_name(-id, "STRING", &argv[i]);
1442 if (status && status != MR_NO_MATCH)
1443 return(status);
1444#ifdef GDSS
1445 if (q->vcnt == U_END && strlen(argv[U_SIGNATURE])) {
1446 login = argv[U_NAME];
1447 EXEC SQL REPEATED SELECT signature, sigdate, sigwho
1448 INTO :rsig, :timestamp, :who FROM users
1449 WHERE login = :login;
1450 /** What about (INGRES) error handling? **/
1451 kname = malloc(1);
1452 status = id_to_name(who, "STRING", &kname);
1453 si.timestamp = timestamp;
1454 si.SigInfoVersion = 0; /* XXXXX this isn't used */
1455 kname_parse(si.pname, si.pinst, si.prealm, kname);
1456 free(kname);
1457 rsig.data_buf[rsig.data_size] = 0;
1458 si.rawsig = (unsigned char *)strsave(rsig.data_buf);
1459 if (log_flags & LOG_GDSS)
1460 com_err(whoami, 0, "rawsig length = %d, sig=\"%s\"", strlen(si.rawsig), si.rawsig);
1461 GDSS_Recompose(&si, sigbuf);
1462 free(si.rawsig);
1463 free(argv[U_SIGNATURE]);
1464 argv[U_SIGNATURE] = strsave(sigbuf);
1465 if (log_flags & LOG_GDSS)
1466 com_err(whoami, 0, "generated signature length %d", strlen(sigbuf));
1467 }
1468#endif /* GDSS */
1469 (*action)(q->vcnt, argv, actarg);
1470 for (j = 0; j < q->vcnt; j++)
1471 free(argv[j]);
1472 free(argv);
1473 }
1474 sq_destroy(sq);
1475 return(MR_SUCCESS);
1476}
1477
1478
1479/**
1480 ** followup_ausr - add finger and pobox entries, set_user_modtime
1481 **
1482 ** Inputs:
1483 ** argv[0] - login (add_user)
1484 ** argv[3] - last name
1485 ** argv[4] - first name
1486 ** argv[5] - middle name
1487 **
1488 **/
1489
1490followup_ausr(q, argv, cl)
1491 struct query *q;
1492 char *argv[];
1493 client *cl;
1494{
1495 EXEC SQL BEGIN DECLARE SECTION;
1496 int who, status, id;
1497 char *login, *entity, *src, *dst, *name;
1498 char fullname[129];
1499 EXEC SQL END DECLARE SECTION;
1500#ifdef GDSS
1501 char databuf[32], *kname_unparse();
1502 EXEC SQL BEGIN DECLARE SECTION;
1503 char rawsig[128];
1504 int sigwho, timestamp;
1505 EXEC SQL END DECLARE SECTION;
1506 SigInfo si;
1507#endif /* GDSS */
1508
1509 /* build fullname */
1510 if (strlen(argv[4]) && strlen(argv[5]))
1511 sprintf(fullname, "%s %s %s", argv[4], argv[5], argv[3]);
1512 else if (strlen(argv[4]))
1513 sprintf(fullname, "%s %s", argv[4], argv[3]);
1514 else
1515 sprintf(fullname, "%s", argv[3]);
1516
1517#ifdef GDSS
1518 if (q->vcnt == U_END && *argv[U_SIGNATURE]) {
1519 /* unquote ' chars in signature */
1520 for (dst = src = argv[U_SIGNATURE]; *src; ) {
1521 if (*src == '\'')
1522 src++;
1523 *dst++ = *src++;
1524 }
1525 *dst = 0;
1526 sprintf(databuf, "%s:%s", argv[U_NAME], argv[U_MITID]);
1527 /* skip bytes for timestamp & kname */
1528 si.rawsig = (unsigned char *) rawsig;
1529 status = GDSS_Verify(databuf, strlen(databuf), argv[U_SIGNATURE], &si);
1530 if (strlen(rawsig) > mr_sig_length) {
1531 com_err(whoami, 0, "GDSS signature would be truncated."); /** untested **/
1532 return(MR_INTERNAL);
1533 }
1534 if (status == 0) {
1535 name = kname_unparse(si.pname, si.pinst, si.prealm);
1536 status = name_to_id(name, "STRING", &sigwho);
1537 if (status == MR_NO_MATCH) {
1538 sigwho=add_string(name);
1539 } else if (status)
1540 return(status);
1541 timestamp = si.timestamp;
1542 } else {
1543 if (log_flags & LOG_GDSS)
1544 hex_dump(argv[U_SIGNATURE]);
1545 return(gdss2et(status));
1546 }
1547 } else {
1548 rawsig[0] = 0;
1549 sigwho = 0;
1550 timestamp = 0;
1551 }
1552#endif /* GDSS */
1553
1554 login = argv[0];
1555 who = cl->client_id;
1556 entity = cl->entity;
1557
1558 /* create finger entry, pobox & set modtime on user */
1559#ifdef GDSS
1560 EXEC SQL REPEATED UPDATE users
1561 SET modtime='now', modby=:who, modwith = :entity,
1562 fullname = :fullname, affiliation = type,
1563 signature = :rawsig, sigdate = :timestamp, sigwho = :sigwho,
1564 fmodtime='now', fmodby = :who, fmodwith = :entity,
1565 potype='NONE', pmodtime='now', pmodby = :who, pmodwith = :entity
1566 WHERE login = :login;
1567#else /* GDSS */
1568 EXEC SQL REPEATED UPDATE users
1569 SET modtime='now', modby=:who, modwith = :entity,
1570 fullname = :fullname, affiliation = type,
1571 fmodtime='now', fmodby = :who, fmodwith = :entity,
1572 potype='NONE', pmodtime='now', pmodby = :who, pmodwith = :entity
1573 WHERE login = :login;
1574#endif /* GDSS */
1575
1576 return(MR_SUCCESS);
1577}
1578
1579
1580/**
1581 ** followup_uusr - do signature, set_user_modtime
1582 **
1583 ** Inputs:
1584 ** argv[0] - login (add_user)
1585 ** argv[U_SIGNATURE] - sig
1586 **
1587 **/
1588
1589followup_uuac(q, argv, cl)
1590 struct query *q;
1591 char *argv[];
1592 client *cl;
1593{
1594 EXEC SQL BEGIN DECLARE SECTION;
1595 int who, status, id;
1596 char *entity, *name, *src, *dst;
1597 EXEC SQL END DECLARE SECTION;
1598#ifdef GDSS
1599 char databuf[32], *kname_unparse();
1600 EXEC SQL BEGIN DECLARE SECTION;
1601 char rawsig[128];
1602 char *login;
1603 int sigwho, timestamp;
1604 EXEC SQL END DECLARE SECTION;
1605 SigInfo si;
1606#endif /* GDSS */
1607
1608 id = *(int *)argv[0];
1609 who = cl->client_id;
1610 entity = cl->entity;
1611
1612#ifdef GDSS
1613 if (q->vcnt == U_MODTIME && *argv[U_SIGNATURE + 1]) {
1614 /* unquote ' chars in signature */
1615 for (dst = src = argv[U_SIGNATURE+1]; *src; ) {
1616 if (*src == '\'')
1617 src++;
1618 *dst++ = *src++;
1619 }
1620 *dst = 0;
1621 login = malloc(1);
1622 status = id_to_name(id, "USER", &login);
1623 sprintf(databuf, "%s:%s", login, argv[U_MITID+1]);
1624 free(login);
1625 /* skip bytes for timestamp & kname */
1626 si.rawsig = (unsigned char *) rawsig;
1627#ifdef DEBUG
1628 com_err(whoami, 0, "verifying sig");
1629#endif /* DEBUG */
1630 status = GDSS_Verify(databuf, strlen(databuf), argv[U_SIGNATURE+1], &si);
1631#ifdef DEBUG
1632 com_err(whoami, 0, "verified");
1633#endif /* DEBUG */
1634 if (strlen(rawsig) > mr_sig_length) {
1635 com_err(whoami, 0, "GDSS signature would be truncated."); /** untested **/
1636 return(MR_INTERNAL);
1637 }
1638 if (status == 0) {
1639 name = kname_unparse(si.pname, si.pinst, si.prealm);
1640 status = name_to_id(name, "STRING", &sigwho);
1641 if (status == MR_NO_MATCH) {
1642 sigwho=add_string(name);
1643 } else if (status)
1644 return(status);
1645 timestamp = si.timestamp;
1646 } else {
1647 if (log_flags & LOG_GDSS)
1648 hex_dump(argv[U_SIGNATURE+1]);
1649 return(gdss2et(status));
1650 }
1651 } else {
1652 rawsig[0] = 0;
1653 sigwho = 0;
1654 timestamp = 0;
1655 }
1656#endif /* GDSS */
1657
1658 /* create finger entry, pobox & set modtime on user */
1659
1660#ifdef GDSS
1661 EXEC SQL REPEATED UPDATE users SET modtime='now', modby = :who, modwith = :entity,
1662 signature = :rawsig, sigdate = :timestamp, sigwho = :sigwho
1663 WHERE users_id = :id;
1664#else /* GDSS */
1665 EXEC SQL REPEATED UPDATE users SET modtime='now', modby = :who, modwith = :entity
1666 WHERE users_id = :id;
1667#endif /* GDSS */
1668 return(MR_SUCCESS);
1669}
1670
1671
1672/* followup_gpob: fixes argv[2] based on the IDs currently there and the
1673 * type in argv[1]. Then completes the upcall to the user.
1674 *
1675 * argv[2] is of the form "123:234" where the first integer is the machine
1676 * ID if it is a pop box, and the second is the string ID if it is an SMTP
1677 * box. argv[1] should be "POP", "SMTP", or "NONE". Boxes of type NONE
1678 * are skipped.
1679 */
1680
1681followup_gpob(q, sq, v, action, actarg, cl)
1682 register struct query *q;
1683 register struct save_queue *sq;
1684 register struct validate *v;
1685 register int (*action)();
1686 int actarg;
1687 client *cl;
1688{
1689 char **argv, *index();
1690 char *ptype, *p;
1691 int mid, sid, status, i;
1692
1693 /* for each row */
1694 while (sq_get_data(sq, &argv)) {
1695 mr_trim_args(2, argv);
1696 ptype = argv[1];
1697 p = index(argv[2], ':');
1698 *p++ = 0;
1699 mid = atoi(argv[2]);
1700 sid = atoi(p);
1701
1702 if (!strcmp(ptype, "POP")) {
1703 status = id_to_name(mid, "MACHINE", &argv[2]);
1704 if (status == MR_NO_MATCH)
1705 return(MR_MACHINE);
1706 } else if (!strcmp(ptype, "SMTP")) {
1707 status = id_to_name(sid, "STRING", &argv[2]);
1708 if (status == MR_NO_MATCH)
1709 return(MR_STRING);
1710 } else /* ptype == "NONE" */ {
1711 goto skip;
1712 }
1713 if (status) return(status);
1714
1715 if (!strcmp(q->shortname, "gpob")) {
1716 sid = atoi(argv[4]);
1717 if (sid > 0)
1718 status = id_to_name(sid, "USER", &argv[4]);
1719 else
1720 status = id_to_name(-sid, "STRING", &argv[4]);
1721 }
1722 if (status && status != MR_NO_MATCH) return(status);
1723
1724 (*action)(q->vcnt, argv, actarg);
1725 skip:
1726 /* free saved data */
1727 for (i = 0; i < q->vcnt; i++)
1728 free(argv[i]);
1729 free(argv);
1730 }
1731
1732 sq_destroy(sq);
1733 return (MR_SUCCESS);
1734}
1735
1736
1737/* followup_glin: fix the ace_name in argv[8]. argv[7] will contain the
1738 * ace_type: "LIST", "USER", or "NONE". Decode the id in argv[8] into the
1739 * proper name based on the type, and repace that string in the argv.
1740 * Also fixes the modby field by called followup_fix_modby.
1741 */
1742
1743followup_glin(q, sq, v, action, actarg, cl)
1744 register struct query *q;
1745 register struct save_queue *sq;
1746 register struct validate *v;
1747 register int (*action)();
1748 int actarg;
1749 client *cl;
1750{
1751 char **argv, *malloc(), *realloc(), *type;
1752 int id, i, idx, status;
1753
1754 idx = 8;
1755 if (!strcmp(q->shortname, "gsin"))
1756 idx = 12;
1757
1758 while (sq_get_data(sq, &argv)) {
1759 mr_trim_args(q->vcnt, argv);
1760
1761 id = atoi(argv[i = q->vcnt - 2]);
1762 if (id > 0)
1763 status = id_to_name(id, "USER", &argv[i]);
1764 else
1765 status = id_to_name(-id, "STRING", &argv[i]);
1766 if (status && status != MR_NO_MATCH)
1767 return(status);
1768
1769 id = atoi(argv[idx]);
1770 type = argv[idx - 1];
1771
1772 if (!strcmp(type, "LIST")) {
1773 status = id_to_name(id, "LIST", &argv[idx]);
1774 } else if (!strcmp(type, "USER")) {
1775 status = id_to_name(id, "USER", &argv[idx]);
1776 } else if (!strcmp(type, "KERBEROS")) {
1777 status = id_to_name(id, "STRING", &argv[idx]);
1778 } else if (!strcmp(type, "NONE")) {
1779 status = 0;
1780 free(argv[idx]);
1781 argv[idx] = strsave("NONE");
1782 } else {
1783 status = 0;
1784 free(argv[idx]);
1785 argv[idx] = strsave("???");
1786 }
1787 if (status && status != MR_NO_MATCH)
1788 return(status);
1789
1790 if (!strcmp(q->shortname, "glin") && atoi(argv[6]) == -1) {
1791 argv[6] = realloc(argv[6], strlen(UNIQUE_GID) + 1);
1792 strcpy(argv[6], UNIQUE_GID);
1793 }
1794
1795 /* send the data */
1796 (*action)(q->vcnt, argv, actarg);
1797
1798 /* free saved data */
1799 for (i = 0; i < q->vcnt; i++)
1800 free(argv[i]);
1801 free(argv);
1802 }
1803
1804 sq_destroy(sq);
1805 return (MR_SUCCESS);
1806}
1807
1808
1809/* followup_gqot: Fix the entity name, directory name & modby fields
1810 * argv[0] = filsys_id
1811 * argv[1] = type
1812 * argv[2] = entity_id
1813 * argv[3] = ascii(quota)
1814 */
1815
1816followup_gqot(q, sq, v, action, actarg, cl)
1817 struct query *q;
1818 register struct save_queue *sq;
1819 struct validate *v;
1820 register int (*action)();
1821 register int actarg;
1822 client *cl;
1823{
1824 register int j;
1825 char **argv, *malloc();
1826 EXEC SQL BEGIN DECLARE SECTION;
1827 int id;
1828 char *name, *label;
1829 EXEC SQL END DECLARE SECTION;
1830 int status, idx;
1831
1832 if (!strcmp(q->name, "get_quota") ||
1833 !strcmp(q->name, "get_quota_by_filesys"))
1834 idx = 4;
1835 else
1836 idx = 3;
1837 while (sq_get_data(sq, &argv)) {
1838 if (idx == 4) {
1839 switch (argv[1][0]) {
1840 case 'U':
1841 status = id_to_name(atoi(argv[2]), "USER", &argv[2]);
1842 break;
1843 case 'G':
1844 case 'L':
1845 status = id_to_name(atoi(argv[2]), "LIST", &argv[2]);
1846 break;
1847 case 'A':
1848 free(argv[2]);
1849 argv[2] = strsave("system:anyuser");
1850 break;
1851 default:
1852 id = atoi(argv[2]);
1853 argv[2] = malloc(8);
1854 sprintf(argv[2], "%d", id);
1855 }
1856 }
1857 id = atoi(argv[idx]);
1858 free(argv[idx]);
1859 argv[idx] = malloc(256);
1860 name = argv[idx];
1861 if (id == 0) {
1862 label = argv[0];
1863 EXEC SQL REPEATED SELECT name INTO :name FROM filesys
1864 WHERE label = :label;
1865 } else {
1866 EXEC SQL REPEATED SELECT dir INTO :name FROM nfsphys
1867 WHERE nfsphys_id = :id;
1868 }
1869 if (sqlca.sqlerrd[2] != 1) {
1870 sprintf(argv[idx], "#%d", id);
1871 }
1872
1873 id = atoi(argv[idx+3]);
1874 if (id > 0)
1875 status = id_to_name(id, "USER", &argv[idx+3]);
1876 else
1877 status = id_to_name(-id, "STRING", &argv[idx+3]);
1878 if (status && status != MR_NO_MATCH)
1879 return(status);
1880 (*action)(q->vcnt, argv, actarg);
1881 for (j = 0; j < q->vcnt; j++)
1882 free(argv[j]);
1883 free(argv);
1884 }
1885 sq_destroy(sq);
1886 return(MR_SUCCESS);
1887}
1888
1889
1890/* followup_aqot: Add allocation to nfsphys after creating quota.
1891 * argv[0] = filsys_id
1892 * argv[1] = type if "add_quota" or "update_quota"
1893 * argv[2 or 1] = id
1894 * argv[3 or 2] = ascii(quota)
1895 */
1896
1897followup_aqot(q, argv, cl)
1898 struct query *q;
1899 char **argv;
1900 client *cl;
1901{
1902 EXEC SQL BEGIN DECLARE SECTION;
1903 int quota, id, fs, who, physid;
1904 char *entity, *qtype, *table_name;
1905 EXEC SQL END DECLARE SECTION;
1906 char incr_qual[60];
1907 char *incr_argv[2];
1908 int status;
1909
1910 table_name=q->rtable;
1911 fs = *(int *)argv[0];
1912 EXEC SQL REPEATED SELECT phys_id INTO :physid FROM filesys
1913 WHERE filsys_id = :fs;
1914 if(ingres_errno)
1915 return(mr_errcode);
1916
1917 if (!strcmp(q->shortname, "aqot") || !strcmp(q->shortname, "uqot")) {
1918 qtype = argv[1];
1919 id = *(int *)argv[2];
1920 quota = atoi(argv[3]);
1921 sprintf(incr_qual,"q.filsys_id = %d",fs);
1922 } else {
1923 qtype = "USER";
1924 id = *(int *)argv[1];
1925 quota = atoi(argv[2]);
1926 sprintf(incr_qual,"q.filsys_id=%d AND q.type='%s' AND q.entity_id=%d",
1927 fs,qtype,id);
1928 }
1929
1930 /* quota case of incremental_{before|after} only looks at slot 1 */
1931 incr_argv[1]=qtype;
1932
1933 /* Follows one of many possible gross hacks to fix these particular
1934 * conflicts between what is possible in the query table and what
1935 * is possible in SQL.
1936 */
1937 if(q->type==APPEND) {
1938 incremental_clear_before();
1939 EXEC SQL INSERT INTO quota
1940 (filsys_id, type, entity_id, quota, phys_id)
1941 VALUES (:fs, :qtype, :id, :quota, :physid);
1942 incremental_after(table_name, incr_qual, incr_argv);
1943 } else {
1944 incremental_before(table_name, incr_qual, incr_argv);
1945 EXEC SQL UPDATE quota SET quota = :quota
1946 WHERE filsys_id = :fs AND type = :qtype AND entity_id = :id;
1947 status = mr_errcode;
1948 incremental_after(table_name, incr_qual, incr_argv);
1949 }
1950
1951 if (ingres_errno)
1952 return(mr_errcode);
1953 flush_name(argv[0], q->rtable);
1954 if(q->type==APPEND) {
1955 EXEC SQL UPDATE tblstats SET appends = appends + 1, modtime = 'now'
1956 WHERE table_name = :table_name;
1957 } else {
1958 EXEC SQL UPDATE tblstats SET updates = updates + 1, modtime = 'now'
1959 WHERE table_name = :table_name;
1960 }
1961
1962 /* Proceed with original followup */
1963 who = cl->client_id;
1964 entity = cl->entity;
1965
1966 EXEC SQL REPEATED UPDATE quota
1967 SET modtime = 'now', modby = :who, modwith = :entity
1968 WHERE filsys_id = :fs and type = :qtype and entity_id = :id;
1969 EXEC SQL REPEATED UPDATE nfsphys SET allocated = allocated + :quota
1970 WHERE nfsphys_id = :physid;
1971 if (ingres_errno) return(mr_errcode);
1972 return(MR_SUCCESS);
1973}
1974
1975
1976/* Necessitated by the requirement of a correlation name by the incremental
1977 * routines, since query table deletes don't provide one.
1978 */
1979followup_dqot(q,argv,cl)
1980 struct query *q;
1981 char **argv;
1982 struct client *cl;
1983{
1984 char *qtype;
1985 int id, fs;
1986 char *incr_argv[2];
1987 EXEC SQL BEGIN DECLARE SECTION;
1988 char incr_qual[80];
1989 char *tblname;
1990 EXEC SQL END DECLARE SECTION;
1991
1992 fs = *(int *)argv[0];
1993 if (!strcmp(q->shortname, "dqot")) {
1994 qtype = argv[1];
1995 id = *(int *)argv[2];
1996 } else {
1997 qtype = "USER";
1998 id = *(int *)argv[1];
1999 }
2000 sprintf(incr_qual,"q.filsys_id=%d AND q.type='%s' AND q.entity_id=%d",
2001 fs,qtype,id);
2002
2003 /* quota case of incremental_{before|after} only looks at slot 1 */
2004 incr_argv[1]=qtype;
2005
2006 incremental_before(q->rtable, incr_qual, incr_argv);
2007 EXEC SQL DELETE FROM quota q WHERE :incr_qual;
2008 incremental_clear_after();
2009
2010 if (ingres_errno)
2011 return(mr_errcode);
2012 flush_name(argv[0], q->rtable);
2013
2014 tblname = q->rtable;
2015 EXEC SQL UPDATE tblstats SET deletes = deletes + 1, modtime = 'now'
2016 WHERE table_name = :tblname;
2017 return(MR_SUCCESS);
2018}
2019
2020
2021followup_gpce(q, sq, v, action, actarg, cl)
2022 struct query *q;
2023 register struct save_queue *sq;
2024 struct validate *v;
2025 register int (*action)();
2026 register int actarg;
2027 client *cl;
2028{
2029 register int i, j;
2030 char **argv, *malloc();
2031 int id, status;
2032
2033 i = q->vcnt - 2;
2034 while (sq_get_data(sq, &argv)) {
2035 id = atoi(argv[PCAP_QSERVER]);
2036 status = id_to_name(id, "MACHINE", &argv[PCAP_QSERVER]);
2037 if (status) return (status);
2038 id = atoi(argv[i]);
2039 if (id > 0)
2040 status = id_to_name(id, "USER", &argv[i]);
2041 else
2042 status = id_to_name(-id, "STRING", &argv[i]);
2043 if (status && status != MR_NO_MATCH)
2044 return(status);
2045 (*action)(q->vcnt, argv, actarg);
2046 for (j = 0; j < q->vcnt; j++)
2047 free(argv[j]);
2048 free(argv);
2049 }
2050 sq_destroy(sq);
2051 return(MR_SUCCESS);
2052}
2053
2054
2055/* followup_gzcl:
2056 */
2057
2058followup_gzcl(q, sq, v, action, actarg, cl)
2059 register struct query *q;
2060 register struct save_queue *sq;
2061 register struct validate *v;
2062 register int (*action)();
2063 int actarg;
2064 client *cl;
2065{
2066 int id, i, status;
2067 char **argv;
2068
2069 while (sq_get_data(sq, &argv)) {
2070 mr_trim_args(q->vcnt, argv);
2071
2072 id = atoi(argv[i = q->vcnt - 2]);
2073 if (id > 0)
2074 status = id_to_name(id, "USER", &argv[i]);
2075 else
2076 status = id_to_name(-id, "STRING", &argv[i]);
2077 if (status && status != MR_NO_MATCH)
2078 return(status);
2079
2080 for (i = 1; i < 8; i+=2) {
2081 id = atoi(argv[i+1]);
2082 if (!strcmp(argv[i], "LIST")) {
2083 status = id_to_name(id, "LIST", &argv[i+1]);
2084 } else if (!strcmp(argv[i], "USER")) {
2085 status = id_to_name(id, "USER", &argv[i+1]);
2086 } else if (!strcmp(argv[i], "KERBEROS")) {
2087 status = id_to_name(id, "STRING", &argv[i+1]);
2088 } else if (!strcmp(argv[i], "NONE")) {
2089 status = 0;
2090 free(argv[i+1]);
2091 argv[i+1] = strsave("NONE");
2092 } else {
2093 status = 0;
2094 free(argv[i+1]);
2095 argv[i+1] = strsave("???");
2096 }
2097 if (status && status != MR_NO_MATCH)
2098 return(status);
2099 }
2100
2101 /* send the data */
2102 (*action)(q->vcnt, argv, actarg);
2103
2104 /* free saved data */
2105 for (i = 0; i < q->vcnt; i++)
2106 free(argv[i]);
2107 free(argv);
2108 }
2109 sq_destroy(sq);
2110 return(MR_SUCCESS);
2111}
2112
2113
2114/* followup_gsha:
2115 */
2116
2117followup_gsha(q, sq, v, action, actarg, cl)
2118 register struct query *q;
2119 register struct save_queue *sq;
2120 register struct validate *v;
2121 register int (*action)();
2122 int actarg;
2123 client *cl;
2124{
2125 char **argv;
2126 int i, id, status;
2127
2128 while (sq_get_data(sq, &argv)) {
2129 mr_trim_args(q->vcnt, argv);
2130
2131 id = atoi(argv[4]);
2132 if (id > 0)
2133 status = id_to_name(id, "USER", &argv[4]);
2134 else
2135 status = id_to_name(-id, "STRING", &argv[4]);
2136 if (status && status != MR_NO_MATCH)
2137 return(status);
2138
2139 id = atoi(argv[2]);
2140 if (!strcmp(argv[1], "LIST")) {
2141 status = id_to_name(id, "LIST", &argv[2]);
2142 } else if (!strcmp(argv[1], "USER")) {
2143 status = id_to_name(id, "USER", &argv[2]);
2144 } else if (!strcmp(argv[1], "KERBEROS")) {
2145 status = id_to_name(id, "STRING", &argv[2]);
2146 } else if (!strcmp(argv[1], "NONE")) {
2147 status = 0;
2148 free(argv[2]);
2149 argv[2] = strsave("NONE");
2150 } else {
2151 status = 0;
2152 free(argv[2]);
2153 argv[2] = strsave("???");
2154 }
2155 if (status && status != MR_NO_MATCH)
2156 return(status);
2157
2158 /* send the data */
2159 (*action)(q->vcnt, argv, actarg);
2160
2161 /* free saved data */
2162 for (i = 0; i < q->vcnt; i++)
2163 free(argv[i]);
2164 free(argv);
2165 }
2166 sq_destroy(sq);
2167 return(MR_SUCCESS);
2168}
2169
2170
2171\f
2172/* Special query routines */
2173
2174/* set_pobox - this does all of the real work.
2175 * argv = user_id, type, box
2176 * if type is POP, then box should be a machine, and its ID should be put in
2177 * pop_id. If type is SMTP, then box should be a string and its ID should
2178 * be put in box_id. If type is NONE, then box doesn't matter.
2179 */
2180
2181int set_pobox(q, argv, cl)
2182 struct query *q;
2183 char **argv;
2184 client *cl;
2185{
2186 EXEC SQL BEGIN DECLARE SECTION;
2187 int user, id;
2188 char *box, potype[9];
2189 EXEC SQL END DECLARE SECTION;
2190 int status;
2191
2192 box = argv[2];
2193 user = *(int *)argv[0];
2194
2195 EXEC SQL REPEATED SELECT pop_id, potype INTO :id, :potype FROM users
2196 WHERE users_id = :user;
2197 if (ingres_errno) return(mr_errcode);
2198 if (!strcmp(strtrim(potype), "POP"))
2199 set_pop_usage(id, -1);
2200
2201 if (!strcmp(argv[1], "POP")) {
2202 status = name_to_id(box, "MACHINE", &id);
2203 if (status == MR_NO_MATCH)
2204 return(MR_MACHINE);
2205 else if (status)
2206 return(status);
2207 EXEC SQL REPEATED UPDATE users SET potype = 'POP', pop_id = :id
2208 WHERE users_id = :user;
2209 set_pop_usage(id, 1);
2210 } else if (!strcmp(argv[1], "SMTP")) {
2211 if (index(box, '/') || index(box, '|'))
2212 return(MR_BAD_CHAR);
2213 status = name_to_id(box, "STRING", &id);
2214 if (status == MR_NO_MATCH) {
2215 id=add_string(box);
2216 } else if (status)
2217 return(status);
2218 EXEC SQL REPEATED UPDATE users SET potype='SMTP', box_id = :id
2219 WHERE users_id = :user;
2220 } else /* argv[1] == "NONE" */ {
2221 EXEC SQL REPEATED UPDATE users SET potype='NONE'
2222 WHERE users_id = :user;
2223 }
2224
2225 set_pobox_modtime(q, argv, cl);
2226 EXEC SQL REPEATED UPDATE tblstats SET updates = updates+1, modtime='now'
2227 WHERE table_name='users';
2228 if (ingres_errno) return(mr_errcode);
2229 return(MR_SUCCESS);
2230}
2231
2232
2233/* get_list_info: passed a wildcard list name, returns lots of stuff about
2234 * each list. This is tricky: first build a queue of all requested
2235 * data. Rest of processing consists of fixing gid, ace_name, and modby.
2236 */
2237
2238get_list_info(q, aargv, cl, action, actarg)
2239 register struct query *q;
2240 char **aargv;
2241 client *cl;
2242 register int (*action)();
2243 int actarg;
2244{
2245 char *argv[13], *malloc(), *realloc();
2246 EXEC SQL BEGIN DECLARE SECTION;
2247 char *name, acl_type[9], listname[33], active[5], public[5], hidden[5];
2248 char maillist[5], grouplist[5], gid_str[6], acl_name[256], desc[256];
2249 char modtime[27], modby[256], modwith[9];
2250 int id, rowcount, acl_id, hid, modby_id;
2251 char qual[80];
2252 EXEC SQL END DECLARE SECTION;
2253 int returned, status;
2254 struct save_queue *sq, *sq_create();
2255
2256 returned = rowcount = 0;
2257 name = aargv[0];
2258 convert_wildcards(name);
2259
2260 sq = sq_create();
2261 sprintf(qual,"name LIKE '%s' ESCAPE '*'",name);
2262 optimize_sql_stmt(qual);
2263 EXEC SQL DECLARE csr102 CURSOR FOR SELECT list_id FROM list
2264 WHERE :qual;
2265 if (ingres_errno)
2266 return(mr_errcode);
2267 EXEC SQL OPEN csr102;
2268 if (ingres_errno)
2269 return(mr_errcode);
2270 while(1)
2271 {
2272 EXEC SQL FETCH csr102 INTO :id;
2273 if(sqlca.sqlcode!=0) break;
2274 sq_save_data(sq, id);
2275 rowcount++;
2276 }
2277 EXEC SQL CLOSE csr102;
2278
2279 if (ingres_errno) return(mr_errcode);
2280 if (rowcount == 0)
2281 return(MR_NO_MATCH);
2282
2283 argv[0] = listname; argv[1] = active; argv[2] = public; argv[3] = hidden;
2284 argv[4] = maillist; argv[5] = grouplist; argv[6] = gid_str;
2285 argv[7] = acl_type; argv[9] = desc; argv[10] = modtime; argv[12] = modwith;
2286
2287 while (sq_get_data(sq, &id)) {
2288 if (id == 0)
2289 continue;
2290 argv[6] = gid_str;
2291 EXEC SQL REPEATED SELECT name, CHAR(active), CHAR(publicflg),
2292 CHAR(hidden), hidden, CHAR(maillist), CHAR(grouplist), CHAR(gid),
2293 TRIM(acl_type), acl_id, description, CHAR(modtime), modby, modwith
2294 INTO :listname, :active, :public, :hidden, :hid, :maillist,
2295 :grouplist, :gid_str, :acl_type, :acl_id, :desc,
2296 :modtime, :modby_id, :modwith
2297 FROM list WHERE list_id = :id;
2298
2299 if (ingres_errno) return(mr_errcode);
2300
2301 if (atoi(gid_str) == -1)
2302 argv[6] = UNIQUE_GID;
2303
2304 argv[8] = malloc(0);
2305 if (!strcmp(acl_type, "LIST")) {
2306 status = id_to_name(acl_id, "LIST", &argv[8]);
2307 } else if (!strcmp(acl_type, "USER")) {
2308 status = id_to_name(acl_id, "USER", &argv[8]);
2309 } else if (!strcmp(acl_type, "KERBEROS")) {
2310 status = id_to_name(acl_id, "STRING", &argv[8]);
2311 } else if (!strcmp(acl_type, "NONE")) {
2312 status = 0;
2313 free(argv[8]);
2314 argv[8] = strsave("NONE");
2315 } else {
2316 status = 0;
2317 free(argv[8]);
2318 argv[8] = strsave("???");
2319 }
2320 if (status && status != MR_NO_MATCH) return(status);
2321
2322 argv[11] = malloc(0);
2323 if (modby_id > 0)
2324 status = id_to_name(modby_id, "USER", &argv[11]);
2325 else
2326 status = id_to_name(-modby_id, "STRING", &argv[11]);
2327 if (status && status != MR_NO_MATCH) return(status);
2328
2329 mr_trim_args(q->vcnt, argv);
2330 returned++;
2331 (*action)(q->vcnt, argv, actarg);
2332 free(argv[8]);
2333 free(argv[11]);
2334 }
2335
2336 sq_destroy(sq);
2337 if (ingres_errno) return(mr_errcode);
2338 return (MR_SUCCESS);
2339}
2340
2341
2342/* Add_member_to_list: do list flattening as we go! MAXLISTDEPTH is
2343 * how many different ancestors a member is allowed to have.
2344 */
2345
2346#define MAXLISTDEPTH 1024
2347
2348int add_member_to_list(q, argv, cl)
2349 struct query *q;
2350 char **argv;
2351 client *cl;
2352{
2353 EXEC SQL BEGIN DECLARE SECTION;
2354 int id, lid, mid, error, who, ref, rowcnt;
2355 char *mtype, dtype[9], *entity;
2356 EXEC SQL END DECLARE SECTION;
2357 int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a;
2358 int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d;
2359 int status;
2360 char *dtypes[MAXLISTDEPTH];
2361 char *iargv[3], *buf;
2362
2363 lid = *(int *)argv[0];
2364 mtype = argv[1];
2365 mid = *(int *)argv[2];
2366 /* if the member is already a direct member of the list, punt */
2367 EXEC SQL REPEATED SELECT COUNT(list_id) INTO :rowcnt FROM imembers
2368 WHERE list_id = :lid AND member_id = :mid
2369 AND member_type = :mtype AND direct = 1;
2370 if (rowcnt > 0)
2371 return(MR_EXISTS);
2372 if (!strcasecmp(mtype, "STRING")) {
2373 buf = malloc(0);
2374 status = id_to_name(mid, "STRING", &buf);
2375 if (status) return(status);
2376 if (index(buf, '/') || index(buf, '|')) {
2377 free(buf);
2378 return(MR_BAD_CHAR);
2379 }
2380 free(buf);
2381 }
2382
2383 ancestors[0] = lid;
2384 aref[0] = 1;
2385 acount = 1;
2386 EXEC SQL DECLARE csr103 CURSOR FOR
2387 SELECT list_id, ref_count FROM imembers
2388 WHERE member_id = :lid AND member_type='LIST';
2389 if (ingres_errno)
2390 return(mr_errcode);
2391 EXEC SQL OPEN csr103;
2392 if (ingres_errno)
2393 return(mr_errcode);
2394 while(1) {
2395 EXEC SQL FETCH csr103 INTO :id, :ref;
2396 if(sqlca.sqlcode != 0) break;
2397 aref[acount] = ref;
2398 ancestors[acount++] = id;
2399 if (acount >= MAXLISTDEPTH) break;
2400 }
2401 EXEC SQL CLOSE csr103;
2402 if (ingres_errno) return(mr_errcode);
2403 if (acount >= MAXLISTDEPTH) {
2404 return(MR_INTERNAL);
2405 }
2406 descendants[0] = mid;
2407 dtypes[0] = mtype;
2408 dref[0] = 1;
2409 dcount = 1;
2410 error = 0;
2411 if (!strcmp(mtype, "LIST")) {
2412 EXEC SQL DECLARE csr104 CURSOR FOR
2413 SELECT member_id, member_type, ref_count
2414 FROM imembers
2415 WHERE list_id = :mid;
2416 if (ingres_errno)
2417 return(mr_errcode);
2418 EXEC SQL OPEN csr104;
2419 if (ingres_errno)
2420 return(mr_errcode);
2421 while(1) {
2422 EXEC SQL FETCH csr104 INTO :id, :dtype, :ref;
2423 if(sqlca.sqlcode != 0) break;
2424 switch (dtype[0]) {
2425 case 'L':
2426 dtypes[dcount] = "LIST";
2427 break;
2428 case 'U':
2429 dtypes[dcount] = "USER";
2430 break;
2431 case 'S':
2432 dtypes[dcount] = "STRING";
2433 break;
2434 case 'K':
2435 dtypes[dcount] = "KERBEROS";
2436 break;
2437 default:
2438 error++;
2439 break;
2440 }
2441 dref[dcount] = ref;
2442 descendants[dcount++] = id;
2443 if (dcount >= MAXLISTDEPTH) {
2444 error++;
2445 break;
2446 }
2447 }
2448 EXEC SQL CLOSE csr104;
2449 if (ingres_errno) return(mr_errcode);
2450 if (error)
2451 return(MR_INTERNAL);
2452 }
2453 for (a = 0; a < acount; a++) {
2454 lid = ancestors[a];
2455 for (d = 0; d < dcount; d++) {
2456 mid = descendants[d];
2457 mtype = dtypes[d];
2458 if (mid == lid && !strcmp(mtype, "LIST")) {
2459 return(MR_LISTLOOP);
2460 }
2461 EXEC SQL REPEATED SELECT COUNT(ref_count) INTO :rowcnt
2462 FROM imembers
2463 WHERE list_id = :lid AND member_id = :mid
2464 AND member_type = :mtype;
2465 ref = aref[a] * dref[d];
2466 if (rowcnt > 0) {
2467 if (a == 0 && d == 0) {
2468 EXEC SQL UPDATE imembers
2469 SET ref_count = ref_count+:ref, direct=1
2470 WHERE list_id = :lid AND member_id = :mid
2471 AND member_type = :mtype;
2472 } else {
2473 EXEC SQL UPDATE imembers
2474 SET ref_count = ref_count+:ref
2475 WHERE list_id = :lid AND member_id = :mid
2476 AND member_type = :mtype;
2477 }
2478 } else {
2479 incremental_clear_before();
2480 if (a == 0 && d == 0) {
2481 EXEC SQL INSERT INTO imembers
2482 (list_id, member_id, direct, member_type, ref_count)
2483 VALUES (:lid, :mid, 1, :mtype, 1);
2484 } else {
2485 EXEC SQL INSERT INTO imembers
2486 (list_id, member_id, member_type, ref_count)
2487 VALUES (:lid, :mid, :mtype, 1);
2488 }
2489 iargv[0] = (char *)lid;
2490 iargv[1] = mtype;
2491 iargv[2] = (char *)mid;
2492 incremental_after("members", 0, iargv);
2493 }
2494 }
2495 }
2496 lid = *(int *)argv[0];
2497 entity = cl->entity;
2498 who = cl->client_id;
2499 EXEC SQL REPEATED UPDATE list
2500 SET modtime='now', modby = :who, modwith = :entity
2501 WHERE list_id = :lid;
2502 if (ingres_errno) return(mr_errcode);
2503 return(MR_SUCCESS);
2504}
2505
2506
2507/* Delete_member_from_list: do list flattening as we go!
2508 */
2509
2510int delete_member_from_list(q, argv, cl)
2511 struct query *q;
2512 char **argv;
2513 client *cl;
2514{
2515 EXEC SQL BEGIN DECLARE SECTION;
2516 int id, lid, mid, cnt, error, who, ref;
2517 char *mtype, dtype[9], *entity;
2518 EXEC SQL END DECLARE SECTION;
2519 int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a;
2520 int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d;
2521 char *dtypes[MAXLISTDEPTH];
2522 char *iargv[3];
2523
2524 lid = *(int *)argv[0];
2525 mtype = argv[1];
2526 mid = *(int *)argv[2];
2527 /* if the member is not a direct member of the list, punt */
2528 EXEC SQL REPEATED SELECT COUNT(list_id) INTO :cnt FROM imembers
2529 WHERE list_id = :lid AND member_id = :mid
2530 AND member_type = :mtype AND direct = 1;
2531 if (ingres_errno) return(mr_errcode);
2532 if (cnt == 0)
2533 return(MR_NO_MATCH);
2534 ancestors[0] = lid;
2535 aref[0] = 1;
2536 acount = 1;
2537 EXEC SQL DECLARE csr105 CURSOR FOR
2538 SELECT list_id, ref_count FROM imembers
2539 WHERE member_id = :lid AND member_type = 'LIST';
2540 if (ingres_errno)
2541 return(mr_errcode);
2542 EXEC SQL OPEN csr105;
2543 if (ingres_errno)
2544 return(mr_errcode);
2545 while(1) {
2546 EXEC SQL FETCH csr105 INTO :id, :ref;
2547 if(sqlca.sqlcode!=0) break;
2548 aref[acount] = ref;
2549 ancestors[acount++] = id;
2550 if (acount >= MAXLISTDEPTH) break;
2551 }
2552 EXEC SQL CLOSE csr105;
2553 if (ingres_errno)
2554 return(mr_errcode);
2555 if (acount >= MAXLISTDEPTH)
2556 return(MR_INTERNAL);
2557 descendants[0] = mid;
2558 dtypes[0] = mtype;
2559 dref[0] = 1;
2560 dcount = 1;
2561 error = 0;
2562 if (!strcmp(mtype, "LIST")) {
2563 EXEC SQL DECLARE csr106 CURSOR FOR
2564 SELECT member_id, member_type, ref_count FROM imembers
2565 WHERE list_id = :mid;
2566 if (ingres_errno)
2567 return(mr_errcode);
2568 EXEC SQL OPEN csr106;
2569 if (ingres_errno)
2570 return(mr_errcode);
2571 while(1) {
2572 EXEC SQL FETCH csr106 INTO :id, :dtype, :ref;
2573 if(sqlca.sqlcode!=0) break;
2574 switch (dtype[0]) {
2575 case 'L':
2576 dtypes[dcount] = "LIST";
2577 break;
2578 case 'U':
2579 dtypes[dcount] = "USER";
2580 break;
2581 case 'S':
2582 dtypes[dcount] = "STRING";
2583 break;
2584 case 'K':
2585 dtypes[dcount] = "KERBEROS";
2586 break;
2587 default:
2588 error++;
2589 break;
2590 }
2591 dref[dcount] = ref;
2592 descendants[dcount++] = id;
2593 if (dcount >= MAXLISTDEPTH) break;
2594 }
2595 EXEC SQL CLOSE csr106;
2596 if (ingres_errno)
2597 return(mr_errcode);
2598 if (error)
2599 return(MR_INTERNAL);
2600 }
2601 for (a = 0; a < acount; a++) {
2602 lid = ancestors[a];
2603 for (d = 0; d < dcount; d++) {
2604 mid = descendants[d];
2605 mtype = dtypes[d];
2606 if (mid == lid && !strcmp(mtype, "LIST")) {
2607 return(MR_LISTLOOP);
2608 }
2609 EXEC SQL REPEATED SELECT ref_count INTO :cnt FROM imembers
2610 WHERE list_id = :lid AND member_id = :mid AND member_type = :mtype;
2611 ref = aref[a] * dref[d];
2612 if (cnt <= ref) {
2613 iargv[0] = (char *)lid;
2614 iargv[1] = mtype;
2615 iargv[2] = (char *)mid;
2616 incremental_before("members", 0, iargv);
2617 EXEC SQL DELETE FROM imembers
2618 WHERE list_id = :lid AND member_id = :mid
2619 AND member_type= :mtype;
2620 incremental_clear_after();
2621 } else if (a == 0 && d == 0) {
2622 EXEC SQL UPDATE imembers
2623 SET ref_count = ref_count - :ref, direct = 0
2624 WHERE list_id = :lid AND member_id = :mid
2625 AND member_type = :mtype;
2626 } else {
2627 EXEC SQL UPDATE imembers
2628 SET ref_count = ref_count - :ref
2629 WHERE list_id = :lid AND member_id = :mid
2630 AND member_type = :mtype;
2631 }
2632 }
2633 }
2634 lid = *(int *)argv[0];
2635 entity = cl->entity;
2636 who = cl->client_id;
2637 EXEC SQL UPDATE list SET modtime = 'now', modby = :who, modwith = :entity
2638 WHERE list_id = :lid;
2639 if (ingres_errno) return(mr_errcode);
2640 return(MR_SUCCESS);
2641}
2642
2643
2644/* get_ace_use - given a type and a name, return a type and a name.
2645 * The ace_type is one of "LIST", "USER", "RLIST", or "RUSER" in argv[0],
2646 * and argv[1] will contain the ID of the entity in question. The R*
2647 * types mean to recursively look at every containing list, not just
2648 * when the object in question is a direct member. On return, the
2649 * usage type will be one of LIST, SERVICE, FILESYS, QUOTA, QUERY, or ZEPHYR.
2650 */
2651
2652int get_ace_use(q, argv, cl, action, actarg)
2653 struct query *q;
2654 char *argv[];
2655 client *cl;
2656 int (*action)();
2657 int actarg;
2658{
2659 int found = 0;
2660 EXEC SQL BEGIN DECLARE SECTION;
2661 char *atype;
2662 int aid, listid, id;
2663 EXEC SQL END DECLARE SECTION;
2664 struct save_queue *sq, *sq_create();
2665
2666 atype = argv[0];
2667 aid = *(int *)argv[1];
2668 if (!strcmp(atype, "LIST") || !strcmp(atype, "USER") ||
2669 !strcmp(atype, "KERBEROS")) {
2670 return(get_ace_internal(atype, aid, action, actarg));
2671 }
2672
2673 sq = sq_create();
2674 if (!strcmp(atype, "RLIST")) {
2675 sq_save_data(sq, aid);
2676 /* get all the list_id's of containing lists */
2677 EXEC SQL DECLARE csr107 CURSOR FOR
2678 SELECT list_id FROM imembers
2679 WHERE member_type='LIST' AND member_id = :aid;
2680 if (ingres_errno)
2681 return(mr_errcode);
2682 EXEC SQL OPEN csr107;
2683 if (ingres_errno)
2684 return(mr_errcode);
2685 while(1) {
2686 EXEC SQL FETCH csr107 INTO :listid;
2687 if(sqlca.sqlcode != 0) break;
2688 sq_save_unique_data(sq, listid);
2689 }
2690 EXEC SQL CLOSE csr107;
2691 /* now process each one */
2692 while (sq_get_data(sq, &id)) {
2693 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2694 found++;
2695 }
2696 }
2697
2698 if (!strcmp(atype, "RUSER")) {
2699 EXEC SQL DECLARE csr108 CURSOR FOR
2700 SELECT list_id FROM imembers
2701 WHERE member_type='USER' AND member_id = :aid;
2702 if (ingres_errno)
2703 return(mr_errcode);
2704 EXEC SQL OPEN csr108;
2705 if (ingres_errno)
2706 return(mr_errcode);
2707 while(1) {
2708 EXEC SQL FETCH csr108 INTO :listid;
2709 if(sqlca.sqlcode != 0) break;
2710 sq_save_data(sq, listid);
2711 }
2712 EXEC SQL CLOSE csr108;
2713 /* now process each one */
2714 while (sq_get_data(sq, &id)) {
2715 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2716 found++;
2717 }
2718 if (get_ace_internal("USER", aid, action, actarg) == MR_SUCCESS)
2719 found++;
2720 }
2721
2722 if (!strcmp(atype, "RKERBERO")) {
2723 EXEC SQL DECLARE csr109 CURSOR FOR
2724 SELECT list_id FROM imembers
2725 WHERE member_type='KERBEROS' AND member_id = :aid;
2726 if (ingres_errno)
2727 return(mr_errcode);
2728 EXEC SQL OPEN csr109;
2729 if (ingres_errno)
2730 return(mr_errcode);
2731 while(1) {
2732 EXEC SQL FETCH csr109 INTO :listid;
2733 if(sqlca.sqlcode != 0) break;
2734 sq_save_data(sq, listid);
2735 }
2736 EXEC SQL CLOSE csr109;
2737 /* now process each one */
2738 while (sq_get_data(sq, &id)) {
2739 if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS)
2740 found++;
2741 }
2742 if (get_ace_internal("KERBEROS", aid, action, actarg) == MR_SUCCESS)
2743 found++;
2744 }
2745
2746 sq_destroy(sq);
2747 if (ingres_errno) return(mr_errcode);
2748 if (!found) return(MR_NO_MATCH);
2749 return(MR_SUCCESS);
2750}
2751
2752
2753/* This looks up a single list or user for ace use. atype must be "USER"
2754 * or "LIST", and aid is the ID of the corresponding object. This is used
2755 * by get_ace_use above.
2756 */
2757
2758get_ace_internal(atype, aid, action, actarg)
2759 EXEC SQL BEGIN DECLARE SECTION;
2760 char *atype;
2761 int aid;
2762 EXEC SQL END DECLARE SECTION;
2763 int (*action)();
2764 int actarg;
2765{
2766 char *rargv[2];
2767 int found = 0;
2768 EXEC SQL BEGIN DECLARE SECTION;
2769 char name[33];
2770 EXEC SQL END DECLARE SECTION;
2771
2772 rargv[1] = name;
2773 if (!strcmp(atype, "LIST")) {
2774 rargv[0] = "FILESYS";
2775 EXEC SQL DECLARE csr110 CURSOR FOR
2776 SELECT label FROM filesys
2777 WHERE owners = :aid;
2778 if (ingres_errno)
2779 return(mr_errcode);
2780 EXEC SQL OPEN csr110;
2781 if (ingres_errno)
2782 return(mr_errcode);
2783 while(1) {
2784 EXEC SQL FETCH csr110 INTO :name;
2785 if(sqlca.sqlcode != 0) break;
2786 (*action)(2, rargv, actarg);
2787 found++;
2788 }
2789 EXEC SQL CLOSE csr110;
2790
2791 rargv[0] = "QUERY";
2792 EXEC SQL DECLARE csr111 CURSOR FOR
2793 SELECT capability FROM capacls
2794 WHERE list_id = :aid ;
2795 if (ingres_errno)
2796 return(mr_errcode);
2797 EXEC SQL OPEN csr111;
2798 if (ingres_errno)
2799 return(mr_errcode);
2800 while(1) {
2801 EXEC SQL FETCH csr111 INTO :name ;
2802 if(sqlca.sqlcode != 0) break;
2803 (*action)(2, rargv, actarg);
2804 found++;
2805 }
2806 EXEC SQL CLOSE csr111;
2807 } else if (!strcmp(atype, "USER")) {
2808 rargv[0] = "FILESYS";
2809 EXEC SQL DECLARE csr112 CURSOR FOR
2810 SELECT label FROM filesys
2811 WHERE owner = :aid;
2812 if (ingres_errno)
2813 return(mr_errcode);
2814 EXEC SQL OPEN csr112;
2815 if (ingres_errno)
2816 return(mr_errcode);
2817 while(1) {
2818 EXEC SQL FETCH csr112 INTO :name ;
2819 if(sqlca.sqlcode != 0) break;
2820 (*action)(2, rargv, actarg);
2821 found++;
2822 }
2823 EXEC SQL CLOSE csr112;
2824 }
2825
2826 rargv[0] = "LIST";
2827 EXEC SQL DECLARE csr113 CURSOR FOR
2828 SELECT name FROM list
2829 WHERE acl_type = :atype AND acl_id = :aid;
2830 if (ingres_errno)
2831 return(mr_errcode);
2832 EXEC SQL OPEN csr113;
2833 if (ingres_errno)
2834 return(mr_errcode);
2835 while(1) {
2836 EXEC SQL FETCH csr113 INTO :name;
2837 if(sqlca.sqlcode != 0) break;
2838 (*action)(2, rargv, actarg);
2839 found++;
2840 }
2841 EXEC SQL CLOSE csr113;
2842
2843 rargv[0] = "SERVICE";
2844 EXEC SQL DECLARE csr114 CURSOR FOR
2845 SELECT name FROM servers
2846 WHERE acl_type = :atype AND acl_id = :aid;
2847 if (ingres_errno)
2848 return(mr_errcode);
2849 EXEC SQL OPEN csr114;
2850 if (ingres_errno)
2851 return(mr_errcode);
2852 while(1) {
2853 EXEC SQL FETCH csr114 INTO :name;
2854 if(sqlca.sqlcode != 0) break;
2855 (*action)(2, rargv, actarg);
2856 found++;
2857 }
2858 EXEC SQL CLOSE csr114;
2859
2860 rargv[0] = "HOSTACCESS";
2861 EXEC SQL DECLARE csr115 CURSOR FOR
2862 SELECT name FROM machine m, hostaccess ha
2863 WHERE m.mach_id = ha.mach_id AND ha.acl_type = :atype
2864 AND ha.acl_id = :aid;
2865 if (ingres_errno)
2866 return(mr_errcode);
2867 EXEC SQL OPEN csr115;
2868 if (ingres_errno)
2869 return(mr_errcode);
2870 while(1) {
2871 EXEC SQL FETCH csr115 INTO :name;
2872 if(sqlca.sqlcode != 0) break;
2873 (*action)(2, rargv, actarg);
2874 found++;
2875 }
2876 EXEC SQL CLOSE csr115;
2877
2878 rargv[0] = "ZEPHYR";
2879 EXEC SQL DECLARE csr116 CURSOR FOR
2880 SELECT class FROM zephyr z
2881 WHERE z.xmt_type = :atype AND z.xmt_id = :aid
2882 OR z.sub_type = :atype AND z.sub_id = :aid
2883 OR z.iws_type = :atype AND z.iws_id = :aid
2884 OR z.iui_type = :atype AND z.iui_id = :aid;
2885 if (ingres_errno)
2886 return(mr_errcode);
2887 EXEC SQL OPEN csr116;
2888 if (ingres_errno)
2889 return(mr_errcode);
2890 while(1) {
2891 EXEC SQL FETCH csr116 INTO :name;
2892 if(sqlca.sqlcode != 0) break;
2893 (*action)(2, rargv, actarg);
2894 found++;
2895 }
2896 EXEC SQL CLOSE csr116;
2897
2898 if (!found) return(MR_NO_MATCH);
2899 return(MR_SUCCESS);
2900}
2901
2902
2903/* get_lists_of_member - given a type and a name, return the name and flags
2904 * of all of the lists of the given member. The member_type is one of
2905 * "LIST", "USER", "STRING", "RLIST", "RUSER", or "RSTRING" in argv[0],
2906 * and argv[1] will contain the ID of the entity in question. The R*
2907 * types mean to recursively look at every containing list, not just
2908 * when the object in question is a direct member.
2909 */
2910
2911int get_lists_of_member(q, argv, cl, action, actarg)
2912 struct query *q;
2913 char *argv[];
2914 client *cl;
2915 int (*action)();
2916 int actarg;
2917{
2918 int found = 0, direct = 1;
2919 char *rargv[6];
2920 EXEC SQL BEGIN DECLARE SECTION;
2921 char *atype;
2922 int aid, listid, id;
2923 char name[33], active[5], public[5], hidden[5], maillist[5], grouplist[5];
2924 EXEC SQL END DECLARE SECTION;
2925
2926 atype = argv[0];
2927 aid = *(int *)argv[1];
2928 if (!strcmp(atype, "RLIST")) {
2929 atype = "LIST";
2930 direct = 0;
2931 }
2932 if (!strcmp(atype, "RUSER")) {
2933 atype = "USER";
2934 direct = 0;
2935 }
2936 if (!strcmp(atype, "RSTRING")) {
2937 atype = "STRING";
2938 direct = 0;
2939 }
2940 if (!strcmp(atype, "RKERBEROS")) {
2941 atype = "KERBEROS";
2942 direct = 0;
2943 }
2944
2945 rargv[0] = name;
2946 rargv[1] = active;
2947 rargv[2] = public;
2948 rargv[3] = hidden;
2949 rargv[4] = maillist;
2950 rargv[5] = grouplist;
2951 if (direct) {
2952 EXEC SQL DECLARE csr117a CURSOR FOR
2953 SELECT l.name, CHAR(l.active), CHAR(l.publicflg), CHAR(l.hidden),
2954 CHAR(l.maillist), CHAR(l.grouplist)
2955 FROM list l, imembers im
2956 WHERE l.list_id = im.list_id AND im.direct = 1
2957 AND im.member_type = :atype AND im.member_id = :aid;
2958 if (ingres_errno)
2959 return(mr_errcode);
2960 EXEC SQL OPEN csr117a;
2961 if (ingres_errno)
2962 return(mr_errcode);
2963 while(1) {
2964 EXEC SQL FETCH csr117a
2965 INTO :name, :active, :public, :hidden, :maillist, :grouplist;
2966 if(sqlca.sqlcode != 0) break;
2967 (*action)(6, rargv, actarg);
2968 found++;
2969 }
2970 EXEC SQL CLOSE csr117a;
2971 } else {
2972 EXEC SQL DECLARE csr117b CURSOR FOR
2973 SELECT l.name, CHAR(l.active), CHAR(l.publicflg), CHAR(l.hidden),
2974 CHAR(l.maillist), CHAR(l.grouplist)
2975 FROM list l, imembers im
2976 WHERE l.list_id = im.list_id
2977 AND im.member_type = :atype AND im.member_id = :aid;
2978 if (ingres_errno)
2979 return(mr_errcode);
2980 EXEC SQL OPEN csr117b;
2981 if (ingres_errno)
2982 return(mr_errcode);
2983 while(1) {
2984 EXEC SQL FETCH csr117b
2985 INTO :name, :active, :public, :hidden, :maillist, :grouplist;
2986 if(sqlca.sqlcode != 0) break;
2987 (*action)(6, rargv, actarg);
2988 found++;
2989 }
2990 EXEC SQL CLOSE csr117b;
2991 }
2992
2993 if (ingres_errno) return(mr_errcode);
2994 if (!found) return(MR_NO_MATCH);
2995 return(MR_SUCCESS);
2996}
2997
2998
2999/* qualified_get_lists: passed "TRUE", "FALSE", or "DONTCARE" for each of
3000 * the five flags associated with each list. It will return the name of
3001 * each list that meets the quailifications. It does this by building a
3002 * where clause based on the arguments, then doing a retrieve.
3003 */
3004
3005static char *lflags[5] = { "active", "publicflg", "hidden", "maillist", "grouplist" };
3006
3007int qualified_get_lists(q, argv, cl, action, actarg)
3008 struct query *q;
3009 char *argv[];
3010 client *cl;
3011 int (*action)();
3012 int actarg;
3013{
3014 return(qualified_get(q, argv, action, actarg, "l.list_id != 0",
3015 "l", "name", lflags));
3016}
3017
3018
3019/* get_members_of_list - this gets only direct members */
3020
3021get_members_of_list(q, argv, cl, action, actarg)
3022 struct query *q;
3023 char *argv[];
3024 client *cl;
3025 int (*action)();
3026 int actarg;
3027{
3028 return(gmol_internal(q, argv, cl, action, actarg, 1));
3029}
3030
3031/* get_end_members_of_list - this gets direct or indirect members */
3032
3033get_end_members_of_list(q, argv, cl, action, actarg)
3034 struct query *q;
3035 char *argv[];
3036 client *cl;
3037 int (*action)();
3038 int actarg;
3039{
3040 return(gmol_internal(q, argv, cl, action, actarg, 0));
3041}
3042
3043/** gmol_internal - optimized query for retrieval of list members
3044 ** used by both get_members_of_list and get_end_members_of_list
3045 **
3046 ** Inputs:
3047 ** argv[0] - list_id
3048 **
3049 ** Description:
3050 ** - retrieve USER members, then LIST members, then STRING members
3051 **/
3052
3053gmol_internal(q, argv, cl, action, actarg, flag)
3054 struct query *q;
3055 char *argv[];
3056 client *cl;
3057 int (*action)();
3058 int actarg;
3059 int flag;
3060{
3061 EXEC SQL BEGIN DECLARE SECTION;
3062 int list_id, member_id, direct;
3063 char member_name[129], member_type[9];
3064 EXEC SQL END DECLARE SECTION;
3065 char *targv[2];
3066 int members;
3067 struct save_queue *sq;
3068
3069 /* true/false flag indicates whether to display only direct members. */
3070 if (flag)
3071 direct = 0;
3072 else
3073 direct = -1;
3074
3075 list_id = *(int *)argv[0];
3076 members = 0;
3077 sq = sq_create();
3078
3079 EXEC SQL DECLARE csr118 CURSOR FOR
3080 SELECT member_type, member_id FROM imembers
3081 WHERE list_id = :list_id AND direct > :direct;
3082 if (ingres_errno)
3083 return(mr_errcode);
3084 EXEC SQL OPEN csr118;
3085 if (ingres_errno)
3086 return(mr_errcode);
3087 while(1) {
3088 EXEC SQL FETCH csr118 INTO :member_type, :member_id;
3089 if (sqlca.sqlcode != 0) break;
3090 if (members++ > 49)
3091 break;
3092 sq_save_data(sq, ((int)member_type[0] << 24) | (member_id & 0xffffff));
3093 }
3094 EXEC SQL CLOSE csr118;
3095
3096 if (members <= 49) {
3097 targv[1] = malloc(0);
3098 while (sq_remove_data(sq, &member_id)) {
3099 switch (member_id >> 24) {
3100 case 'U':
3101 targv[0] = "USER";
3102 id_to_name(member_id & 0xffffff, "USER", &targv[1]);
3103 (*action)(2, targv, actarg);
3104 break;
3105 case 'L':
3106 targv[0] = "LIST";
3107 id_to_name(member_id & 0xffffff, "LIST", &targv[1]);
3108 (*action)(2, targv, actarg);
3109 break;
3110 case 'S':
3111 targv[0] = "STRING";
3112 id_to_name(member_id & 0xffffff, "STRING", &targv[1]);
3113 (*action)(2, targv, actarg);
3114 break;
3115 case 'K':
3116 targv[0] = "KERBEROS";
3117 id_to_name(member_id & 0xffffff, "STRING", &targv[1]);
3118 (*action)(2, targv, actarg);
3119 break;
3120 default:
3121 sq_destroy(sq);
3122 return(MR_INTERNAL);
3123 }
3124 }
3125 free(targv[1]);
3126 sq_destroy(sq);
3127 return(MR_SUCCESS);
3128 }
3129 sq_destroy(sq);
3130
3131 targv[1] = member_name;
3132 targv[0] = "USER";
3133 EXEC SQL DECLARE csr119 CURSOR FOR
3134 SELECT u.login FROM users u, imembers im
3135 WHERE im.list_id = :list_id AND im.member_type = 'USER'
3136 AND im.member_id = u.users_id AND im.direct > :direct
3137 ORDER BY 1;
3138 if (ingres_errno)
3139 return(mr_errcode);
3140 EXEC SQL OPEN csr119;
3141 if (ingres_errno)
3142 return(mr_errcode);
3143 while(1) {
3144 EXEC SQL FETCH csr119 INTO :member_name;
3145 if(sqlca.sqlcode != 0) break;
3146 (*action)(2, targv, actarg);
3147 }
3148 EXEC SQL CLOSE csr119;
3149 if (ingres_errno) return(mr_errcode);
3150
3151 targv[0] = "LIST";
3152 EXEC SQL DECLARE csr120 CURSOR FOR
3153 SELECT l.name FROM list l, imembers im
3154 WHERE im.list_id = :list_id AND im.member_type='LIST'
3155 AND im.member_id = l.list_id AND im.direct > :direct
3156 ORDER BY 1;
3157 if (ingres_errno)
3158 return(mr_errcode);
3159 EXEC SQL OPEN csr120;
3160 if (ingres_errno)
3161 return(mr_errcode);
3162 while(1) {
3163 EXEC SQL FETCH csr120 INTO :member_name;
3164 if(sqlca.sqlcode != 0) break;
3165 (*action)(2, targv, actarg);
3166 }
3167 EXEC SQL CLOSE csr120;
3168 if (ingres_errno) return(mr_errcode);
3169
3170 targv[0] = "STRING";
3171 EXEC SQL DECLARE csr121 CURSOR FOR
3172 SELECT CHAR(str.string) FROM strings str, imembers im
3173 WHERE im.list_id = :list_id AND im.member_type='STRING'
3174 AND im.member_id = str.string_id AND im.direct > :direct
3175 ORDER BY 1;
3176 if (ingres_errno)
3177 return(mr_errcode);
3178 EXEC SQL OPEN csr121;
3179 if (ingres_errno)
3180 return(mr_errcode);
3181 while(1) {
3182 EXEC SQL FETCH csr121 INTO :member_name;
3183 if(sqlca.sqlcode != 0) break;
3184 (*action)(2, targv, actarg);
3185 }
3186 EXEC SQL CLOSE csr121;
3187 if (ingres_errno) return(mr_errcode);
3188
3189 targv[0] = "KERBEROS";
3190 EXEC SQL DECLARE csr122 CURSOR FOR
3191 SELECT CHAR(str.string) FROM strings str, imembers im
3192 WHERE im.list_id = :list_id AND im.member_type='KERBEROS'
3193 AND im.member_id = str.string_id
3194 AND im.direct > :direct
3195 ORDER BY 1;
3196 if (ingres_errno)
3197 return(mr_errcode);
3198 EXEC SQL OPEN csr122;
3199 if (ingres_errno)
3200 return(mr_errcode);
3201 while(1) {
3202 EXEC SQL FETCH csr122 INTO :member_name;
3203 if(sqlca.sqlcode != 0) break;
3204 (*action)(2, targv, actarg);
3205 }
3206 EXEC SQL CLOSE csr122;
3207 if (ingres_errno) return(mr_errcode);
3208
3209 return(MR_SUCCESS);
3210}
3211
3212
3213/* count_members_of_list: this is a simple query, but it cannot be done
3214 * through the dispatch table.
3215 */
3216
3217int count_members_of_list(q, argv, cl, action, actarg)
3218 struct query *q;
3219 char *argv[];
3220 client *cl;
3221 int (*action)();
3222 int actarg;
3223{
3224 EXEC SQL BEGIN DECLARE SECTION;
3225 int list, ct = 0;
3226 EXEC SQL END DECLARE SECTION;
3227 char *rargv[1], countbuf[5];
3228
3229 list = *(int *)argv[0];
3230 rargv[0] = countbuf;
3231 EXEC SQL REPEATED SELECT count (*) INTO :ct FROM imembers
3232 WHERE list_id = :list AND direct=1;
3233 if (ingres_errno) return(mr_errcode);
3234 sprintf(countbuf, "%d", ct);
3235 (*action)(1, rargv, actarg);
3236 return(MR_SUCCESS);
3237}
3238
3239
3240/* qualified_get_server: passed "TRUE", "FALSE", or "DONTCARE" for each of
3241 * the three flags associated with each service. It will return the name of
3242 * each service that meets the quailifications. It does this by building a
3243 * where clause based on the arguments, then doing a retrieve.
3244 */
3245
3246static char *sflags[3] = { "enable", "inprogress", "harderror" };
3247
3248int qualified_get_server(q, argv, cl, action, actarg)
3249 struct query *q;
3250 char *argv[];
3251 client *cl;
3252 int (*action)();
3253 int actarg;
3254{
3255 return(qualified_get(q, argv, action, actarg, "s.name != ''",
3256 "s", "name", sflags));
3257}
3258
3259
3260/* generic qualified get routine, used by qualified_get_lists,
3261 * qualified_get_server, and qualified_get_serverhost.
3262 * Args:
3263 * start - a simple where clause, must not be empty
3264 * range - the name of the range variable
3265 * field - the field to return
3266 * flags - an array of strings, names of the flag variables
3267 */
3268
3269int qualified_get(q, argv, action, actarg, start, range, field, flags)
3270 struct query *q;
3271 char *argv[];
3272 int (*action)();
3273 int actarg;
3274 char *start;
3275 char *range;
3276 char *field;
3277 char *flags[];
3278{
3279 char name[33], qual[256];
3280 int rowcount=0, i;
3281 char *rargv[1], buf[32];
3282
3283 strcpy(qual, start);
3284 for (i = 0; i < q->argc; i++) {
3285 if (!strcmp(argv[i], "TRUE")) {
3286 sprintf(buf, " AND %s.%s != 0", range, flags[i]);
3287 (void) strcat(qual, buf);
3288 } else if (!strcmp(argv[i], "FALSE")) {
3289 sprintf(buf, " AND %s.%s = 0", range, flags[i]);
3290 (void) strcat(qual, buf);
3291 }
3292 }
3293
3294 rargv[0] = SQLDA->sqlvar[0].sqldata;
3295 sprintf(stmt_buf,"SELECT CHAR(%s.%s) FROM %s %s WHERE %s",range,field,q->rtable,range,qual);
3296 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3297 if(sqlca.sqlcode)
3298 return(MR_INTERNAL);
3299 EXEC SQL DECLARE csr123 CURSOR FOR stmt;
3300 EXEC SQL OPEN csr123;
3301 while(1) {
3302 EXEC SQL FETCH csr123 USING DESCRIPTOR :SQLDA;
3303 if(sqlca.sqlcode != 0) break;
3304 rowcount++;
3305 (*action)(1, rargv, actarg);
3306 }
3307 EXEC SQL CLOSE csr123;
3308 if (ingres_errno) return(mr_errcode);
3309 if (rowcount == 0)
3310 return(MR_NO_MATCH);
3311 return(MR_SUCCESS);
3312}
3313
3314
3315/* qualified_get_serverhost: passed "TRUE", "FALSE", or "DONTCARE" for each of
3316 * the five flags associated with each serverhost. It will return the name of
3317 * each service and host that meets the quailifications. It does this by
3318 * building a where clause based on the arguments, then doing a retrieve.
3319 */
3320
3321static char *shflags[6] = { "service", "enable", "override", "success",
3322 "inprogress", "hosterror" };
3323
3324int qualified_get_serverhost(q, argv, cl, action, actarg)
3325 struct query *q;
3326 char *argv[];
3327 client *cl;
3328 int (*action)();
3329 int actarg;
3330{
3331 EXEC SQL BEGIN DECLARE SECTION;
3332 char sname[33], mname[33], qual[256];
3333 EXEC SQL END DECLARE SECTION;
3334 char *rargv[2], buf[32];
3335 int i, rowcount;
3336
3337 sprintf(qual, "m.mach_id = sh.mach_id AND sh.service = uppercase('%s')",
3338 argv[0]);
3339 for (i = 1; i < q->argc; i++) {
3340 if (!strcmp(argv[i], "TRUE")) {
3341 sprintf(buf, " AND sh.%s != 0", shflags[i]);
3342 strcat(qual, buf);
3343 } else if (!strcmp(argv[i], "FALSE")) {
3344 sprintf(buf, " AND sh.%s = 0", shflags[i]);
3345 strcat(qual, buf);
3346 }
3347 }
3348
3349 rargv[0] = sname;
3350 rargv[1] = mname;
3351 EXEC SQL DECLARE csr124 CURSOR FOR
3352 SELECT sh.service, m.name FROM serverhosts sh, machine m
3353 WHERE :qual;
3354 if (ingres_errno)
3355 return(mr_errcode);
3356 EXEC SQL OPEN csr124;
3357 if (ingres_errno)
3358 return(mr_errcode);
3359 while(1) {
3360 EXEC SQL FETCH csr124 INTO :sname, :mname;
3361 if(sqlca.sqlcode != 0) break;
3362 rowcount++;
3363 (*action)(2, rargv, actarg);
3364 }
3365 EXEC SQL CLOSE csr124;
3366
3367 if (ingres_errno) return(mr_errcode);
3368 if (rowcount == 0)
3369 return(MR_NO_MATCH);
3370 return(MR_SUCCESS);
3371}
3372
3373
3374/* register_user - change user's login name and allocate a pobox, group,
3375 * filesystem, and quota for them. The user's status must start out as 0,
3376 * and is left as 2. Arguments are: user's UID, new login name, and user's
3377 * type for filesystem allocation (MR_FS_STUDENT, MR_FS_FACULTY,
3378 * MR_FS_STAFF, MR_FS_MISC).
3379 */
3380
3381register_user(q, argv, cl)
3382 struct query *q;
3383 char **argv;
3384 client *cl;
3385{
3386 EXEC SQL BEGIN DECLARE SECTION;
3387 char *login, dir[65], *entity, directory[129], machname[33];
3388 int who, rowcount, mid, uid, users_id, flag, utype, nid, list_id, quota;
3389 int size, alloc, pid, ostatus, nstatus, gidval, fsidval, npidval;
3390 static int m_id = 0, def_quota = 0;
3391 EXEC SQL END DECLARE SECTION;
3392 char buffer[256], *aargv[3];
3393
3394 entity = cl->entity;
3395 who = cl->client_id;
3396
3397 uid = atoi(argv[0]);
3398 login = argv[1];
3399 utype = atoi(argv[2]);
3400
3401 /* find user */
3402 EXEC SQL REPEATED SELECT users_id, status INTO :users_id, :ostatus
3403 FROM users
3404 WHERE uid = :uid AND (status=0 OR status=5 OR status=6);
3405
3406 if (sqlca.sqlerrd[2] == 0)
3407 return(MR_NO_MATCH);
3408 if (sqlca.sqlerrd[2] > 1)
3409 return(MR_NOT_UNIQUE);
3410
3411 /* check new login name */
3412 EXEC SQL REPEATED SELECT COUNT(login) INTO :rowcount FROM users
3413 WHERE login = :login AND users_id != :users_id;
3414 if (ingres_errno) return(mr_errcode);
3415 if (rowcount > 0) return(MR_IN_USE);
3416 EXEC SQL REPEATED SELECT COUNT(name) INTO :rowcount FROM list
3417 WHERE name = :login;
3418 if (ingres_errno) return(mr_errcode);
3419 if (rowcount > 0) return(MR_IN_USE);
3420 EXEC SQL REPEATED SELECT COUNT(label) INTO :rowcount FROM filesys
3421 WHERE label = :login;
3422 if (ingres_errno) return(mr_errcode);
3423 if (rowcount > 0) return(MR_IN_USE);
3424 com_err(whoami, 0, "login name OK");
3425
3426 /* choose place for pobox, put in mid */
3427 EXEC SQL DECLARE csr130 CURSOR FOR
3428 SELECT sh.mach_id, m.name FROM serverhosts sh, machine m
3429 WHERE sh.service='POP' AND sh.mach_id=m.mach_id
3430 AND sh.value2 - sh.value1 =
3431 (SELECT MAX(value2 - value1) FROM serverhosts
3432 WHERE service = 'POP');
3433 if (ingres_errno)
3434 return(mr_errcode);
3435 EXEC SQL OPEN csr130;
3436 if (ingres_errno)
3437 return(mr_errcode);
3438 EXEC SQL FETCH csr130 INTO :mid, :machname;
3439 if (sqlca.sqlerrd[2] == 0) {
3440 EXEC SQL CLOSE csr130;
3441 if (ingres_errno) return(mr_errcode);
3442 return(MR_NO_POBOX);
3443 } else {
3444 EXEC SQL CLOSE csr130;
3445 if (ingres_errno) return(mr_errcode);
3446 }
3447
3448 /* change login name, set pobox */
3449 sprintf(buffer, "u.users_id = %d", users_id);
3450 incremental_before("users", buffer, 0);
3451 nstatus = 2;
3452 if (ostatus == 5 || ostatus == 6)
3453 nstatus = 1;
3454 EXEC SQL REPEATED UPDATE users SET login = :login, status = :nstatus,
3455 modtime='now', modby = :who, modwith = :entity, potype='POP',
3456 pop_id = :mid, pmodtime='now', pmodby = :who, pmodwith = :entity
3457 WHERE users_id = :users_id;
3458
3459 if (ingres_errno) return(mr_errcode);
3460 if (sqlca.sqlerrd[2] != 1)
3461 return(MR_INTERNAL);
3462 set_pop_usage(mid, 1);
3463 com_err(whoami, 0, "set login name to %s and pobox to %s", login,
3464 strtrim(machname));
3465 incremental_after("users", buffer, 0);
3466
3467 /* create group list */
3468 if (set_next_object_id("gid", "list", 1))
3469 return(MR_NO_ID);
3470 if (set_next_object_id("list_id", "list", 0))
3471 return(MR_NO_ID);
3472 EXEC SQL REPEATED SELECT value INTO :list_id FROM numvalues
3473 WHERE name='list_id';
3474 if (ingres_errno) return(mr_errcode);
3475 if (sqlca.sqlerrd[2] != 1)
3476 return(MR_INTERNAL);
3477 incremental_clear_before();
3478 EXEC SQL SELECT value INTO :gidval FROM numvalues WHERE name = 'gid';
3479 EXEC SQL REPEATED INSERT INTO list
3480 (name, list_id, active, publicflg, hidden, maillist, grouplist,
3481 gid, description, acl_type, acl_id,
3482 modtime, modby, modwith)
3483 VALUES (:login, :list_id, 1, 0, 0, 0, 1,
3484 :gidval, 'User Group', 'USER', :users_id,
3485 'now', :who, :entity);
3486 if (ingres_errno) return(mr_errcode);
3487 if (sqlca.sqlerrd[2] != 1)
3488 return(MR_INTERNAL);
3489 sprintf(buffer, "l.list_id = %d", list_id);
3490 incremental_after("list", buffer, 0);
3491 aargv[0] = (char *) list_id;
3492 aargv[1] = "USER";
3493 aargv[2] = (char *) users_id;
3494 incremental_clear_before();
3495 EXEC SQL REPEATED INSERT INTO imembers
3496 (list_id, member_type, member_id, ref_count, direct)
3497 VALUES (:list_id, 'USER', :users_id, 1, 1);
3498 if (ingres_errno) return(mr_errcode);
3499 if (sqlca.sqlerrd[2] != 1)
3500 return(MR_INTERNAL);
3501 incremental_after("members", 0, aargv);
3502
3503 if (m_id == 0) {
3504 /* Cell Name (I know, it shouldn't be hard coded...) */
3505 strcpy(machname, "ATHENA.MIT.EDU");
3506 EXEC SQL SELECT mach_id INTO :m_id FROM machine
3507 WHERE name = :machname;
3508 }
3509
3510 /* create filesystem */
3511 if (set_next_object_id("filsys_id", "filesys", 0))
3512 return(MR_NO_ID);
3513 incremental_clear_before();
3514 if (islower(login[0]) && islower(login[1])) {
3515 sprintf(directory, "/afs/athena.mit.edu/user/%c/%c/%s",
3516 login[0], login[1], login);
3517 } else {
3518 sprintf(directory, "/afs/athena.mit.edu/user/other/%s", login);
3519 }
3520
3521 EXEC SQL SELECT value INTO :fsidval FROM numvalues
3522 WHERE numvalues.name='filsys_id';
3523 EXEC SQL REPEATED INSERT INTO filesys
3524 (filsys_id, phys_id, label, type, mach_id, name,
3525 mount, access, comments, owner, owners, createflg,
3526 lockertype, modtime, modby, modwith)
3527 VALUES
3528 (:fsidval, 0, :login, 'AFS', :m_id, :directory,
3529 '/mit/'+:login, 'w', 'User Locker', :users_id, :list_id, 1,
3530 'HOMEDIR', 'now', :who, :entity);
3531
3532 if (ingres_errno) return(mr_errcode);
3533 if (sqlca.sqlerrd[2] != 1)
3534 return(MR_INTERNAL);
3535 sprintf(buffer,"fs.filsys_id = %d",fsidval);
3536 incremental_after("filesys", buffer, 0);
3537
3538 /* set quota */
3539 if (def_quota == 0) {
3540 EXEC SQL REPEATED SELECT value INTO :def_quota FROM numvalues
3541 WHERE name='def_quota';
3542 if (ingres_errno) return(mr_errcode);
3543 if (sqlca.sqlerrd[2] != 1)
3544 return(MR_NO_QUOTA);
3545
3546 }
3547 incremental_clear_before();
3548 EXEC SQL REPEATED INSERT INTO quota
3549 (entity_id, filsys_id, type, quota, phys_id, modtime, modby, modwith)
3550 VALUES
3551 (0, :fsidval, 'ANY', :def_quota, 0, 'now', :who, :entity);
3552 if (ingres_errno) return(mr_errcode);
3553 if (sqlca.sqlerrd[2] != 1)
3554 return(MR_INTERNAL);
3555 aargv[0] = login;
3556 aargv[1] = "ANY";
3557 aargv[2] = login;
3558 sprintf(buffer, "q.entity_id = 0 and q.filsys_id = %d and q.type = 'ANY'", fsidval);
3559 incremental_after("quota", buffer, aargv);
3560 com_err(whoami, 0, "quota of %d assigned", def_quota);
3561 if (ingres_errno) return(mr_errcode);
3562
3563 cache_entry(login, "USER", users_id);
3564
3565 EXEC SQL REPEATED UPDATE tblstats SET updates=updates+1, modtime='now'
3566 WHERE table_name='users';
3567 EXEC SQL REPEATED UPDATE tblstats SET appends=appends+1, modtime='now'
3568 WHERE table_name='list' OR table_name='filesys' OR table_name='quota';
3569 if (ingres_errno) return(mr_errcode);
3570 return(MR_SUCCESS);
3571}
3572
3573
3574
3575/** set_pop_usage - incr/decr usage count for pop server in serverhosts talbe
3576 **
3577 ** Inputs:
3578 ** id of machine
3579 ** delta (will be +/- 1)
3580 **
3581 ** Description:
3582 ** - incr/decr value field in serverhosts table for pop/mach_id
3583 **
3584 **/
3585
3586static int set_pop_usage(id, cnt)
3587 EXEC SQL BEGIN DECLARE SECTION;
3588 int id;
3589 int cnt;
3590 EXEC SQL END DECLARE SECTION;
3591{
3592 EXEC SQL REPEATED UPDATE serverhosts SET value1 = value1 + :cnt
3593 WHERE serverhosts.service = 'POP' AND serverhosts.mach_id = :id;
3594
3595 if (ingres_errno) return(mr_errcode);
3596 return(MR_SUCCESS);
3597}
3598
3599int _sdl_followup(q, argv, cl)
3600 struct query *q;
3601 char **argv;
3602 client *cl;
3603{
3604 int i;
3605 i = atoi(argv[0]);
3606 log_flags = i;
3607 if (i & LOG_SQL) {
3608 EXEC SQL set printqry;
3609 } else {
3610 EXEC SQL set noprintqry;
3611 }
3612 return(MR_SUCCESS);
3613}
3614
3615
3616\f
3617/* Validation Routines */
3618
3619validate_row(q, argv, v)
3620 register struct query *q;
3621 char *argv[];
3622 register struct validate *v;
3623{
3624 EXEC SQL BEGIN DECLARE SECTION;
3625 char *name;
3626 char qual[128];
3627 int rowcount;
3628 EXEC SQL END DECLARE SECTION;
3629
3630 /* build where clause */
3631 build_qual(v->qual, v->argc, argv, qual);
3632
3633 if (log_flags & LOG_VALID)
3634 /* tell the logfile what we're doing */
3635 com_err(whoami, 0, "validating row: %s", qual);
3636
3637 /* look for the record */
3638 sprintf(stmt_buf,"SELECT COUNT (*) FROM %s WHERE %s",q->rtable,qual);
3639 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3640 if(sqlca.sqlcode)
3641 return(MR_INTERNAL);
3642 EXEC SQL DECLARE csr126 CURSOR FOR stmt;
3643 EXEC SQL OPEN csr126;
3644 EXEC SQL FETCH csr126 USING DESCRIPTOR :SQLDA;
3645 EXEC SQL CLOSE csr126;
3646 rowcount = *(int *)SQLDA->sqlvar[0].sqldata;
3647
3648 if (ingres_errno) return(mr_errcode);
3649 if (rowcount == 0) return(MR_NO_MATCH);
3650 if (rowcount > 1) return(MR_NOT_UNIQUE);
3651 return(MR_EXISTS);
3652}
3653
3654validate_fields(q, argv, vo, n)
3655 struct query *q;
3656 register char *argv[];
3657 register struct valobj *vo;
3658 register int n;
3659{
3660 register int status;
3661
3662 while (--n >= 0) {
3663 switch (vo->type) {
3664 case V_NAME:
3665 if (log_flags & LOG_VALID)
3666 com_err(whoami, 0, "validating %s in %s: %s",
3667 vo->namefield, vo->table, argv[vo->index]);
3668 status = validate_name(argv, vo);
3669 break;
3670
3671 case V_ID:
3672 if (log_flags & LOG_VALID)
3673 com_err(whoami, 0, "validating %s in %s: %s",
3674 vo->idfield, vo->table, argv[vo->index]);
3675 status = validate_id(q, argv, vo);
3676 break;
3677
3678 case V_DATE:
3679 if (log_flags & LOG_VALID)
3680 com_err(whoami, 0, "validating date: %s", argv[vo->index]);
3681 status = validate_date(argv, vo);
3682 break;
3683
3684 case V_TYPE:
3685 if (log_flags & LOG_VALID)
3686 com_err(whoami, 0, "validating %s type: %s",
3687 vo->table, argv[vo->index]);
3688 status = validate_type(argv, vo);
3689 break;
3690
3691 case V_TYPEDATA:
3692 if (log_flags & LOG_VALID)
3693 com_err(whoami, 0, "validating typed data (%s): %s",
3694 argv[vo->index - 1], argv[vo->index]);
3695 status = validate_typedata(q, argv, vo);
3696 break;
3697
3698 case V_RENAME:
3699 if (log_flags & LOG_VALID)
3700 com_err(whoami, 0, "validating rename %s in %s",
3701 argv[vo->index], vo->table);
3702 status = validate_rename(argv, vo);
3703 break;
3704
3705 case V_CHAR:
3706 if (log_flags & LOG_VALID)
3707 com_err(whoami, 0, "validating chars: %s", argv[vo->index]);
3708 status = validate_chars(argv[vo->index]);
3709 break;
3710
3711 case V_SORT:
3712 status = MR_EXISTS;
3713 break;
3714
3715 case V_LOCK:
3716 status = lock_table(vo);
3717 break;
3718
3719 case V_WILD:
3720 status = convert_wildcards(argv[vo->index]);
3721 break;
3722
3723 case V_UPWILD:
3724 status = convert_wildcards_uppercase(argv[vo->index]);
3725 break;
3726
3727 }
3728
3729 if (status != MR_EXISTS) return(status);
3730 vo++;
3731 }
3732
3733 if (ingres_errno) return(mr_errcode);
3734 return(MR_SUCCESS);
3735}
3736
3737
3738/* validate_chars: verify that there are no illegal characters in
3739 * the string. Legal characters are printing chars other than
3740 * ", *, ?, \, [ and ].
3741 */
3742static int illegalchars[] = {
3743 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
3744 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
3745 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
3746 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
3747 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* : - O */
3748 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* P - _ */
3749 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
3750 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
3751 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3752 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3753 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3754 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3755 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3756 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3757 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3758 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3759};
3760
3761validate_chars(s)
3762register char *s;
3763{
3764 while (*s)
3765 if (illegalchars[*s++])
3766 return(MR_BAD_CHAR);
3767 return(MR_EXISTS);
3768}
3769
3770
3771validate_id(q, argv, vo)
3772 struct query *q;
3773 char *argv[];
3774 register struct valobj *vo;
3775{
3776 EXEC SQL BEGIN DECLARE SECTION;
3777 char *name, *tbl, *namefield, *idfield;
3778 int id, rowcount;
3779 EXEC SQL END DECLARE SECTION;
3780 int status;
3781 register char *c;
3782
3783 name = argv[vo->index];
3784 tbl = vo->table;
3785 namefield = vo->namefield;
3786 idfield = vo->idfield;
3787
3788 if ((!strcmp(tbl, "users") && !strcmp(namefield, "login")) ||
3789 !strcmp(tbl, "machine") ||
3790 !strcmp(tbl, "filesys") ||
3791 !strcmp(tbl, "list") ||
3792 !strcmp(tbl, "cluster") ||
3793 !strcmp(tbl, "strings")) {
3794 if (!strcmp(tbl, "machine"))
3795 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3796 status = name_to_id(name, tbl, &id);
3797 if (status == 0) {
3798 *(int *)argv[vo->index] = id;
3799 return(MR_EXISTS);
3800 } else if (status == MR_NO_MATCH && !strcmp(tbl, "strings") &&
3801 (q->type == APPEND || q->type == UPDATE)) {
3802 id=add_string(name);
3803 cache_entry(name, "STRING", id);
3804 *(int *)argv[vo->index] = id;
3805 return(MR_EXISTS);
3806 } else if (status == MR_NO_MATCH || status == MR_NOT_UNIQUE)
3807 return(vo->error);
3808 else
3809 return(status);
3810 }
3811
3812 if (!strcmp(namefield, "uid")) {
3813 sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s = %s",idfield,tbl,namefield,name);
3814 } else {
3815 sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s = '%s'",idfield,tbl,namefield,name);
3816 }
3817 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3818 if(sqlca.sqlcode)
3819 return(MR_INTERNAL);
3820 EXEC SQL DECLARE csr127 CURSOR FOR stmt;
3821 EXEC SQL OPEN csr127;
3822 rowcount=0;
3823 EXEC SQL FETCH csr127 USING DESCRIPTOR :SQLDA;
3824 if(sqlca.sqlcode == 0) {
3825 rowcount++;
3826 EXEC SQL FETCH csr127 USING DESCRIPTOR :SQLDA;
3827 if(sqlca.sqlcode == 0) rowcount++;
3828 }
3829 EXEC SQL CLOSE csr127;
3830 if (ingres_errno)
3831 return(mr_errcode);
3832
3833 if (rowcount != 1) return(vo->error);
3834 bcopy(SQLDA->sqlvar[0].sqldata,argv[vo->index],sizeof(int));
3835 return(MR_EXISTS);
3836}
3837
3838validate_name(argv, vo)
3839 char *argv[];
3840 register struct valobj *vo;
3841{
3842 EXEC SQL BEGIN DECLARE SECTION;
3843 char *name, *tbl, *namefield;
3844 int rowcount;
3845 EXEC SQL END DECLARE SECTION;
3846 register char *c;
3847
3848 name = argv[vo->index];
3849 tbl = vo->table;
3850 namefield = vo->namefield;
3851 if (!strcmp(tbl, "servers") && !strcmp(namefield, "name")) {
3852 for (c = name; *c; c++)
3853 if (islower(*c))
3854 *c = toupper(*c);
3855 }
3856 sprintf(stmt_buf,"SELECT DISTINCT COUNT(*) FROM %s WHERE %s.%s = '%s'",
3857 tbl,tbl,namefield,name);
3858 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3859 if(sqlca.sqlcode)
3860 return(MR_INTERNAL);
3861 EXEC SQL DECLARE csr128 CURSOR FOR stmt;
3862 EXEC SQL OPEN csr128;
3863 EXEC SQL FETCH csr128 USING DESCRIPTOR :SQLDA;
3864 rowcount = *(int *)SQLDA->sqlvar[0].sqldata;
3865 EXEC SQL CLOSE csr128;
3866
3867 if (ingres_errno) return(mr_errcode);
3868 return ((rowcount == 1) ? MR_EXISTS : vo->error);
3869}
3870
3871validate_date(argv, vo)
3872 char *argv[];
3873 struct valobj *vo;
3874{
3875 EXEC SQL BEGIN DECLARE SECTION;
3876 char *idate;
3877 double dd;
3878 int errorno;
3879 EXEC SQL END DECLARE SECTION;
3880
3881 idate = argv[vo->index];
3882 EXEC SQL SELECT interval('years',date(:idate)-date('today')) INTO :dd;
3883
3884 if (sqlca.sqlcode != 0 || dd > 5.0) return(MR_DATE);
3885 return(MR_EXISTS);
3886}
3887
3888
3889validate_rename(argv, vo)
3890char *argv[];
3891struct valobj *vo;
3892{
3893 EXEC SQL BEGIN DECLARE SECTION;
3894 char *name, *tbl, *namefield, *idfield;
3895 int id;
3896 EXEC SQL END DECLARE SECTION;
3897 int status;
3898 register char *c;
3899
3900 c = name = argv[vo->index];
3901 while (*c)
3902 if (illegalchars[*c++])
3903 return(MR_BAD_CHAR);
3904 tbl = vo->table;
3905 /* minor kludge to upcasify machine names */
3906 if (!strcmp(tbl, "machine"))
3907 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
3908 namefield = vo->namefield;
3909 idfield = vo->idfield;
3910 id = -1;
3911 if (idfield == 0) {
3912 if (!strcmp(argv[vo->index], argv[vo->index - 1]))
3913 return(MR_EXISTS);
3914 sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s = LEFT('%s',SIZE(%s))",
3915 namefield,tbl,namefield,name,namefield);
3916 EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf;
3917 if(sqlca.sqlcode)
3918 return(MR_INTERNAL);
3919 EXEC SQL DECLARE csr129 CURSOR FOR stmt;
3920 EXEC SQL OPEN csr129;
3921 EXEC SQL FETCH csr129 USING DESCRIPTOR :SQLDA;
3922 if(sqlca.sqlcode == 0) id=1; else id=0;
3923 EXEC SQL CLOSE csr129;
3924
3925 if (ingres_errno) return(mr_errcode);
3926 if (id)
3927 return(vo->error);
3928 else
3929 return(MR_EXISTS);
3930 }
3931 status = name_to_id(name, tbl, &id);
3932 if (status == MR_NO_MATCH || id == *(int *)argv[vo->index - 1])
3933 return(MR_EXISTS);
3934 else
3935 return(vo->error);
3936}
3937
3938
3939validate_type(argv, vo)
3940 char *argv[];
3941 register struct valobj *vo;
3942{
3943 EXEC SQL BEGIN DECLARE SECTION;
3944 char *typename;
3945 char *val;
3946 int cnt;
3947 EXEC SQL END DECLARE SECTION;
3948 register char *c;
3949
3950 typename = vo->table;
3951 c = val = argv[vo->index];
3952 while (*c) {
3953 if (illegalchars[*c++])
3954 return(MR_BAD_CHAR);
3955 }
3956
3957 /* uppercase type fields */
3958 for (c = val; *c; c++) if (islower(*c)) *c = toupper(*c);
3959
3960 EXEC SQL SELECT COUNT(trans) INTO :cnt FROM alias
3961 WHERE name = :typename AND type='TYPE' AND trans = :val;
3962 if (ingres_errno) return(mr_errcode);
3963 return (cnt ? MR_EXISTS : vo->error);
3964}
3965
3966/* validate member or type-specific data field */
3967
3968validate_typedata(q, argv, vo)
3969 register struct query *q;
3970 register char *argv[];
3971 register struct valobj *vo;
3972{
3973 EXEC SQL BEGIN DECLARE SECTION;
3974 char *name;
3975 char *field_type;
3976 char data_type[129];
3977 int id;
3978 EXEC SQL END DECLARE SECTION;
3979 int status;
3980 char *index();
3981 register char *c;
3982
3983 /* get named object */
3984 name = argv[vo->index];
3985
3986 /* get field type string (known to be at index-1) */
3987 field_type = argv[vo->index-1];
3988
3989 /* get corresponding data type associated with field type name */
3990 EXEC SQL SELECT trans INTO :data_type FROM alias
3991 WHERE name = :field_type AND type='TYPEDATA';
3992 if (ingres_errno) return(mr_errcode);
3993 if (sqlca.sqlerrd[2] != 1) return(MR_TYPE);
3994
3995 /* now retrieve the record id corresponding to the named object */
3996 if (index(data_type, ' '))
3997 *index(data_type, ' ') = 0;
3998 if (!strcmp(data_type, "user")) {
3999 /* USER */
4000 if (index(name, '@'))
4001 return(MR_USER);
4002 status = name_to_id(name, data_type, &id);
4003 if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
4004 return(MR_USER);
4005 if (status) return(status);
4006 } else if (!strcmp(data_type, "list")) {
4007 /* LIST */
4008 status = name_to_id(name, data_type, &id);
4009 if (status && status == MR_NOT_UNIQUE)
4010 return(MR_LIST);
4011 if (status == MR_NO_MATCH) {
4012 /* if idfield is non-zero, then if argv[0] matches the string
4013 * that we're trying to resolve, we should get the value of
4014 * numvalues.[idfield] for the id.
4015 */
4016 if (vo->idfield && !strcmp(argv[0], argv[vo->index])) {
4017 set_next_object_id(q->validate->object_id, q->rtable, 0);
4018 name = vo->idfield;
4019 EXEC SQL REPEATED SELECT value INTO :id FROM numvalues
4020 WHERE name = :name;
4021 if (sqlca.sqlerrd[2] != 1) return(MR_LIST);
4022 } else
4023 return(MR_LIST);
4024 } else if (status) return(status);
4025 } else if (!strcmp(data_type, "machine")) {
4026 /* MACHINE */
4027 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
4028 status = name_to_id(name, data_type, &id);
4029 if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
4030 return(MR_MACHINE);
4031 if (status) return(status);
4032 } else if (!strcmp(data_type, "string")) {
4033 /* STRING */
4034 status = name_to_id(name, data_type, &id);
4035 if (status && status == MR_NOT_UNIQUE)
4036 return(MR_STRING);
4037 if (status == MR_NO_MATCH) {
4038 if (q->type != APPEND && q->type != UPDATE) return(MR_STRING);
4039 id=add_string(name);
4040 cache_entry(name, "STRING", id);
4041 } else if (status) return(status);
4042 } else if (!strcmp(data_type, "none")) {
4043 id = 0;
4044 } else {
4045 return(MR_TYPE);
4046 }
4047
4048 /* now set value in argv */
4049 *(int *)argv[vo->index] = id;
4050
4051 return (MR_EXISTS);
4052}
4053
4054
4055/* Lock the table named by the validation object */
4056
4057lock_table(vo)
4058struct valobj *vo;
4059{
4060 sprintf(stmt_buf,"UPDATE %s SET modtime='now' WHERE %s.%s = 0",
4061 vo->table,vo->table,vo->idfield);
4062 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
4063 if (ingres_errno) return(mr_errcode);
4064 if (sqlca.sqlerrd[2] != 1)
4065 return(vo->error);
4066 else
4067 return(MR_EXISTS);
4068}
4069
4070
4071/* Check the database at startup time. For now this just resets the
4072 * inprogress flags that the DCM uses.
4073 */
4074
4075sanity_check_database()
4076{
4077}
4078
4079
4080/* Dynamic SQL support routines */
4081MR_SQLDA_T *mr_alloc_SQLDA()
4082{
4083 MR_SQLDA_T *it;
4084 short *null_indicators;
4085 register int j;
4086
4087 if((it=(MR_SQLDA_T *)malloc(sizeof(MR_SQLDA_T)))==NULL) {
4088 com_err(whoami, MR_NO_MEM, "setting up SQLDA");
4089 exit(1);
4090 }
4091
4092 if((null_indicators=(short *)calloc(QMAXARGS,sizeof(short)))==NULL) {
4093 com_err(whoami, MR_NO_MEM, "setting up SQLDA null indicators");
4094 exit(1);
4095 }
4096
4097 for(j=0; j<QMAXARGS; j++) {
4098 if((it->sqlvar[j].sqldata=malloc(sizeof(short)+ARGLEN))==NULL) {
4099 com_err(whoami, MR_NO_MEM, "setting up SQLDA variables");
4100 exit(1);
4101 }
4102 it->sqlvar[j].sqllen=ARGLEN;
4103 it->sqlvar[j].sqlind=null_indicators+j;
4104 null_indicators[j]=0;
4105 }
4106 it->sqln=QMAXARGS;
4107 return it;
4108}
4109
4110
4111/* Use this after FETCH USING DESCRIPTOR one or more
4112 * result columns may contain NULLs. This routine is
4113 * not currently needed, since db/schema creates all
4114 * columns with a NOT NULL WITH DEFAULT clause.
4115 *
4116 * This is currently dead flesh, since no Moira columns
4117 * allow null values; all use default values.
4118 */
4119mr_fix_nulls_in_SQLDA(da)
4120 MR_SQLDA_T *da;
4121{
4122 register IISQLVAR *var;
4123 register int j;
4124 int *intp;
4125
4126 for(j=0, var=da->sqlvar; j<da->sqld; j++, var++) {
4127 switch(var->sqltype) {
4128 case -IISQ_CHA_TYPE:
4129 if(*var->sqlind)
4130 *var->sqldata='\0';
4131 break;
4132 case -IISQ_INT_TYPE:
4133 if(*var->sqlind) {
4134 intp=(int *)var->sqldata;
4135 *intp=0;
4136 }
4137 break;
4138 }
4139 }
4140}
4141
4142/* prefetch_value():
4143 * This routine fetches an appropriate value from the numvalues table.
4144 * It is a little hack to get around the fact that SQL doesn't let you
4145 * do something like INSERT INTO table (foo) VALUES (other_table.bar).
4146 *
4147 * It is called from the query table as (*v->pre_rtn)(q,Argv,cl) or
4148 * from within a setup_...() routine with the appropriate arguments.
4149 *
4150 * Correct functioning of this routine may depend on the assumption
4151 * that this query is an APPEND.
4152 */
4153
4154prefetch_value(q,argv,cl)
4155 struct query *q;
4156 char **argv;
4157 client *cl;
4158{
4159 EXEC SQL BEGIN DECLARE SECTION;
4160 char *name = q->validate->object_id;
4161 int value;
4162 EXEC SQL END DECLARE SECTION;
4163 int status, limit, argc;
4164
4165 /* set next object id, limiting it if necessary */
4166 if(!strcmp(name, "uid") || !strcmp(name, "gid"))
4167 limit = 1; /* So far as I know, this isn't needed. Just CMA. */
4168 else
4169 limit = 0;
4170 if((status = set_next_object_id(name, q->rtable, limit)) != MR_SUCCESS)
4171 return(status);
4172
4173 /* fetch object id */
4174 EXEC SQL SELECT value INTO :value FROM numvalues WHERE name=:name;
4175 if(ingres_errno) return(mr_errcode);
4176 if(sqlca.sqlerrd[2] != 1) return(MR_INTERNAL);
4177
4178 argc = q->argc + q->vcnt; /* end of Argv for APPENDs */
4179 sprintf(argv[argc],"%d",value); /** Could save this step by changing tlist from %s to %d **/
4180
4181 return(MR_SUCCESS);
4182}
4183
4184/* prefetch_filesys():
4185 * Fetches the phys_id from filesys based on the filsys_id in argv[0].
4186 * Appends the filsys_id and the phys_id to the argv so they can be
4187 * referenced in an INSERT into a table other than filesys. Also
4188 * see comments at prefetch_value().
4189 *
4190 * Assumes the existence of a row where filsys_id = argv[0], since a
4191 * filesys label has already been resolved to a filsys_id.
4192 */
4193prefetch_filesys(q,argv,cl)
4194 struct query *q;
4195 char **argv;
4196 client *cl;
4197{
4198 EXEC SQL BEGIN DECLARE SECTION;
4199 int fid,phid;
4200 EXEC SQL END DECLARE SECTION;
4201 int argc;
4202
4203 fid = *(int *)argv[0];
4204 EXEC SQL SELECT phys_id INTO :phid FROM filesys WHERE filsys_id = :fid;
4205 if(ingres_errno) return(mr_errcode);
4206
4207 argc=q->argc+q->vcnt;
4208 sprintf(argv[argc++],"%d",phid);
4209 sprintf(argv[argc],"%d",fid);
4210
4211 return(MR_SUCCESS);
4212}
4213
4214/* Convert normal Unix-style wildcards to SQL voodoo */
4215convert_wildcards(arg)
4216 char *arg;
4217{
4218 static char buffer[ARGLEN];
4219 register char *s, *d;
4220
4221 for(d=buffer,s=arg;*s;s++) {
4222 switch(*s) {
4223 case '*': *d++='%'; *d++='%'; break;
4224 case '?': *d++='_'; break;
4225 case '_':
4226 case '[':
4227 case ']': *d++='*'; *d++ = *s; break;
4228 case '%': *d++='*'; *d++='%'; *d++='%'; break;
4229 default: *d++ = *s; break;
4230 }
4231 }
4232 *d='\0';
4233
4234 /* Copy back into argv */
4235 strcpy(arg,buffer);
4236
4237 return(MR_EXISTS);
4238}
4239
4240/* This version includes uppercase conversion, for things like gmac.
4241 * This is necessary because "LIKE" doesn't work with "uppercase()".
4242 * Including it in a wildcard routine saves making two passes over
4243 * the argument string.
4244 */
4245convert_wildcards_uppercase(arg)
4246 char *arg;
4247{
4248 static char buffer[ARGLEN];
4249 register char *s, *d;
4250
4251 for(d=buffer,s=arg;*s;s++) {
4252 switch(*s) {
4253 case '*': *d++='%'; *d++='%'; break;
4254 case '?': *d++='_'; break;
4255 case '_':
4256 case '[':
4257 case ']': *d++='*'; *d++ = *s; break;
4258 case '%': *d++='*'; *d++='%'; *d++='%'; break;
4259 default: *d++=toupper(*s); break; /* This is the only diff. */
4260 }
4261 }
4262 *d='\0';
4263
4264 /* Copy back into argv */
4265 strcpy(arg,buffer);
4266
4267 return(MR_EXISTS);
4268}
4269
4270
4271/* Looks like it's time to build an abstraction barrier, Yogi */
4272mr_select_any(stmt)
4273 EXEC SQL BEGIN DECLARE SECTION;
4274 char *stmt;
4275 EXEC SQL END DECLARE SECTION;
4276{
4277 int result=0;
4278
4279 EXEC SQL PREPARE stmt FROM :stmt;
4280 EXEC SQL DESCRIBE stmt INTO :SQLDA;
4281 if(SQLDA->sqld==0) /* Not a SELECT */
4282 return(MR_INTERNAL);
4283 EXEC SQL DECLARE csr CURSOR FOR stmt;
4284 EXEC SQL OPEN csr;
4285 EXEC SQL FETCH csr USING DESCRIPTOR :SQLDA;
4286 if(sqlca.sqlcode==0)
4287 result=MR_EXISTS;
4288 else if((sqlca.sqlcode<0) && mr_errcode)
4289 result=mr_errcode;
4290 else
4291 result=0;
4292 EXEC SQL CLOSE csr;
4293 return(result);
4294}
4295
4296
4297
4298static hex_dump(p)
4299unsigned char *p;
4300{
4301 char buf[BUFSIZ];
4302 int i;
4303
4304 fprintf(stderr, "Size: %d\n", strlen(p));
4305 while (strlen(p) >= 8) {
4306 fprintf(stderr, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
4307 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
4308 p += 8;
4309 }
4310 switch (strlen(p)) {
4311 case 7:
4312 fprintf(stderr, "%02x %02x %02x %02x %02x %02x %02x\n",
4313 p[0], p[1], p[2], p[3], p[4], p[5], p[6]);
4314 break;
4315 case 6:
4316 fprintf(stderr, "%02x %02x %02x %02x %02x %02x\n",
4317 p[0], p[1], p[2], p[3], p[4], p[5]);
4318 break;
4319 case 5:
4320 fprintf(stderr, "%02x %02x %02x %02x %02x\n",
4321 p[0], p[1], p[2], p[3], p[4]);
4322 break;
4323 case 4:
4324 fprintf(stderr, "%02x %02x %02x %02x\n",
4325 p[0], p[1], p[2], p[3]);
4326 break;
4327 case 3:
4328 fprintf(stderr, "%02x %02x %02x\n",
4329 p[0], p[1], p[2]);
4330 break;
4331 case 2:
4332 fprintf(stderr, "%02x %02x\n",
4333 p[0], p[1]);
4334 break;
4335 case 1:
4336 fprintf(stderr, "%02x\n",
4337 p[0]);
4338 break;
4339 default:
4340 return;
4341 }
4342}
4343
4344
4345
4346/* Adds a string to the string table. Returns the id number.
4347 *
4348 */
4349int add_string(name)
4350 EXEC SQL BEGIN DECLARE SECTION;
4351 char *name;
4352 EXEC SQL END DECLARE SECTION;
4353{
4354 EXEC SQL BEGIN DECLARE SECTION;
4355 char buf[256];
4356 int id;
4357 EXEC SQL END DECLARE SECTION;
4358
4359 EXEC SQL SELECT value INTO :id FROM numvalues WHERE name = 'strings_id';
4360 id++;
4361 EXEC SQL UPDATE numvalues SET value = :id WHERE name = 'strings_id';
4362
4363 /* Use sprintf to get around problem with doubled single quotes */
4364 sprintf(buf,"INSERT INTO strings (string_id, string) VALUES (%d, '%s')",id,name);
4365 EXEC SQL EXECUTE IMMEDIATE :buf;
4366
4367 return(id);
4368}
4369
4370
4371/* eof:qsupport.dc */
This page took 3.482233 seconds and 5 git commands to generate.