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