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