]>
Commit | Line | Data |
---|---|---|
d26cae4e | 1 | /* |
2 | * $Source$ | |
3 | * $Author$ | |
4 | * $Header$ | |
5 | * | |
83526631 | 6 | * Copyright (C) 1987, 1988 by the Massachusetts Institute of Technology |
7ee33a8d | 7 | * For copying and distribution information, please see the file |
8 | * <mit-copyright.h>. | |
faad6f39 | 9 | * |
d26cae4e | 10 | */ |
11 | ||
12 | #ifndef lint | |
13 | static char *rcsid_qrtn_qc = "$Header$"; | |
14 | #endif lint | |
15 | ||
7ee33a8d | 16 | #include <mit-copyright.h> |
97479f6f | 17 | #include "query.h" |
d548a4e7 | 18 | #include "mr_server.h" |
97479f6f | 19 | |
20 | char *Argv[16]; | |
21 | ||
ca7c2f3d | 22 | int ingres_errno = 0; |
d548a4e7 | 23 | int mr_errcode = 0; |
ca7c2f3d | 24 | ## int query_timeout = 30; |
7536027d | 25 | extern char *whoami; |
83526631 | 26 | extern FILE *journal; |
97479f6f | 27 | |
8fcb440e | 28 | #define INGRES_BAD_INT 4111 |
29 | #define INGRES_BAD_DATE 4302 | |
4a7b7001 | 30 | #define INGRES_DEADLOCK 4700 |
ca7c2f3d | 31 | #define INGRES_TIMEOUT 4702 |
a5701583 | 32 | #define INGRES_NO_RANGE 2109 |
8fcb440e | 33 | |
d26cae4e | 34 | /* |
35 | * ingerr: (supposedly) called when Ingres indicates an error. | |
36 | * I have not yet been able to get this to work to intercept a | |
37 | * database open error. | |
38 | */ | |
39 | ||
40 | static int ingerr(num) | |
41 | int *num; | |
97479f6f | 42 | { |
ca7c2f3d | 43 | ingres_errno = *num; |
8fcb440e | 44 | |
45 | switch (*num) { | |
46 | case INGRES_BAD_INT: | |
d548a4e7 | 47 | mr_errcode = MR_INTEGER; |
8fcb440e | 48 | break; |
49 | case INGRES_BAD_DATE: | |
d548a4e7 | 50 | mr_errcode = MR_DATE; |
8fcb440e | 51 | break; |
4a7b7001 | 52 | case INGRES_DEADLOCK: |
d548a4e7 | 53 | mr_errcode = MR_DEADLOCK; |
7ee33a8d | 54 | com_err(whoami, 0, "INGRES deadlock detected"); |
ca7c2f3d | 55 | break; |
56 | case INGRES_TIMEOUT: | |
d548a4e7 | 57 | mr_errcode = MR_BUSY; |
ca7c2f3d | 58 | com_err(whoami, 0, "timed out getting lock"); |
4a7b7001 | 59 | break; |
a5701583 | 60 | case INGRES_NO_RANGE: |
61 | mr_errcode = MR_INGRES_SOFTFAIL; | |
62 | com_err(whoami, 0, "INGRES missing range statement"); | |
63 | break; | |
8fcb440e | 64 | default: |
d548a4e7 | 65 | mr_errcode = MR_INGRES_ERR; |
66 | com_err(whoami, MR_INGRES_ERR, " code %d\n", *num); | |
67 | critical_alert("MOIRA", "Moira server encountered INGRES ERROR %d", *num); | |
8fcb440e | 68 | return (*num); |
69 | } | |
70 | return (0); | |
97479f6f | 71 | } |
72 | ||
d548a4e7 | 73 | int mr_open_database() |
97479f6f | 74 | { |
d26cae4e | 75 | register int i; |
83526631 | 76 | char *malloc(); |
73c902bf | 77 | static first_open = 1; |
97479f6f | 78 | |
73c902bf | 79 | if (first_open) { |
80 | first_open = 0; | |
97479f6f | 81 | |
73c902bf | 82 | /* initialize local argv */ |
83 | for (i = 0; i < 16; i++) | |
84 | Argv[i] = malloc(ARGLEN); | |
85 | ||
86 | IIseterr(ingerr); | |
87 | incremental_init(); | |
88 | flush_cache(); | |
89 | } | |
97479f6f | 90 | |
d26cae4e | 91 | ingres_errno = 0; |
d548a4e7 | 92 | mr_errcode = 0; |
73c902bf | 93 | |
d26cae4e | 94 | /* open the database */ |
95 | ## ingres sms | |
ca7c2f3d | 96 | ## set lockmode session where level = table, timeout = query_timeout |
45266a6f | 97 | ## set lockmode on capacls where readlock = shared |
98 | ## set lockmode on alias where readlock = shared | |
d26cae4e | 99 | return ingres_errno; |
97479f6f | 100 | } |
101 | ||
d548a4e7 | 102 | int mr_close_database() |
97479f6f | 103 | { |
73c902bf | 104 | flush_cache(); |
d26cae4e | 105 | ## exit |
97479f6f | 106 | } |
107 | ||
d548a4e7 | 108 | mr_check_access(cl, name, argc, argv_ro) |
7536027d | 109 | client *cl; |
110 | char *name; | |
111 | int argc; | |
112 | char *argv_ro[]; | |
113 | { | |
9969e1bc | 114 | struct query *q; |
7536027d | 115 | struct query *get_query_by_name(); |
7536027d | 116 | |
ca7c2f3d | 117 | ingres_errno = 0; |
d548a4e7 | 118 | mr_errcode = 0; |
ca7c2f3d | 119 | |
d548a4e7 | 120 | q = get_query_by_name(name, cl->args->mr_version_no); |
9969e1bc | 121 | if (q == (struct query *)0) |
d548a4e7 | 122 | return(MR_NO_HANDLE); |
7536027d | 123 | |
d548a4e7 | 124 | return(mr_verify_query(cl, q, argc, argv_ro)); |
7536027d | 125 | } |
126 | ||
d548a4e7 | 127 | mr_process_query(cl, name, argc, argv_ro, action, actarg) |
7536027d | 128 | client *cl; |
d26cae4e | 129 | char *name; |
130 | int argc; | |
131 | char *argv_ro[]; | |
132 | int (*action)(); | |
133 | char *actarg; | |
97479f6f | 134 | { |
d26cae4e | 135 | register struct query *q; |
7536027d | 136 | register int status; |
7536027d | 137 | register struct validate *v; |
7536027d | 138 | char qual[256]; |
cc1231a1 | 139 | char sort[32]; |
7536027d | 140 | char *pqual; |
cc1231a1 | 141 | char *psort; |
6a84801f | 142 | ## char *table, *rvar; |
7536027d | 143 | struct save_queue *sq; |
d26cae4e | 144 | struct query *get_query_by_name(); |
7536027d | 145 | int sq_save_args(); |
146 | struct save_queue *sq_create(); | |
cc1231a1 | 147 | char *build_sort(); |
d26cae4e | 148 | |
ca7c2f3d | 149 | ingres_errno = 0; |
d548a4e7 | 150 | mr_errcode = 0; |
ca7c2f3d | 151 | |
7536027d | 152 | /* list queries command */ |
153 | if (!strcmp(name, "_list_queries")) { | |
d548a4e7 | 154 | list_queries(cl->args->mr_version_no, action, actarg); |
155 | return(MR_SUCCESS); | |
7536027d | 156 | } |
157 | ||
158 | /* help query command */ | |
159 | if (!strcmp(name, "_help")) { | |
83526631 | 160 | if (argc < 1) |
d548a4e7 | 161 | return(MR_ARGS); |
162 | q = get_query_by_name(argv_ro[0], cl->args->mr_version_no); | |
163 | if (q == (struct query *)0) return(MR_NO_HANDLE); | |
7536027d | 164 | help_query(q, action, actarg); |
d548a4e7 | 165 | return(MR_SUCCESS); |
7536027d | 166 | } |
167 | ||
168 | /* get query structure, return error if named query does not exist */ | |
d548a4e7 | 169 | q = get_query_by_name(name, cl->args->mr_version_no); |
170 | if (q == (struct query *)0) return(MR_NO_HANDLE); | |
7536027d | 171 | v = q->validate; |
172 | ||
7ee33a8d | 173 | if (q->type != RETRIEVE) { |
d353058b | 174 | ## begin transaction |
7ee33a8d | 175 | } |
d353058b | 176 | |
9969e1bc | 177 | /* setup argument vector, verify access and arguments */ |
d548a4e7 | 178 | if ((status = mr_verify_query(cl, q, argc, argv_ro)) != MR_SUCCESS) |
d353058b | 179 | goto out; |
7536027d | 180 | |
181 | /* perform any special query pre-processing */ | |
182 | if (v && v->pre_rtn) { | |
183 | status = (*v->pre_rtn)(q, Argv, cl, 0); | |
d548a4e7 | 184 | if (status != MR_SUCCESS) |
d353058b | 185 | goto out; |
7536027d | 186 | } |
187 | ||
d26cae4e | 188 | switch (q->type) { |
faad6f39 | 189 | case RETRIEVE: |
7536027d | 190 | /* for queries that do not permit wildcarding, check if row |
191 | uniquely exists */ | |
192 | if (v && v->field) { | |
193 | status = validate_row(q, Argv, v); | |
d548a4e7 | 194 | if (status != MR_EXISTS) break; |
7536027d | 195 | } |
196 | ||
197 | /* build "where" clause if needed */ | |
d26cae4e | 198 | if (q->qual) { |
199 | build_qual(q->qual, q->argc, Argv, qual); | |
7536027d | 200 | pqual = qual; |
201 | } else { | |
202 | pqual = 0; | |
203 | } | |
204 | ||
cc1231a1 | 205 | /* build "sort" clause if needed */ |
206 | if (v && v->valobj) { | |
207 | psort = build_sort(v, sort); | |
208 | } else { | |
209 | psort = 0; | |
210 | } | |
211 | ||
7536027d | 212 | /* if there is a followup routine, then we must save the results */ |
213 | /* of the first query for use by the followup routine */ | |
cc1231a1 | 214 | /* if q->rvar = NULL, perform post_rtn only */ |
215 | if (q->rvar) { | |
7536027d | 216 | if (v && v->post_rtn) { |
217 | sq = sq_create(); | |
cc1231a1 | 218 | status = do_retrieve(q, pqual, psort, sq_save_args, sq); |
d548a4e7 | 219 | if (status != MR_SUCCESS) { |
7536027d | 220 | sq_destroy(sq); |
221 | break; | |
222 | } | |
83526631 | 223 | status = (*v->post_rtn)(q, sq, v, action, actarg, cl); |
7536027d | 224 | } else { |
225 | /* normal retrieve */ | |
cc1231a1 | 226 | status = do_retrieve(q, pqual, psort, action, actarg); |
7536027d | 227 | } |
d548a4e7 | 228 | if (status != MR_SUCCESS) break; |
7536027d | 229 | } else { |
83526631 | 230 | status = (*v->post_rtn)(q, Argv, cl, action, actarg); |
7536027d | 231 | } |
232 | ||
d26cae4e | 233 | break; |
234 | ||
faad6f39 | 235 | case UPDATE: |
7536027d | 236 | /* see if row already exists */ |
237 | if (v->field) { | |
238 | status = validate_row(q, Argv, v); | |
d548a4e7 | 239 | if (status != MR_EXISTS) break; |
7536027d | 240 | } |
241 | ||
242 | /* build "where" clause and perform update */ | |
cc1231a1 | 243 | /* if q->rvar = NULL, perform post_rtn only */ |
244 | if (q->rvar) { | |
7536027d | 245 | build_qual(q->qual, q->argc, Argv, qual); |
2755928d | 246 | incremental_before(q->rtable, qual, argv_ro); |
7536027d | 247 | status = do_update(q, &Argv[q->argc], qual, action, actarg); |
2755928d | 248 | incremental_after(q->rtable, qual, argv_ro); |
d548a4e7 | 249 | if (status != MR_SUCCESS) break; |
73c902bf | 250 | flush_name(argv_ro[0], q->rtable); |
cc1231a1 | 251 | table = q->rtable; |
37e49d47 | 252 | if (strcmp(q->shortname, "sshi") && strcmp(q->shortname, "ssif")) { |
253 | ## repeat replace tblstats (updates = tblstats.updates + 1, | |
254 | ## modtime = "now") | |
255 | ## where tblstats.#table = @table | |
256 | } | |
d26cae4e | 257 | } |
7536027d | 258 | |
259 | /* execute followup routine (if any) */ | |
83526631 | 260 | if (v->post_rtn) status = (*v->post_rtn)(q, Argv, cl); |
7536027d | 261 | |
d26cae4e | 262 | break; |
97479f6f | 263 | |
faad6f39 | 264 | case APPEND: |
7536027d | 265 | /* see if row already exists */ |
266 | if (v->field) { | |
267 | status = validate_row(q, Argv, v); | |
d548a4e7 | 268 | if (status != MR_NO_MATCH) break; |
d26cae4e | 269 | } |
7536027d | 270 | |
271 | /* increment id number if necessary */ | |
d353058b | 272 | if (v->object_id) { |
83526631 | 273 | status = set_next_object_id(v->object_id, q->rtable); |
d548a4e7 | 274 | if (status != MR_SUCCESS) break; |
d353058b | 275 | } |
7536027d | 276 | |
cc1231a1 | 277 | /* build "where" clause if needed */ |
278 | if (q->qual) { | |
279 | build_qual(q->qual, q->argc, Argv, qual); | |
280 | pqual = qual; | |
281 | } else { | |
282 | pqual = 0; | |
283 | } | |
284 | ||
7536027d | 285 | /* perform the append */ |
cc1231a1 | 286 | /* if q->rvar = NULL, perform post_rtn only */ |
287 | if (q->rvar) { | |
2755928d | 288 | incremental_clear_before(); |
cc1231a1 | 289 | status = do_append(q, &Argv[q->argc], pqual, action, actarg); |
d548a4e7 | 290 | if (status != MR_SUCCESS) break; |
2755928d | 291 | if (v && v->object_id) { |
292 | sprintf(qual, "%s.%s = values.value and values.name = \"%s\"", | |
293 | q->rvar, v->object_id, v->object_id); | |
294 | incremental_after(q->rtable, qual, argv_ro); | |
295 | } else | |
296 | incremental_after(q->rtable, pqual, argv_ro); | |
297 | ||
cc1231a1 | 298 | table = q->rtable; |
7536027d | 299 | ## repeat replace tblstats (appends = tblstats.appends + 1, |
300 | ## modtime = "now") | |
301 | ## where tblstats.#table = @table | |
302 | } | |
303 | ||
304 | /* execute followup routine */ | |
83526631 | 305 | if (v->post_rtn) status = (*v->post_rtn)(q, Argv, cl); |
d26cae4e | 306 | break; |
97479f6f | 307 | |
faad6f39 | 308 | case DELETE: |
7536027d | 309 | /* see if row already exists */ |
310 | if (v->field) { | |
311 | status = validate_row(q, Argv, v); | |
d548a4e7 | 312 | if (status != MR_EXISTS) break; |
7536027d | 313 | } |
314 | ||
315 | /* build "where" clause and perform delete */ | |
cc1231a1 | 316 | /* if q->rvar = NULL, perform post_rtn only */ |
317 | if (q->rvar) { | |
7536027d | 318 | build_qual(q->qual, q->argc, Argv, qual); |
6a84801f | 319 | table = q->rtable; |
320 | rvar = q->rvar; | |
321 | ## range of rvar is table | |
2755928d | 322 | incremental_before(q->rtable, qual, argv_ro); |
7536027d | 323 | status = do_delete(q, qual, action, actarg); |
2755928d | 324 | incremental_clear_after(); |
d548a4e7 | 325 | if (status != MR_SUCCESS) break; |
73c902bf | 326 | flush_name(argv_ro[0], q->rtable); |
7536027d | 327 | ## repeat replace tblstats (deletes = tblstats.deletes + 1, |
328 | ## modtime = "now") | |
329 | ## where tblstats.#table = @table | |
97479f6f | 330 | } |
7536027d | 331 | |
332 | /* execute followup routine */ | |
83526631 | 333 | if (v->post_rtn) status = (*v->post_rtn)(q, Argv, cl); |
d26cae4e | 334 | break; |
7536027d | 335 | |
d26cae4e | 336 | } |
7536027d | 337 | |
d353058b | 338 | out: |
d548a4e7 | 339 | if (status == MR_SUCCESS && ingres_errno != 0) { |
340 | com_err(whoami, MR_INTERNAL, "Server didn't notice INGRES ERROR %d", | |
e83ef509 | 341 | ingres_errno); |
d548a4e7 | 342 | status = mr_errcode; |
e83ef509 | 343 | } |
344 | ||
3df9e21e | 345 | if (q->type != RETRIEVE) { |
d548a4e7 | 346 | if (status == MR_SUCCESS) { |
d353058b | 347 | ## end transaction /* commit to this */ |
83526631 | 348 | if (journal) { |
349 | char buf[1024], *bp; | |
350 | int i; | |
351 | extern time_t now; | |
352 | ||
353 | fprintf(journal, "%% %s %s %s", | |
354 | cl->clname, cl->entity, ctime(&now)); | |
d548a4e7 | 355 | fprintf(journal, "%s[%d] ", q->name, cl->args->mr_version_no); |
83526631 | 356 | for (i = 0; i < argc; i++) { |
357 | if (i != 0) { | |
358 | putc(' ', journal); | |
359 | } | |
360 | requote(buf, argv_ro[i], sizeof(buf)); | |
361 | fputs(buf, journal); | |
362 | } | |
363 | putc('\n', journal); | |
364 | fflush(journal); | |
365 | } | |
2755928d | 366 | incremental_update(); |
3df9e21e | 367 | } else { |
ca7c2f3d | 368 | if (ingres_errno != INGRES_DEADLOCK) { |
7ee33a8d | 369 | ## abort /* it never happened */ |
370 | } | |
2755928d | 371 | incremental_flush(); |
3df9e21e | 372 | } |
ca7c2f3d | 373 | ## set lockmode session where readlock = system |
374 | } | |
375 | ||
d548a4e7 | 376 | if (status != MR_SUCCESS && log_flags & LOG_RES) |
1bf7f927 | 377 | com_err(whoami, status, " (Query failed)"); |
7536027d | 378 | return(status); |
97479f6f | 379 | } |
380 | ||
381 | build_qual(fmt, argc, argv, qual) | |
382 | char *fmt; | |
383 | int argc; | |
384 | char *argv[]; | |
385 | char *qual; | |
386 | { | |
7536027d | 387 | register char *c; |
388 | register int i; | |
389 | char *args[4]; | |
83526631 | 390 | char *index(); |
7536027d | 391 | |
392 | c = fmt; | |
393 | for (i = 0; i < argc; i++) { | |
83526631 | 394 | c = index(c, '%'); |
d548a4e7 | 395 | if (c++ == (char *)0) return(MR_ARGS); |
7536027d | 396 | if (*c == 's') |
397 | args[i] = argv[i]; | |
398 | else if (*c == 'd') | |
399 | *(int *)&args[i] = *(int *)argv[i]; /* sigh */ | |
400 | else | |
d548a4e7 | 401 | return(MR_INGRES_ERR); |
7536027d | 402 | } |
403 | ||
d26cae4e | 404 | switch (argc) { |
405 | case 0: | |
406 | strcpy(qual, fmt); | |
407 | break; | |
408 | ||
409 | case 1: | |
7536027d | 410 | sprintf(qual, fmt, args[0]); |
d26cae4e | 411 | break; |
412 | ||
413 | case 2: | |
7536027d | 414 | sprintf(qual, fmt, args[0], args[1]); |
d26cae4e | 415 | break; |
416 | ||
417 | case 3: | |
7536027d | 418 | sprintf(qual, fmt, args[0], args[1], args[2]); |
d26cae4e | 419 | break; |
420 | ||
421 | case 4: | |
7536027d | 422 | sprintf(qual, fmt, args[0], args[1], args[2], args[3]); |
d26cae4e | 423 | break; |
424 | } | |
d548a4e7 | 425 | return(MR_SUCCESS); |
97479f6f | 426 | } |
427 | ||
cc1231a1 | 428 | char * |
429 | build_sort(v, sort) | |
430 | register struct validate *v; | |
431 | char *sort; | |
432 | { | |
433 | register struct valobj *vo; | |
434 | register int n; | |
435 | char elem[16]; | |
436 | ||
437 | n = v->objcnt; | |
438 | vo = v->valobj; | |
439 | *sort = 0; | |
440 | ||
441 | while (--n >= 0) { | |
442 | if (vo->type == V_SORT) { | |
443 | sprintf(elem, "RET_VAR%d", vo->index + 1); | |
444 | if (*sort) strcat(sort, ", "); | |
445 | strcat(sort, elem); | |
446 | } | |
447 | vo++; | |
448 | } | |
449 | ||
450 | return ((*sort) ? sort : 0); | |
451 | } | |
452 | ||
9969e1bc | 453 | |
454 | /* Build arguement vector, verify query and arguments */ | |
455 | ||
d548a4e7 | 456 | mr_verify_query(cl, q, argc, argv_ro) |
9969e1bc | 457 | client *cl; |
458 | struct query *q; | |
459 | int argc; | |
460 | char *argv_ro[]; | |
461 | { | |
462 | register int argreq; | |
463 | register int status; | |
464 | register struct validate *v = q->validate; | |
465 | register int i; | |
466 | register int privileged = 0; | |
02d466cf | 467 | int len; |
9969e1bc | 468 | |
469 | /* copy the arguments into a local argv that we can modify */ | |
7ee33a8d | 470 | if (argc >= QMAXARGS) |
d548a4e7 | 471 | return(MR_ARGS); |
9969e1bc | 472 | for (i = 0; i < argc; i++) { |
02d466cf | 473 | if ((len = strlen(argv_ro[i])) < ARGLEN) |
9969e1bc | 474 | strcpy(Argv[i], argv_ro[i]); |
475 | else | |
d548a4e7 | 476 | return(MR_ARG_TOO_LONG); |
02d466cf | 477 | if (Argv[i][len-1] == '\\') |
d548a4e7 | 478 | return(MR_BAD_CHAR); |
9969e1bc | 479 | } |
480 | ||
481 | /* check initial query access */ | |
482 | status = check_query_access(q, Argv, cl); | |
d548a4e7 | 483 | if (status != MR_SUCCESS && status != MR_PERM) |
9969e1bc | 484 | return(status); |
d548a4e7 | 485 | if (status == MR_SUCCESS) |
9969e1bc | 486 | privileged++; |
487 | ||
488 | /* check argument count */ | |
489 | argreq = q->argc; | |
490 | if (q->type == UPDATE || q->type == APPEND) argreq += q->vcnt; | |
d548a4e7 | 491 | if (argc != argreq) return(MR_ARGS); |
9969e1bc | 492 | |
493 | /* validate arguments */ | |
494 | if (v && v->valobj) { | |
495 | status = validate_fields(q, Argv, v->valobj, v->objcnt); | |
d548a4e7 | 496 | if (status != MR_SUCCESS) return(status); |
9969e1bc | 497 | } |
498 | ||
499 | /* perform special query access check */ | |
500 | if (!privileged && v && v->acs_rtn) { | |
501 | status = (*v->acs_rtn)(q, Argv, cl); | |
d548a4e7 | 502 | if (status != MR_SUCCESS && status != MR_PERM) |
9969e1bc | 503 | return(status); |
d548a4e7 | 504 | if (status == MR_SUCCESS) |
9969e1bc | 505 | privileged++; |
506 | } | |
507 | ||
d548a4e7 | 508 | return(privileged ? MR_SUCCESS : MR_PERM); |
9969e1bc | 509 | } |
510 | ||
2755928d | 511 | |
512 | /* This routine caches info from the database. Each query acl is stored | |
513 | * in the query structure, and whether that acl contains everybody. | |
514 | */ | |
515 | ||
7536027d | 516 | check_query_access(q, argv, cl) |
517 | struct query *q; | |
518 | char *argv[]; | |
519 | client *cl; | |
d26cae4e | 520 | ##{ |
7536027d | 521 | ## char *name; |
522 | ## int acl_id; | |
523 | ## int exists; | |
d26cae4e | 524 | ## int rowcount; |
cc1231a1 | 525 | ## int errorno; |
7536027d | 526 | ## static int def_uid; |
527 | int status; | |
528 | int client_id; | |
529 | char *client_type; | |
530 | ||
7536027d | 531 | /* initialize default uid */ |
532 | if (def_uid == 0) { | |
533 | ## retrieve (def_uid = users.users_id) where users.login = "default" | |
d26cae4e | 534 | } |
97479f6f | 535 | |
2755928d | 536 | /* get query access control list */ |
537 | if (q->acl != 0) | |
538 | acl_id = q->acl; | |
539 | else { | |
540 | name = q->shortname; | |
73c902bf | 541 | ## retrieve (acl_id = capacls.list_id) where capacls.tag = name |
2755928d | 542 | ## inquire_equel (rowcount = "rowcount", errorno = "errorno") |
d548a4e7 | 543 | if (errorno != 0) return(MR_INGRES_ERR); |
544 | if (rowcount == 0) return(MR_PERM); | |
2755928d | 545 | q->acl = acl_id; |
546 | ||
547 | /* check for default access */ | |
73c902bf | 548 | ## retrieve (exists = any(imembers.#member_id where |
549 | ## imembers.list_id = acl_id and | |
550 | ## imembers.member_type = "USER" and | |
551 | ## imembers.#member_id = def_uid)) | |
2755928d | 552 | q->everybody = exists; |
553 | } | |
554 | ||
555 | if (q->everybody) | |
d548a4e7 | 556 | return(MR_SUCCESS); |
2755928d | 557 | |
d548a4e7 | 558 | if (get_client(cl, &client_type, &client_id) != MR_SUCCESS) |
559 | return(MR_PERM); | |
db8a5dda | 560 | if (find_member("LIST", acl_id, client_type, client_id, 0)) |
d548a4e7 | 561 | return(MR_SUCCESS); |
2755928d | 562 | else |
d548a4e7 | 563 | return(MR_PERM); |
2755928d | 564 | ##} |
565 | ||
566 | ||
7536027d | 567 | get_client(cl, client_type, client_id) |
568 | client *cl; | |
569 | char **client_type; | |
570 | int *client_id; | |
2755928d | 571 | { |
572 | if (cl->users_id > 0) { | |
83526631 | 573 | *client_id = cl->users_id; |
7536027d | 574 | *client_type = "USER"; |
d548a4e7 | 575 | return(MR_SUCCESS); |
7536027d | 576 | } |
83526631 | 577 | |
2755928d | 578 | if (cl->client_id < 0) { |
579 | *client_id = -cl->users_id; | |
580 | *client_type = "KERBEROS"; | |
d548a4e7 | 581 | return(MR_SUCCESS); |
2755928d | 582 | } |
7536027d | 583 | |
d548a4e7 | 584 | return(MR_PERM); |
2755928d | 585 | } |
97479f6f | 586 | |
dff355ae | 587 | ##find_member(list_type, list_id, member_type, member_id) |
83526631 | 588 | char *list_type; |
7536027d | 589 | ## int list_id; |
590 | ## char *member_type; | |
591 | ## int member_id; | |
7536027d | 592 | ##{ |
dff355ae | 593 | ## int exists, errorno; |
7536027d | 594 | |
e45a151a | 595 | if (!strcmp(strtrim(list_type), strtrim(member_type)) && |
596 | list_id == member_id) | |
597 | return(1); | |
598 | ||
7536027d | 599 | /* see if client is a direct member of list */ |
2755928d | 600 | ## repeat retrieve (exists = any(imembers.#member_id where |
601 | ## imembers.#list_id = @list_id and | |
602 | ## imembers.#member_type = @member_type and | |
603 | ## imembers.#member_id = @member_id)) | |
dff355ae | 604 | ## inquire_equel(errorno = "errorno") |
605 | if (errorno == 0) | |
606 | return(exists); | |
607 | else | |
608 | return(0); | |
d26cae4e | 609 | ##} |
97479f6f | 610 | |
83526631 | 611 | |
cc1231a1 | 612 | do_retrieve(q, pqual, psort, action, actarg) |
d26cae4e | 613 | register struct query *q; |
cc1231a1 | 614 | char *pqual; |
615 | char *psort; | |
d26cae4e | 616 | int (*action)(); |
617 | char *actarg; | |
618 | ##{ | |
619 | ## char *rvar; | |
620 | ## char *rtable; | |
621 | ## char *cqual; | |
cc1231a1 | 622 | ## char *csort; |
d26cae4e | 623 | ## int rowcount; |
cc1231a1 | 624 | ## int errorno; |
83526631 | 625 | static char **vaddrs = (char **)NULL; |
626 | ||
627 | if (!vaddrs) { | |
628 | register int i; | |
629 | ||
630 | if ((vaddrs = (char **)malloc(sizeof(char *) * QMAXARGS)) == NULL) { | |
d548a4e7 | 631 | com_err(whoami, MR_NO_MEM, "setting up static argv"); |
83526631 | 632 | exit(1); |
633 | } | |
634 | for (i = 0; i < QMAXARGS; i++) { | |
635 | if ((vaddrs[i] = malloc(QMAXARGSIZE)) == NULL) { | |
d548a4e7 | 636 | com_err(whoami, MR_NO_MEM, "setting up static argv"); |
83526631 | 637 | exit(1); |
638 | } | |
639 | } | |
640 | } | |
7536027d | 641 | |
d26cae4e | 642 | if (q->rvar) { |
643 | rvar = q->rvar; | |
644 | rtable = q->rtable; | |
645 | ## range of rvar is rtable | |
646 | } | |
97479f6f | 647 | |
cc1231a1 | 648 | if (psort) { |
649 | csort = psort; | |
650 | if (pqual) { | |
651 | cqual = pqual; | |
83526631 | 652 | ## retrieve unique (param (q->tlist, vaddrs)) where cqual |
cc1231a1 | 653 | ## sort by csort |
654 | ## { | |
83526631 | 655 | (*action)(q->vcnt, vaddrs, actarg); |
cc1231a1 | 656 | ## } |
657 | } else { | |
83526631 | 658 | ## retrieve unique (param (q->tlist, vaddrs)) |
cc1231a1 | 659 | ## sort by csort |
660 | ## { | |
83526631 | 661 | (*action)(q->vcnt, vaddrs, actarg); |
cc1231a1 | 662 | ## } |
663 | } | |
664 | ||
7536027d | 665 | } else { |
cc1231a1 | 666 | if (pqual) { |
667 | cqual = pqual; | |
83526631 | 668 | ## retrieve unique (param (q->tlist, vaddrs)) where cqual |
cc1231a1 | 669 | ## { |
83526631 | 670 | (*action)(q->vcnt, vaddrs, actarg); |
cc1231a1 | 671 | ## } |
672 | } else { | |
83526631 | 673 | ## retrieve unique (param (q->tlist, vaddrs)) |
cc1231a1 | 674 | ## { |
83526631 | 675 | (*action)(q->vcnt, vaddrs, actarg); |
cc1231a1 | 676 | ## } |
677 | } | |
7536027d | 678 | } |
97479f6f | 679 | |
d548a4e7 | 680 | if (mr_errcode) return(mr_errcode); |
51dfb5b8 | 681 | ## inquire_equel (rowcount = "rowcount") |
d548a4e7 | 682 | return ((rowcount == 0) ? MR_NO_MATCH : MR_SUCCESS); |
d26cae4e | 683 | ##} |
97479f6f | 684 | |
e38c941b | 685 | do_update(q, argv, qual, action, actarg) |
d26cae4e | 686 | register struct query *q; |
687 | char *argv[]; | |
688 | char *qual; | |
689 | int (*action)(); | |
690 | char *actarg; | |
691 | ##{ | |
692 | ## char *rvar; | |
693 | ## char *rtable; | |
694 | ## char *cqual; | |
cc1231a1 | 695 | ## int errorno; |
97479f6f | 696 | |
d26cae4e | 697 | rvar = q->rvar; |
698 | rtable = q->rtable; | |
699 | ## range of rvar is rtable | |
97479f6f | 700 | |
d26cae4e | 701 | cqual = qual; |
702 | ## replace rvar (param (q->tlist, argv)) | |
703 | ## where cqual | |
97479f6f | 704 | |
d548a4e7 | 705 | if (mr_errcode) return(mr_errcode); |
706 | return(MR_SUCCESS); | |
d26cae4e | 707 | ##} |
97479f6f | 708 | |
cc1231a1 | 709 | do_append(q, argv, pqual, action, actarg) |
d26cae4e | 710 | register struct query *q; |
711 | char *argv[]; | |
cc1231a1 | 712 | char *pqual; |
d26cae4e | 713 | int (*action)(); |
714 | char *actarg; | |
715 | ##{ | |
716 | ## char *rvar; | |
717 | ## char *rtable; | |
7536027d | 718 | ## char *cqual; |
cc1231a1 | 719 | ## int errorno; |
97479f6f | 720 | |
d26cae4e | 721 | rvar = q->rvar; |
722 | rtable = q->rtable; | |
723 | ## range of rvar is rtable | |
97479f6f | 724 | |
cc1231a1 | 725 | if (pqual) { |
726 | cqual = pqual; | |
7536027d | 727 | ## append to rtable (param (q->tlist, argv)) where cqual |
728 | } else { | |
729 | ## append to rtable (param (q->tlist, argv)) | |
730 | } | |
97479f6f | 731 | |
d548a4e7 | 732 | if (mr_errcode) return(mr_errcode); |
733 | return(MR_SUCCESS); | |
d26cae4e | 734 | ##} |
97479f6f | 735 | |
e38c941b | 736 | do_delete(q, qual, action, actarg) |
d26cae4e | 737 | register struct query *q; |
738 | char *qual; | |
739 | int (*action)(); | |
740 | char *actarg; | |
741 | ##{ | |
742 | ## char *rvar; | |
743 | ## char *rtable; | |
744 | ## char *cqual; | |
cc1231a1 | 745 | ## int errorno; |
97479f6f | 746 | |
d26cae4e | 747 | rvar = q->rvar; |
748 | rtable = q->rtable; | |
749 | ## range of rvar is rtable | |
97479f6f | 750 | |
d26cae4e | 751 | cqual = qual; |
752 | ## delete rvar where cqual | |
97479f6f | 753 | |
d548a4e7 | 754 | if (mr_errcode) return(mr_errcode); |
755 | return(MR_SUCCESS); | |
d26cae4e | 756 | ##} |
97479f6f | 757 | |
d26cae4e | 758 | |
83526631 | 759 | /** |
760 | ** set_next_object_id - set next object id in values table | |
761 | ** | |
762 | ** Inputs: object - object name in values table and in objects | |
763 | ** table - name of table objects are found in | |
764 | ** | |
765 | ** - called before an APPEND operation to set the next object id to | |
766 | ** be used for the new record to the next free value | |
767 | ** | |
768 | **/ | |
769 | ||
770 | set_next_object_id(object, table) | |
771 | char *object; | |
772 | char *table; | |
773 | ##{ | |
774 | ## char *name, *tbl; | |
775 | ## int rowcount, exists, value; | |
776 | ||
777 | name = object; | |
778 | tbl = table; | |
73c902bf | 779 | ## repeat retrieve (value = values.#value) where values.#name = @name |
83526631 | 780 | ## inquire_equel(rowcount = "rowcount") |
781 | if (rowcount != 1) | |
d548a4e7 | 782 | return(MR_NO_ID); |
83526631 | 783 | |
784 | ## retrieve (exists = any(tbl.name where tbl.name = value)) | |
785 | ## inquire_equel(rowcount = "rowcount") | |
786 | if (rowcount != 1) | |
d548a4e7 | 787 | return(MR_NO_ID); |
83526631 | 788 | while (exists) { |
789 | value++; | |
8fcb440e | 790 | if (value > MAX_ID_VALUE) |
791 | value = MIN_ID_VALUE; | |
83526631 | 792 | ## retrieve (exists = any(tbl.name where tbl.name = value)) |
793 | } | |
794 | ||
795 | if (LOG_RES) | |
796 | com_err(whoami, 0, "setting ID %s to %d", name, value); | |
73c902bf | 797 | ## repeat replace values (#value = @value) where values.#name = @name |
d548a4e7 | 798 | return(MR_SUCCESS); |
83526631 | 799 | ##} |
800 | ||
801 | ||
2755928d | 802 | /* Turn a kerberos name into the user's ID of the account that principal |
803 | * owns. Sets the kerberos ID and user ID. | |
804 | */ | |
805 | ||
f2bf8730 | 806 | int set_krb_mapping(name, login, ok, kid, uid) |
2755928d | 807 | char *name; |
808 | char *login; | |
809 | int ok; | |
810 | int *kid; | |
811 | int *uid; | |
812 | ##{ | |
813 | ## int u_id, k_id, rowcount; | |
814 | ## char *krbname; | |
815 | ||
816 | krbname = name; | |
817 | *kid = 0; | |
818 | *uid = 0; | |
819 | ||
73c902bf | 820 | ## repeat retrieve (u_id = krbmap.#users_id, k_id = krbmap.#string_id) |
821 | ## where krbmap.string_id = strings.string_id and strings.string = @krbname | |
2755928d | 822 | ## inquire_equel (rowcount = "rowcount") |
f2bf8730 | 823 | if (ingres_errno) return(mr_errcode); |
2755928d | 824 | |
825 | if (rowcount == 1) { | |
826 | *kid = -k_id; | |
827 | *uid = u_id; | |
f0fbba87 | 828 | return(MR_SUCCESS); |
2755928d | 829 | } |
830 | ||
d548a4e7 | 831 | if (name_to_id(name, "STRINGS", &k_id) == MR_SUCCESS) |
73c902bf | 832 | *kid = -k_id; |
2755928d | 833 | |
834 | if (!ok) { | |
835 | *uid = *kid; | |
f0fbba87 | 836 | return(MR_SUCCESS); |
2755928d | 837 | } |
838 | ||
d548a4e7 | 839 | if (name_to_id(login, "USERS", uid) != MR_SUCCESS) |
73c902bf | 840 | *uid = 0; |
841 | ||
2755928d | 842 | if (*kid == 0) |
843 | *kid = *uid; | |
f2bf8730 | 844 | if (ingres_errno) return(mr_errcode); |
845 | return(MR_SUCCESS); | |
2755928d | 846 | ##} |
847 | ||
848 | ||
83526631 | 849 | /* For now this just checks the argc's. It should also see that there |
850 | * are no duplicate names. | |
851 | */ | |
852 | ||
853 | sanity_check_queries() | |
854 | { | |
855 | register int i; | |
856 | int maxv = 0, maxa = 0; | |
c5a0c32c | 857 | #ifdef MULTIPROTOCOLS |
83526631 | 858 | extern int QueryCount1, QueryCount2; |
859 | extern struct query Queries1[], Queries2[]; | |
c5a0c32c | 860 | #else |
861 | extern int QueryCount2; | |
862 | extern struct query Queries2[]; | |
863 | #endif MULTIPROTOCOLS | |
864 | ||
83526631 | 865 | #define MAX(x,y) ((x) > (y) ? (x) : (y)) |
866 | ||
c5a0c32c | 867 | #ifdef MULTIPROTOCOLS |
83526631 | 868 | for (i = 0; i < QueryCount1; i++) { |
869 | maxv = MAX(maxv, Queries1[i].vcnt); | |
870 | maxa = MAX(maxa, Queries1[i].argc); | |
871 | } | |
c5a0c32c | 872 | #endif MULTIPROTOCOLS |
83526631 | 873 | for (i = 0; i < QueryCount2; i++) { |
874 | maxv = MAX(maxv, Queries2[i].vcnt); | |
875 | maxa = MAX(maxa, Queries2[i].argc); | |
876 | } | |
877 | if (MAX(maxv, maxa) > QMAXARGS) { | |
878 | com_err(whoami, 0, "A query has more args than QMAXARGS"); | |
879 | exit(1); | |
880 | } | |
881 | } |