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