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