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