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