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