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