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