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