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