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