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