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