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