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