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