]> andersk Git - moira.git/blame - server/qrtn.qc
upped string lengths to reasonable levels.
[moira.git] / server / qrtn.qc
CommitLineData
d26cae4e 1/*
2 * $Source$
3 * $Author$
4 * $Header$
5 *
6 * Copyright (C) 1987 by the Massachusetts Institute of Technology
7 *
8 * $Log$
19bf23eb 9 * Revision 1.11 1987-09-01 16:10:01 wesommer
10 * This change was made by Mike, who didn't feel like checking it in.
11 * Temp hack: ignore instances.
faad6f39 12 *
19bf23eb 13 * Revision 1.10 87/08/28 14:57:51 mike
14 * Modified sms_query to not enclose RETRIEVE queries in begin/end transaction.
15 * This was necessary to allow get_all_poboxes and get_groups_of_all_users
16 * to temporarily change the Ingres lockmode.
17 *
3df9e21e 18 * Revision 1.9 87/08/22 17:47:38 wesommer
19 * Cleanup (these changes were by Mike).
20 *
cc1231a1 21 * Revision 1.8 87/08/10 16:22:26 mike
22 * wesommer modified error reporting.
23 *
1bf7f927 24 * Revision 1.7 87/08/04 01:49:20 wesommer
25 * Rearranged messages.
26 *
b4182127 27 * Revision 1.6 87/08/04 01:30:54 wesommer
28 * Mike's changes; checked in prior to working over messages.
29 *
7536027d 30 * Revision 1.5 87/06/21 16:37:58 wesommer
31 * Changed include files, reindented things.
32 *
33 *
faad6f39 34 * Revision 1.4 87/06/08 05:03:27 wesommer
35 * Reindented; added header and trailer.
36 *
d26cae4e 37 */
38
39#ifndef lint
40static char *rcsid_qrtn_qc = "$Header$";
41#endif lint
42
97479f6f 43#include "query.h"
97479f6f 44#include "sms_server.h"
45
7536027d 46#define SMS_SUCCESS 0
47
97479f6f 48char *Argv[16];
49
50static int ingres_errno = 0;
7536027d 51extern char *whoami;
97479f6f 52
d26cae4e 53/*
54 * ingerr: (supposedly) called when Ingres indicates an error.
55 * I have not yet been able to get this to work to intercept a
56 * database open error.
57 */
58
59static int ingerr(num)
60 int *num;
97479f6f 61{
d26cae4e 62 ingres_errno = SMS_INGRES_ERR;
1bf7f927 63 com_err(whoami, SMS_INGRES_ERR, " code %d\n", ingres_errno);
d26cae4e 64 return *num;
97479f6f 65}
66
d26cae4e 67int sms_open_database()
97479f6f 68{
d26cae4e 69 register int i;
97479f6f 70
d26cae4e 71 /* initialize local argv */
72 for (i = 0; i < 16; i++)
73 Argv[i] = (char *)malloc(128);
97479f6f 74
d26cae4e 75 IIseterr(ingerr);
97479f6f 76
d26cae4e 77 ingres_errno = 0;
97479f6f 78
d26cae4e 79 /* open the database */
80## ingres sms
81 return ingres_errno;
97479f6f 82}
83
d26cae4e 84int sms_close_database()
97479f6f 85{
d26cae4e 86## exit
97479f6f 87}
88
7536027d 89sms_check_access(cl, name, argc, argv_ro)
90 client *cl;
91 char *name;
92 int argc;
93 char *argv_ro[];
94{
95 register struct query *q;
96 register int argreq;
97 register int status;
98 register struct validate *v;
99 register int i;
100 register int privileged;
101 struct query *get_query_by_name();
102 int access_user();
103 int access_pop();
cc1231a1 104 int access_list();
7536027d 105
106 q = get_query_by_name(name);
107 if (q == (struct query *)0) return(SMS_NO_HANDLE);
108 v = q->validate;
109
110 /* copy the arguments into a local argv that we can modify */
111 for (i = 0; i < argc; i++)
112 strcpy(Argv[i], argv_ro[i]);
113
114 /* check initial query access */
115 status = check_query_access(q, Argv, cl);
116 privileged = (status == SMS_SUCCESS) ? 1 : 0;
117 if (status != SMS_SUCCESS && !(v && (v->pre_rtn == access_user ||
cc1231a1 118 v->pre_rtn == access_pop ||
119 v->pre_rtn == access_list)))
7536027d 120 return(status);
121
122 /* check argument count */
123 argreq = q->argc;
124 if (q->type == UPDATE || q->type == APPEND) argreq += q->vcnt;
125 if (argc != argreq) return(SMS_ARGS);
126
127 /* validate arguments */
128 if (v && v->valobj) {
129 status = validate_fields(q, Argv, v->valobj, v->objcnt);
130 if (status != SMS_SUCCESS) return(status);
131 }
132
133 /* perform special query access check */
134 if (v && v->pre_rtn) {
135 status = (*v->pre_rtn)(q, Argv, cl, 1);
136 if (status != SMS_SUCCESS && (status != SMS_PERM || !privileged))
137 return(status);
138 }
139
140 return(SMS_SUCCESS);
141}
142
143sms_process_query(cl, name, argc, argv_ro, action, actarg)
144 client *cl;
d26cae4e 145 char *name;
146 int argc;
147 char *argv_ro[];
148 int (*action)();
149 char *actarg;
97479f6f 150{
d26cae4e 151 register struct query *q;
152 register int i;
7536027d 153 register int status;
154 register int argreq;
155 register struct validate *v;
156 int privileged;
157 char qual[256];
cc1231a1 158 char sort[32];
7536027d 159 char *pqual;
cc1231a1 160 char *psort;
7536027d 161## char *table;
162 struct save_queue *sq;
d26cae4e 163 struct query *get_query_by_name();
7536027d 164 int sq_save_args();
165 struct save_queue *sq_create();
cc1231a1 166 char *build_sort();
7536027d 167 int access_user();
cc1231a1 168 int access_pop();
169 int access_list();
d26cae4e 170
171 /* copy the arguments into a local argv that we can modify */
172 for (i = 0; i < argc; i++)
173 strcpy(Argv[i], argv_ro[i]);
174
7536027d 175 /* list queries command */
176 if (!strcmp(name, "_list_queries")) {
177 list_queries(action, actarg);
178 return(SMS_SUCCESS);
179 }
180
181 /* help query command */
182 if (!strcmp(name, "_help")) {
183 q = get_query_by_name(Argv[0]);
184 if (q == (struct query *)0) return(SMS_NO_HANDLE);
185 help_query(q, action, actarg);
186 return(SMS_SUCCESS);
187 }
188
189 /* get query structure, return error if named query does not exist */
d26cae4e 190 q = get_query_by_name(name);
7536027d 191 if (q == (struct query *)0) return(SMS_NO_HANDLE);
192 v = q->validate;
193
194 /* check query access */
195 status = check_query_access(q, Argv, cl);
196 privileged = (status == SMS_SUCCESS) ? 1 : 0;
cc1231a1 197 if (!privileged && !(status == SMS_PERM &&
198 (v && (v->pre_rtn == access_user ||
199 v->pre_rtn == access_pop ||
200 v->pre_rtn == access_list))))
7536027d 201 return(status);
202
203 /* check argument count */
204 argreq = q->argc;
205 if (q->type == UPDATE || q->type == APPEND) argreq += q->vcnt;
206 if (argc != argreq) return(SMS_ARGS);
207
208 /* validate arguments */
209 if (v && v->valobj) {
210 status = validate_fields(q, Argv, v->valobj, v->objcnt);
211 if (status != SMS_SUCCESS) return(status);
212 }
213
214 /* perform any special query pre-processing */
215 if (v && v->pre_rtn) {
216 status = (*v->pre_rtn)(q, Argv, cl, 0);
217 if (status != SMS_SUCCESS && (status != SMS_PERM || !privileged))
218 return(status);
219 }
220
3df9e21e 221 if (q->type != RETRIEVE)
222## begin transaction
d26cae4e 223
224 switch (q->type) {
faad6f39 225 case RETRIEVE:
7536027d 226 /* for queries that do not permit wildcarding, check if row
227 uniquely exists */
228 if (v && v->field) {
229 status = validate_row(q, Argv, v);
230 if (status != SMS_EXISTS) break;
231 }
232
233 /* build "where" clause if needed */
d26cae4e 234 if (q->qual) {
235 build_qual(q->qual, q->argc, Argv, qual);
7536027d 236 pqual = qual;
237 } else {
238 pqual = 0;
239 }
240
cc1231a1 241 /* build "sort" clause if needed */
242 if (v && v->valobj) {
243 psort = build_sort(v, sort);
244 } else {
245 psort = 0;
246 }
247
7536027d 248 /* if there is a followup routine, then we must save the results */
249 /* of the first query for use by the followup routine */
cc1231a1 250 /* if q->rvar = NULL, perform post_rtn only */
251 if (q->rvar) {
7536027d 252 if (v && v->post_rtn) {
253 sq = sq_create();
cc1231a1 254 status = do_retrieve(q, pqual, psort, sq_save_args, sq);
7536027d 255 if (status != SMS_SUCCESS) {
256 sq_destroy(sq);
257 break;
258 }
259 status = (*v->post_rtn)(q, sq, v, action, actarg);
260 } else {
261 /* normal retrieve */
cc1231a1 262 status = do_retrieve(q, pqual, psort, action, actarg);
7536027d 263 }
264 if (status != SMS_SUCCESS) break;
cc1231a1 265 table = q->rtable;
7536027d 266## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
267## where tblstats.#table = @table
268 } else {
269 status = (*v->post_rtn)(q, Argv, action, actarg);
270 }
271
d26cae4e 272 break;
273
faad6f39 274 case UPDATE:
7536027d 275 /* see if row already exists */
276 if (v->field) {
277 status = validate_row(q, Argv, v);
278 if (status != SMS_EXISTS) break;
279 }
280
281 /* build "where" clause and perform update */
cc1231a1 282 /* if q->rvar = NULL, perform post_rtn only */
283 if (q->rvar) {
7536027d 284 build_qual(q->qual, q->argc, Argv, qual);
285 status = do_update(q, &Argv[q->argc], qual, action, actarg);
286 if (status != SMS_SUCCESS) break;
cc1231a1 287 table = q->rtable;
7536027d 288## repeat replace tblstats (updates = tblstats.updates + 1,
289## modtime = "now")
290## where tblstats.#table = @table
d26cae4e 291 }
7536027d 292
293 /* execute followup routine (if any) */
294 if (v->post_rtn) status = (*v->post_rtn)(q, Argv);
295
d26cae4e 296 break;
97479f6f 297
faad6f39 298 case APPEND:
7536027d 299 /* see if row already exists */
300 if (v->field) {
301 status = validate_row(q, Argv, v);
302 if (status != SMS_NO_MATCH) break;
d26cae4e 303 }
7536027d 304
305 /* increment id number if necessary */
306 if (v->object_id) set_next_object_id(v->object_id);
307
cc1231a1 308 /* build "where" clause if needed */
309 if (q->qual) {
310 build_qual(q->qual, q->argc, Argv, qual);
311 pqual = qual;
312 } else {
313 pqual = 0;
314 }
315
7536027d 316 /* perform the append */
cc1231a1 317 /* if q->rvar = NULL, perform post_rtn only */
318 if (q->rvar) {
319 status = do_append(q, &Argv[q->argc], pqual, action, actarg);
7536027d 320 if (status != SMS_SUCCESS) break;
cc1231a1 321 table = q->rtable;
7536027d 322## repeat replace tblstats (appends = tblstats.appends + 1,
323## modtime = "now")
324## where tblstats.#table = @table
325 }
326
327 /* execute followup routine */
328 if (v->post_rtn) status = (*v->post_rtn)(q, Argv);
d26cae4e 329 break;
97479f6f 330
faad6f39 331 case DELETE:
7536027d 332 /* see if row already exists */
333 if (v->field) {
334 status = validate_row(q, Argv, v);
335 if (status != SMS_EXISTS) break;
336 }
337
338 /* build "where" clause and perform delete */
cc1231a1 339 /* if q->rvar = NULL, perform post_rtn only */
340 if (q->rvar) {
7536027d 341 build_qual(q->qual, q->argc, Argv, qual);
342 status = do_delete(q, qual, action, actarg);
343 if (status != SMS_SUCCESS) break;
cc1231a1 344 table = q->rtable;
7536027d 345## repeat replace tblstats (deletes = tblstats.deletes + 1,
346## modtime = "now")
347## where tblstats.#table = @table
97479f6f 348 }
7536027d 349
350 /* execute followup routine */
351 if (v->post_rtn) status = (*v->post_rtn)(q, Argv);
d26cae4e 352 break;
7536027d 353
d26cae4e 354 }
7536027d 355
3df9e21e 356 if (q->type != RETRIEVE) {
357 if (status == SMS_SUCCESS) {
358## end transaction
359 } else {
360## abort
361 }
362 }
7536027d 363
1bf7f927 364 if (status != SMS_SUCCESS && log_flags & LOG_RES)
365 com_err(whoami, status, " (Query failed)");
7536027d 366 return(status);
97479f6f 367}
368
369build_qual(fmt, argc, argv, qual)
370 char *fmt;
371 int argc;
372 char *argv[];
373 char *qual;
374{
7536027d 375 register char *c;
376 register int i;
377 char *args[4];
378
379 c = fmt;
380 for (i = 0; i < argc; i++) {
381 c = (char *)index(c, '%');
382 if (c++ == (char *)0) return(SMS_ARGS);
383 if (*c == 's')
384 args[i] = argv[i];
385 else if (*c == 'd')
386 *(int *)&args[i] = *(int *)argv[i]; /* sigh */
387 else
388 return(SMS_INGRES_ERR);
389 }
390
d26cae4e 391 switch (argc) {
392 case 0:
393 strcpy(qual, fmt);
394 break;
395
396 case 1:
7536027d 397 sprintf(qual, fmt, args[0]);
d26cae4e 398 break;
399
400 case 2:
7536027d 401 sprintf(qual, fmt, args[0], args[1]);
d26cae4e 402 break;
403
404 case 3:
7536027d 405 sprintf(qual, fmt, args[0], args[1], args[2]);
d26cae4e 406 break;
407
408 case 4:
7536027d 409 sprintf(qual, fmt, args[0], args[1], args[2], args[3]);
d26cae4e 410 break;
411 }
97479f6f 412}
413
cc1231a1 414char *
415build_sort(v, sort)
416 register struct validate *v;
417 char *sort;
418{
419 register struct valobj *vo;
420 register int n;
421 char elem[16];
422
423 n = v->objcnt;
424 vo = v->valobj;
425 *sort = 0;
426
427 while (--n >= 0) {
428 if (vo->type == V_SORT) {
429 sprintf(elem, "RET_VAR%d", vo->index + 1);
430 if (*sort) strcat(sort, ", ");
431 strcat(sort, elem);
432 }
433 vo++;
434 }
435
436 return ((*sort) ? sort : 0);
437}
438
7536027d 439check_query_access(q, argv, cl)
440 struct query *q;
441 char *argv[];
442 client *cl;
d26cae4e 443##{
7536027d 444## char *name;
445## int acl_id;
446## int exists;
d26cae4e 447## int rowcount;
cc1231a1 448## int errorno;
7536027d 449## static int def_uid;
450 int status;
451 int client_id;
452 char *client_type;
453
454 /* get query access control list */
455 name = q->shortname;
456## repeat retrieve (acl_id = capacls.list_id) where capacls.tag = @name
cc1231a1 457## inquire_equel (rowcount = "rowcount", errorno = "errorno")
458 if (errorno != 0) return(SMS_INGRES_ERR);
7536027d 459 if (rowcount == 0) return(SMS_PERM);
d26cae4e 460
7536027d 461 /* initialize default uid */
462 if (def_uid == 0) {
463## retrieve (def_uid = users.users_id) where users.login = "default"
d26cae4e 464 }
97479f6f 465
7536027d 466 /* check for default access */
467## range of m is members
468## repeat retrieve (exists = any(m.#member_id where m.list_id = @acl_id and
469## m.member_type = "USER" and m.#member_id = def_uid))
470 if (exists) return(SMS_SUCCESS);
471
472 /* parse client name */
473 status = get_client(cl, &client_type, &client_id);
474 if (status != SMS_SUCCESS) return(status);
475
7536027d 476 /* see if client is in the list (or any of its sub-lists) */
477 exists = find_member(acl_id, client_type, client_id, 0);
478 return ((exists) ? SMS_SUCCESS : SMS_PERM);
479##}
97479f6f 480
7536027d 481get_client(cl, client_type, client_id)
482 client *cl;
483 char **client_type;
484 int *client_id;
485##{
486 struct krbname *krb;
487## int member_id;
488## char *name;
489## int rowcount;
490
19bf23eb 491 /* for now ignore instances */
7536027d 492 krb = &cl->kname;
7536027d 493
494 /* if client is from local realm, get users_id */
495 if (!strcmp(krb->realm, krb_realm)) {
496 name = krb->name;
497## repeat retrieve (member_id = users.users_id) where users.login = @name
498 *client_type = "USER";
499 } else {
500 /* otherwise use string_id */
501 name = cl->clname;
502## repeat retrieve (member_id = strings.string_id)
503## where strings.string = @name
504 *client_type = "STRING";
505 }
506
507 /* make sure we found a users or string id */
d26cae4e 508## inquire_equel (rowcount = "rowcount")
7536027d 509 if (rowcount == 0) return(SMS_PERM);
510
511 *client_id = member_id;
512 return(SMS_SUCCESS);
513##}
97479f6f 514
7536027d 515##find_member(list_id, member_type, member_id, sq)
516## int list_id;
517## char *member_type;
518## int member_id;
519 struct save_queue *sq;
520##{
521## int exists;
522## int sublist;
523 int child;
524 struct save_queue *sq_create();
525
526 /* see if client is a direct member of list */
527## repeat retrieve (exists = any(m.#member_id where
528## m.#list_id = @list_id and
529## m.#member_type = @member_type and
530## m.#member_id = @member_id))
531 if (exists) return(1);
532
533 /* are there any sub-lists? */
7536027d 534## repeat retrieve (exists = any(m.#member_id where m.#list_id = @list_id and
535## m.#member_type = "LIST"))
536 if (!exists) return(0);
537
538 /* yes; now recurse through sublists */
539
540 /* create a save queue */
541 if (sq == (struct save_queue *)0) {
542 sq = sq_create();
543 child = 0;
544 } else {
545 child = 1;
d26cae4e 546 }
97479f6f 547
7536027d 548 /* save all sublist ids */
549## range of m is members
550## retrieve (sublist = m.#member_id)
551## where m.#list_id = list_id and m.#member_type = "LIST"
552## {
553 sq_save_unique_data(sq, sublist);
554## }
555
556 if (child) return;
557
7536027d 558 /* at top-level, check sub-lists for client (breadth-first search) */
559 while (sq_get_data(sq, &sublist)) {
560 exists = find_member(sublist, member_type, member_id, sq);
561 if (exists) {
562 sq_destroy(sq);
563 return(1);
564 }
565 }
d26cae4e 566##}
97479f6f 567
cc1231a1 568do_retrieve(q, pqual, psort, action, actarg)
d26cae4e 569 register struct query *q;
cc1231a1 570 char *pqual;
571 char *psort;
d26cae4e 572 int (*action)();
573 char *actarg;
574##{
575## char *rvar;
576## char *rtable;
577## char *cqual;
cc1231a1 578## char *csort;
d26cae4e 579## int rowcount;
cc1231a1 580## int errorno;
7536027d 581
d26cae4e 582 if (q->rvar) {
583 rvar = q->rvar;
584 rtable = q->rtable;
585## range of rvar is rtable
586 }
97479f6f 587
cc1231a1 588 if (psort) {
589 csort = psort;
590 if (pqual) {
591 cqual = pqual;
592## retrieve unique (param (q->tlist, q->vaddr)) where cqual
593## sort by csort
594## {
595 (*action)(q->vcnt, q->vaddr, actarg);
596## }
597 } else {
598## retrieve unique (param (q->tlist, q->vaddr))
599## sort by csort
600## {
601 (*action)(q->vcnt, q->vaddr, actarg);
602## }
603 }
604
7536027d 605 } else {
cc1231a1 606 if (pqual) {
607 cqual = pqual;
608## retrieve unique (param (q->tlist, q->vaddr)) where cqual
609## {
610 (*action)(q->vcnt, q->vaddr, actarg);
611## }
612 } else {
613## retrieve unique (param (q->tlist, q->vaddr))
614## {
615 (*action)(q->vcnt, q->vaddr, actarg);
616## }
617 }
7536027d 618 }
97479f6f 619
cc1231a1 620## inquire_equel (rowcount = "rowcount", errorno = "errorno")
621 if (errorno != 0) return(SMS_INGRES_ERR);
7536027d 622 return ((rowcount == 0) ? SMS_NO_MATCH : SMS_SUCCESS);
d26cae4e 623##}
97479f6f 624
e38c941b 625do_update(q, argv, qual, action, actarg)
d26cae4e 626 register struct query *q;
627 char *argv[];
628 char *qual;
629 int (*action)();
630 char *actarg;
631##{
632## char *rvar;
633## char *rtable;
634## char *cqual;
635## int rowcount;
cc1231a1 636## int errorno;
97479f6f 637
d26cae4e 638 rvar = q->rvar;
639 rtable = q->rtable;
640## range of rvar is rtable
97479f6f 641
d26cae4e 642 cqual = qual;
643## replace rvar (param (q->tlist, argv))
644## where cqual
97479f6f 645
cc1231a1 646## inquire_equel (errorno = "errorno")
647 if (errorno != 0) return(SMS_INGRES_ERR);
7536027d 648 return(SMS_SUCCESS);
d26cae4e 649##}
97479f6f 650
cc1231a1 651do_append(q, argv, pqual, action, actarg)
d26cae4e 652 register struct query *q;
653 char *argv[];
cc1231a1 654 char *pqual;
d26cae4e 655 int (*action)();
656 char *actarg;
657##{
658## char *rvar;
659## char *rtable;
7536027d 660## char *cqual;
cc1231a1 661## int errorno;
97479f6f 662
d26cae4e 663 rvar = q->rvar;
664 rtable = q->rtable;
665## range of rvar is rtable
97479f6f 666
cc1231a1 667 if (pqual) {
668 cqual = pqual;
7536027d 669## append to rtable (param (q->tlist, argv)) where cqual
670 } else {
671## append to rtable (param (q->tlist, argv))
672 }
97479f6f 673
cc1231a1 674## inquire_equel (errorno = "errorno")
675 if (errorno != 0) return(SMS_INGRES_ERR);
7536027d 676 return(SMS_SUCCESS);
d26cae4e 677##}
97479f6f 678
e38c941b 679do_delete(q, qual, action, actarg)
d26cae4e 680 register struct query *q;
681 char *qual;
682 int (*action)();
683 char *actarg;
684##{
685## char *rvar;
686## char *rtable;
687## char *cqual;
cc1231a1 688## int errorno;
97479f6f 689
d26cae4e 690 rvar = q->rvar;
691 rtable = q->rtable;
692## range of rvar is rtable
97479f6f 693
d26cae4e 694 cqual = qual;
695## delete rvar where cqual
97479f6f 696
cc1231a1 697## inquire_equel (errorno = "errorno")
698 if (errorno != 0) return(SMS_INGRES_ERR);
7536027d 699 return(SMS_SUCCESS);
d26cae4e 700##}
97479f6f 701
d26cae4e 702
703/*
704 * Local Variables:
705 * mode: c
706 * c-indent-level: 4
707 * c-continued-statement-offset: 4
708 * c-brace-offset: -4
709 * c-argdecl-indent: 4
710 * c-label-offset: -4
711 * End:
712 */
713
This page took 0.18806 seconds and 5 git commands to generate.