]> andersk Git - moira.git/blob - server/qrtn.qc
added incremental updates; caching of access info
[moira.git] / server / qrtn.qc
1 /*
2  *      $Source$
3  *      $Author$
4  *      $Header$
5  *
6  *      Copyright (C) 1987, 1988 by the Massachusetts Institute of Technology
7  *      For copying and distribution information, please see the file
8  *      <mit-copyright.h>.
9  * 
10  */
11
12 #ifndef lint
13 static char *rcsid_qrtn_qc = "$Header$";
14 #endif lint
15
16 #include <mit-copyright.h>
17 #include "query.h"
18 #include "sms_server.h"
19
20 char *Argv[16];
21
22 int ingres_errno = 0;
23 int sms_errcode = 0;
24 ## int query_timeout = 30;
25 extern char *whoami;
26 extern FILE *journal;
27
28 #define INGRES_BAD_INT 4111
29 #define INGRES_BAD_DATE 4302
30 #define INGRES_DEADLOCK 4700
31 #define INGRES_TIMEOUT 4702
32
33 /*
34  * ingerr: (supposedly) called when Ingres indicates an error.
35  * I have not yet been able to get this to work to intercept a
36  * database open error.
37  */
38
39 static int ingerr(num)
40     int *num;
41 {
42     ingres_errno = *num;
43
44     switch (*num) {
45     case INGRES_BAD_INT:
46         sms_errcode = SMS_INTEGER;
47         break;
48     case INGRES_BAD_DATE:
49         sms_errcode = SMS_DATE;
50         break;
51     case INGRES_DEADLOCK:
52         sms_errcode = SMS_DEADLOCK;
53         com_err(whoami, 0, "INGRES deadlock detected");
54         break;
55     case INGRES_TIMEOUT:
56         sms_errcode = SMS_BUSY;
57         com_err(whoami, 0, "timed out getting lock");
58         break;
59     default:
60         sms_errcode = SMS_INGRES_ERR;
61         com_err(whoami, SMS_INGRES_ERR, " code %d\n", *num);
62         critical_alert("SMS", "SMS server encountered INGRES ERROR %d", *num);
63         return (*num);
64     }
65     return (0);
66 }
67
68 int sms_open_database()
69 {
70     register int i;
71     char *malloc();
72
73     /* initialize local argv */
74     for (i = 0; i < 16; i++)
75         Argv[i] = malloc(ARGLEN);
76     incremental_init();
77
78     IIseterr(ingerr);
79         
80     ingres_errno = 0;
81         
82     /* open the database */
83 ##  ingres sms
84 ##  set lockmode session where level = table, timeout = query_timeout
85 ##  set lockmode on capacls where readlock = shared
86 ##  set lockmode on alias where readlock = shared
87     return ingres_errno;
88 }
89
90 int sms_close_database()
91 {
92 ##  exit
93 }
94
95 sms_check_access(cl, name, argc, argv_ro)
96     client *cl;
97     char *name;
98     int argc;
99     char *argv_ro[];
100 {
101     struct query *q;
102     struct query *get_query_by_name();
103
104     ingres_errno = 0;
105
106     q = get_query_by_name(name, cl->args->sms_version_no);
107     if (q == (struct query *)0)
108         return(SMS_NO_HANDLE);
109
110     return(sms_verify_query(cl, q, argc, argv_ro));
111 }
112
113 sms_process_query(cl, name, argc, argv_ro, action, actarg)
114     client *cl;
115     char *name;
116     int argc;
117     char *argv_ro[];
118     int (*action)();
119     char *actarg;
120 {
121     register struct query *q;
122     register int status;
123     register struct validate *v;
124     char qual[256];
125     char sort[32];
126     char *pqual;
127     char *psort;
128 ##  char *table;
129     struct save_queue *sq;
130     struct query *get_query_by_name();
131     int sq_save_args();
132     struct save_queue *sq_create();
133     char *build_sort();
134
135     ingres_errno = 0;
136
137     /* list queries command */
138     if (!strcmp(name, "_list_queries")) {
139         list_queries(cl->args->sms_version_no, action, actarg);
140         return(SMS_SUCCESS);
141     }
142
143     /* help query command */
144     if (!strcmp(name, "_help")) {
145         if (argc < 1)
146             return(SMS_ARGS);
147         q = get_query_by_name(argv_ro[0], cl->args->sms_version_no);
148         if (q == (struct query *)0) return(SMS_NO_HANDLE);
149         help_query(q, action, actarg);
150         return(SMS_SUCCESS);
151     }
152
153     /* get query structure, return error if named query does not exist */
154     q = get_query_by_name(name, cl->args->sms_version_no);
155     if (q == (struct query *)0) return(SMS_NO_HANDLE);
156     v = q->validate;
157
158     if (q->type != RETRIEVE) {
159 ##      begin transaction
160     }
161
162     /* setup argument vector, verify access and arguments */
163     if ((status = sms_verify_query(cl, q, argc, argv_ro)) != SMS_SUCCESS)
164         goto out;
165
166     /* perform any special query pre-processing */
167     if (v && v->pre_rtn) {
168         status = (*v->pre_rtn)(q, Argv, cl, 0);
169         if (status != SMS_SUCCESS)
170             goto out;
171     }
172
173     switch (q->type) {
174     case RETRIEVE:
175         /* for queries that do not permit wildcarding, check if row
176            uniquely exists */
177         if (v && v->field) {
178             status = validate_row(q, Argv, v);
179             if (status != SMS_EXISTS) break;
180         }
181
182         /* build "where" clause if needed */
183         if (q->qual) {
184             build_qual(q->qual, q->argc, Argv, qual);
185             pqual = qual;
186         } else {
187             pqual = 0;
188         }
189
190         /* build "sort" clause if needed */
191         if (v && v->valobj) {
192             psort = build_sort(v, sort);
193         } else {
194             psort = 0;
195         }
196
197         /* if there is a followup routine, then we must save the results */
198         /* of the first query for use by the followup routine */
199         /* if q->rvar = NULL, perform post_rtn only */
200         if (q->rvar) {
201             if (v && v->post_rtn) {
202                 sq = sq_create();
203                 status = do_retrieve(q, pqual, psort, sq_save_args, sq);
204                 if (status != SMS_SUCCESS) {
205                     sq_destroy(sq);
206                     break;
207                 }
208                 status = (*v->post_rtn)(q, sq, v, action, actarg, cl);
209             } else {
210                 /* normal retrieve */
211                 status = do_retrieve(q, pqual, psort, action, actarg);
212             }
213             if (status != SMS_SUCCESS) break;
214         } else {
215             status = (*v->post_rtn)(q, Argv, cl, action, actarg);
216         }
217
218         break;
219
220     case UPDATE:
221         /* see if row already exists */
222         if (v->field) {
223             status = validate_row(q, Argv, v);
224             if (status != SMS_EXISTS) break;
225         }
226
227         /* build "where" clause and perform update */
228         /* if q->rvar = NULL, perform post_rtn only */
229         if (q->rvar) {
230             build_qual(q->qual, q->argc, Argv, qual);
231             incremental_before(q->rtable, qual, argv_ro);
232             status = do_update(q, &Argv[q->argc], qual, action, actarg);
233             incremental_after(q->rtable, qual, argv_ro);
234             if (status != SMS_SUCCESS) break;
235             table = q->rtable;
236             if (strcmp(q->shortname, "sshi") && strcmp(q->shortname, "ssif")) {
237 ##              repeat replace tblstats (updates = tblstats.updates + 1,
238 ##                                       modtime = "now")
239 ##                  where tblstats.#table = @table
240             }
241         }
242
243         /* execute followup routine (if any) */
244         if (v->post_rtn) status = (*v->post_rtn)(q, Argv, cl);
245
246         break;
247
248     case APPEND:
249         /* see if row already exists */
250         if (v->field) {
251             status = validate_row(q, Argv, v);
252             if (status != SMS_NO_MATCH) break;
253         }
254
255         /* increment id number if necessary */
256         if (v->object_id) {
257             status = set_next_object_id(v->object_id, q->rtable);
258             if (status != SMS_SUCCESS) break;
259         }
260
261         /* build "where" clause if needed */
262         if (q->qual) {
263             build_qual(q->qual, q->argc, Argv, qual);
264             pqual = qual;
265         } else {
266             pqual = 0;
267         }
268
269         /* perform the append */
270         /* if q->rvar = NULL, perform post_rtn only */
271         if (q->rvar) {
272             incremental_clear_before();
273             status = do_append(q, &Argv[q->argc], pqual, action, actarg);
274             if (status != SMS_SUCCESS) break;
275             if (v && v->object_id) {
276                 sprintf(qual, "%s.%s = values.value and values.name = \"%s\"",
277                         q->rvar, v->object_id, v->object_id);
278                 incremental_after(q->rtable, qual, argv_ro);
279             } else
280               incremental_after(q->rtable, pqual, argv_ro);
281
282             table = q->rtable;
283 ##          repeat replace tblstats (appends = tblstats.appends + 1,
284 ##                                   modtime = "now")
285 ##              where tblstats.#table = @table
286         }
287         
288         /* execute followup routine */
289         if (v->post_rtn) status = (*v->post_rtn)(q, Argv, cl);
290         break;
291
292     case DELETE:
293         /* see if row already exists */
294         if (v->field) {
295             status = validate_row(q, Argv, v);
296             if (status != SMS_EXISTS) break;
297         }
298
299         /* build "where" clause and perform delete */
300         /* if q->rvar = NULL, perform post_rtn only */
301         if (q->rvar) {
302             build_qual(q->qual, q->argc, Argv, qual);
303             incremental_before(q->rtable, qual, argv_ro);
304             status = do_delete(q, qual, action, actarg);
305             incremental_clear_after();
306             if (status != SMS_SUCCESS) break;
307             table = q->rtable;
308 ##          repeat replace tblstats (deletes = tblstats.deletes + 1,
309 ##                                   modtime = "now")
310 ##              where tblstats.#table = @table
311         }
312
313         /* execute followup routine */
314         if (v->post_rtn) status = (*v->post_rtn)(q, Argv, cl);
315         break;
316
317     }
318
319 out:
320     if (q->type != RETRIEVE) {
321         if (status == SMS_SUCCESS) {
322 ##          end transaction     /* commit to this */
323             if (journal) {
324                 char buf[1024], *bp;
325                 int i;
326                 extern time_t now;
327
328                 fprintf(journal, "%% %s %s %s",
329                         cl->clname, cl->entity, ctime(&now));
330                 fprintf(journal, "%s[%d] ", q->name, cl->args->sms_version_no);
331                 for (i = 0; i < argc; i++) {
332                     if (i != 0) {
333                         putc(' ', journal);
334                     }
335                     requote(buf, argv_ro[i], sizeof(buf));
336                     fputs(buf, journal);
337                 }
338                 putc('\n', journal);
339                 fflush(journal);
340             }
341             incremental_update();
342         } else {
343             if (ingres_errno != INGRES_DEADLOCK) {
344 ##              abort           /* it never happened */
345             }
346             incremental_flush();
347         }
348 ##      set lockmode session where readlock = system
349     }
350
351     if (status == SMS_SUCCESS && ingres_errno != 0) {
352         critical_alert("SMS", "Server didn't notice INGRES ERROR %d",
353                        ingres_errno);
354         status = SMS_INTERNAL;
355     }
356
357     if (status != SMS_SUCCESS && log_flags & LOG_RES)
358         com_err(whoami, status, " (Query failed)");
359     return(status);
360 }
361
362 build_qual(fmt, argc, argv, qual)
363         char *fmt;
364         int argc;
365         char *argv[];
366         char *qual;
367 {
368     register char *c;
369     register int i;
370     char *args[4];
371     char *index();
372
373     c = fmt;
374     for (i = 0; i < argc; i++) {
375         c = index(c, '%');
376         if (c++ == (char *)0) return(SMS_ARGS);
377         if (*c == 's')
378             args[i] = argv[i];
379         else if (*c == 'd')
380             *(int *)&args[i] = *(int *)argv[i]; /* sigh */
381         else
382             return(SMS_INGRES_ERR);
383     }
384
385     switch (argc) {
386     case 0:
387         strcpy(qual, fmt);
388         break;
389
390     case 1:
391         sprintf(qual, fmt, args[0]);
392         break;
393
394     case 2:
395         sprintf(qual, fmt, args[0], args[1]);
396         break;
397
398     case 3:
399         sprintf(qual, fmt, args[0], args[1], args[2]);
400         break;
401
402     case 4:
403         sprintf(qual, fmt, args[0], args[1], args[2], args[3]);
404         break;
405     }
406     return(SMS_SUCCESS);
407 }
408
409 char *
410 build_sort(v, sort)
411     register struct validate *v;
412     char *sort;
413 {
414     register struct valobj *vo;
415     register int n;
416     char elem[16];
417
418     n = v->objcnt;
419     vo = v->valobj;
420     *sort = 0;
421
422     while (--n >= 0) {
423         if (vo->type == V_SORT) {
424             sprintf(elem, "RET_VAR%d", vo->index + 1);
425             if (*sort) strcat(sort, ", ");
426             strcat(sort, elem);
427         }
428         vo++;
429     }
430
431     return ((*sort) ? sort : 0);
432 }
433
434
435 /* Build arguement vector, verify query and arguments */
436
437 sms_verify_query(cl, q, argc, argv_ro)
438     client *cl;
439     struct query *q;
440     int argc;
441     char *argv_ro[];
442 {
443     register int argreq;
444     register int status;
445     register struct validate *v = q->validate;
446     register int i;
447     register int privileged = 0;
448     int len;
449
450     /* copy the arguments into a local argv that we can modify */
451     if (argc >= QMAXARGS)
452       return(SMS_ARGS);
453     for (i = 0; i < argc; i++) {
454         if ((len = strlen(argv_ro[i])) < ARGLEN)
455             strcpy(Argv[i], argv_ro[i]);
456         else
457             return(SMS_ARG_TOO_LONG);
458         if (Argv[i][len-1] == '\\')
459           return(SMS_BAD_CHAR);
460     }
461
462     /* check initial query access */
463     status = check_query_access(q, Argv, cl);
464     if (status != SMS_SUCCESS && status != SMS_PERM)
465         return(status);
466     if (status == SMS_SUCCESS)
467         privileged++;
468
469     /* check argument count */
470     argreq = q->argc;
471     if (q->type == UPDATE || q->type == APPEND) argreq += q->vcnt;
472     if (argc != argreq) return(SMS_ARGS);
473
474     /* validate arguments */
475     if (v && v->valobj) {
476         status = validate_fields(q, Argv, v->valobj, v->objcnt);
477         if (status != SMS_SUCCESS) return(status);
478     }
479
480     /* perform special query access check */
481     if (!privileged && v && v->acs_rtn) {
482         status = (*v->acs_rtn)(q, Argv, cl);
483         if (status != SMS_SUCCESS && status != SMS_PERM)
484             return(status);
485         if (status == SMS_SUCCESS)
486             privileged++;
487     }
488
489     return(privileged ? SMS_SUCCESS : SMS_PERM);
490 }
491
492
493 /* This routine caches info from the database.  Each query acl is stored
494  * in the query structure, and whether that acl contains everybody.
495  */
496
497 check_query_access(q, argv, cl)
498     struct query *q;
499     char *argv[];
500     client *cl;
501 ##{
502 ##  char *name;
503 ##  int acl_id;
504 ##  int exists;
505 ##  int rowcount;
506 ##  int errorno;
507 ##  static int def_uid;
508     int status;
509     int client_id;
510     char *client_type;
511
512     /* initialize default uid */
513     if (def_uid == 0) {
514 ##      retrieve (def_uid = users.users_id) where users.login = "default"
515     }
516
517     /* get query access control list */
518     if (q->acl != 0)
519       acl_id = q->acl;
520     else {
521         name = q->shortname;
522 ##      repeat retrieve (acl_id = capacls.list_id) where capacls.tag = @name
523 ##      inquire_equel (rowcount = "rowcount", errorno = "errorno")
524         if (errorno != 0) return(SMS_INGRES_ERR);
525         if (rowcount == 0) return(SMS_PERM);
526         q->acl = acl_id;
527
528         /* check for default access */
529 ##      repeat retrieve (exists = any(imembers.#member_id where
530 ##                                    imembers.list_id = @acl_id and
531 ##                                    imembers.member_type = "USER" and
532 ##                                    imembers.#member_id = def_uid))
533         q->everybody = exists;
534     }
535
536     if (q->everybody)
537       return(SMS_SUCCESS);
538
539     if (client_is_member(cl, acl_id))
540       return(SMS_SUCCESS);
541     else
542       return(SMS_PERM);
543 ##}
544
545
546 /* If this client has cached list information, use that.  Otherwise, 
547  * use the general get_client & find_member routines to determine if
548  * the user is a member of the list.
549  */
550
551 int client_is_member(cl, id)
552 client *cl;
553 int id;
554 {
555     char *client_type;
556     int client_id, status;
557
558     if (cl->lists[0]) {
559         register int i;
560         for (i = 0; cl->lists[i] && i < NLISTS; i++)
561           if (cl->lists[i] == id)
562             return(1);
563         return(0);
564     }
565
566     /* parse client name */
567     if (get_client(cl, &client_type, &client_id) != SMS_SUCCESS)
568       return(0);
569
570     /* see if client is in the list (or any of its sub-lists) */
571     return(find_member("LIST", id, client_type, client_id, 0));
572 }
573
574
575 get_client(cl, client_type, client_id)
576     client *cl;
577     char **client_type;
578     int *client_id;
579 {
580     if (cl->users_id > 0) {
581         *client_id = cl->users_id;
582         *client_type = "USER";
583         return(SMS_SUCCESS);
584     }
585
586     if (cl->client_id < 0) {
587         *client_id = -cl->users_id;
588         *client_type = "KERBEROS";
589         return(SMS_SUCCESS);
590     }
591
592     return(SMS_PERM);
593 }
594
595 ##find_member(list_type, list_id, member_type, member_id)
596     char *list_type;
597 ##  int list_id;
598 ##  char *member_type;
599 ##  int member_id;
600 ##{
601 ##  int exists, errorno;
602
603     if (!strcmp(strtrim(list_type), strtrim(member_type)) &&
604         list_id == member_id)
605         return(1);
606
607     /* see if client is a direct member of list */
608 ##  repeat retrieve (exists = any(imembers.#member_id where 
609 ##                                imembers.#list_id = @list_id and
610 ##                                imembers.#member_type = @member_type and 
611 ##                                imembers.#member_id = @member_id))
612 ##  inquire_equel(errorno = "errorno")
613     if (errorno == 0)
614       return(exists);
615     else
616       return(0);
617 ##}
618
619
620 do_retrieve(q, pqual, psort, action, actarg)
621     register struct query *q;
622     char *pqual;
623     char *psort;
624     int (*action)();
625     char *actarg;
626 ##{
627 ##  char *rvar;
628 ##  char *rtable;
629 ##  char *cqual;
630 ##  char *csort;
631 ##  int rowcount;
632 ##  int errorno;
633     static char **vaddrs = (char **)NULL;
634
635     if (!vaddrs) {
636         register int i;
637
638         if ((vaddrs = (char **)malloc(sizeof(char *) * QMAXARGS)) == NULL) {
639             com_err(whoami, SMS_NO_MEM, "setting up static argv");
640             exit(1);
641         }
642         for (i = 0; i < QMAXARGS; i++) {
643             if ((vaddrs[i] = malloc(QMAXARGSIZE)) == NULL) {
644                 com_err(whoami, SMS_NO_MEM, "setting up static argv");
645                 exit(1);
646             }
647         }
648     }
649
650     if (q->rvar) {
651         rvar = q->rvar;
652         rtable = q->rtable;
653 ##      range of rvar is rtable
654     }
655
656     if (psort) {
657         csort = psort;
658         if (pqual) {
659             cqual = pqual;
660 ##          retrieve unique (param (q->tlist, vaddrs)) where cqual
661 ##                   sort by csort
662 ##          {
663                  (*action)(q->vcnt, vaddrs, actarg);
664 ##          }
665         } else {
666 ##          retrieve unique (param (q->tlist, vaddrs))
667 ##                   sort by csort
668 ##          {
669                  (*action)(q->vcnt, vaddrs, actarg);
670 ##          }
671         }
672
673     } else {
674         if (pqual) {
675             cqual = pqual;
676 ##          retrieve unique (param (q->tlist, vaddrs)) where cqual
677 ##          {
678                  (*action)(q->vcnt, vaddrs, actarg);
679 ##          }
680         } else {
681 ##          retrieve unique (param (q->tlist, vaddrs))
682 ##          {
683                  (*action)(q->vcnt, vaddrs, actarg);
684 ##          }
685         }
686     }
687
688 ##  inquire_equel (rowcount = "rowcount", errorno = "errorno")
689     if (errorno != 0) return(SMS_INGRES_ERR);
690     return ((rowcount == 0) ? SMS_NO_MATCH : SMS_SUCCESS);
691 ##}
692
693 do_update(q, argv, qual, action, actarg)
694     register struct query *q;
695     char *argv[];
696     char *qual;
697     int (*action)();
698     char *actarg;
699 ##{
700 ##  char *rvar;
701 ##  char *rtable;
702 ##  char *cqual;
703 ##  int errorno;
704       
705     rvar = q->rvar;
706     rtable = q->rtable;
707 ##  range of rvar is rtable
708
709     cqual = qual;
710 ##  replace rvar (param (q->tlist, argv))
711 ##  where cqual
712
713 ##  inquire_equel (errorno = "errorno")
714     if (errorno == INGRES_BAD_INT)
715         return(SMS_INTEGER);
716     else if (errorno != 0)
717         return(SMS_INGRES_ERR);
718     return(SMS_SUCCESS);
719 ##}
720
721 do_append(q, argv, pqual, action, actarg)
722     register struct query *q;
723     char *argv[];
724     char *pqual;
725     int (*action)();
726     char *actarg;
727 ##{
728 ##  char *rvar;
729 ##  char *rtable;
730 ##  char *cqual;
731 ##  int errorno;
732
733     rvar = q->rvar;
734     rtable = q->rtable;
735 ##  range of rvar is rtable
736
737     if (pqual) {
738         cqual = pqual;
739 ##      append to rtable (param (q->tlist, argv)) where cqual
740     } else {
741 ##      append to rtable (param (q->tlist, argv))
742     }
743
744 ##  inquire_equel (errorno = "errorno")
745     if (errorno == INGRES_BAD_INT)
746         return(SMS_INTEGER);
747     else if (errorno != 0)
748         return(SMS_INGRES_ERR);
749     return(SMS_SUCCESS);
750 ##}
751
752 do_delete(q, qual, action, actarg)
753     register struct query *q;
754     char *qual;
755     int (*action)();
756     char *actarg;
757 ##{
758 ##  char *rvar;
759 ##  char *rtable;
760 ##  char *cqual;
761 ##  int errorno;
762
763     rvar = q->rvar;
764     rtable = q->rtable;
765 ##  range of rvar is rtable
766
767     cqual = qual;
768 ##  delete rvar where cqual
769
770 ##  inquire_equel (errorno = "errorno")
771     if (errorno != 0) return(SMS_INGRES_ERR);
772     return(SMS_SUCCESS);
773 ##}
774
775
776 /**
777  ** set_next_object_id - set next object id in values table
778  **
779  ** Inputs: object - object name in values table and in objects
780  **         table - name of table objects are found in
781  **
782  ** - called before an APPEND operation to set the next object id to
783  **   be used for the new record to the next free value
784  **
785  **/
786
787 set_next_object_id(object, table)
788     char *object;
789     char *table;
790 ##{
791 ##  char *name, *tbl;
792 ##  int rowcount, exists, value;
793
794     name = object;
795     tbl = table;
796 ##  range of v is values
797 ##  repeat retrieve (value = v.#value) where v.#name = @name
798 ##  inquire_equel(rowcount = "rowcount")
799     if (rowcount != 1)
800         return(SMS_NO_ID);
801
802 ##  retrieve (exists = any(tbl.name where tbl.name = value))
803 ##  inquire_equel(rowcount = "rowcount")
804     if (rowcount != 1)
805         return(SMS_NO_ID);
806     while (exists) {
807         value++;
808         if (value > MAX_ID_VALUE)
809             value = MIN_ID_VALUE;
810 ##      retrieve (exists = any(tbl.name where tbl.name = value))
811     }
812
813     if (LOG_RES)
814         com_err(whoami, 0, "setting ID %s to %d", name, value);
815 ##  repeat replace v (#value = @value) where v.#name = @name
816     return(SMS_SUCCESS);
817 ##}
818
819
820 /* This looks up a login name and returns the SMS internal ID.  It is used
821  * by authenticate to put the users_id in the client structure.
822  */
823
824 int get_users_id(name)
825 char *name;
826 ##{
827 ##  int id, rowcount;
828 ##  char *login;
829
830     login = name;
831
832 ##  range of u is users
833 ##  repeat retrieve (id = u.#users_id) where u.#login = @login
834 ##  inquire_equel (rowcount = "rowcount")
835     
836     if (rowcount == 1)
837         return(id);
838     else
839         return(0);
840 ##}
841
842
843 /* Turn a kerberos name into the user's ID of the account that principal
844  * owns.  Sets the kerberos ID and user ID.
845  */
846
847 set_krb_mapping(name, login, ok, kid, uid)
848 char *name;
849 char *login;
850 int ok;
851 int *kid;
852 int *uid;
853 ##{
854 ##  int u_id, k_id, rowcount;
855 ##  char *krbname;
856
857     krbname = name;
858     *kid = 0;
859     *uid = 0;
860
861 ##  range of k is krbmap
862 ##  range of s is strings
863 ##  repeat retrieve (u_id = k.#users_id, k_id = k.#string_id)
864 ##      where k.string_id = s.string_id and s.string = @krbname
865 ##  inquire_equel (rowcount = "rowcount")
866     
867     if (rowcount == 1) {
868         *kid = -k_id;
869         *uid = u_id;
870         return;
871     }
872
873 ##  repeat retrieve (k_id = s.#string_id) where s.string = @krbname
874 ##  inquire_equel (rowcount = "rowcount")
875
876     if (rowcount == 1) {
877         *kid = -k_id;
878     }
879
880     if (!ok) {
881         *uid = *kid;
882         return;
883     }
884
885     *uid = get_users_id(login);
886     if (*kid == 0)
887       *kid = *uid;
888 ##}
889
890
891 /* Cache the lists that the client is a member of.  These will be used
892  * to speed up access checking later.
893  */
894
895 set_client_lists(cl)
896 client *cl;
897 ##{
898 ##  int lid, mid;
899 ##  char *type;
900     int count = 0;
901
902     cl->lists[count] = 0;
903     if (cl->users_id != 0) {
904         type = "USER";
905         mid = cl->users_id;
906     } else if (cl->client_id != 0) {
907         type = "KERBEROS";
908         mid = -cl->client_id;
909     } else
910       return;
911
912 ##  range of m is members
913 ##  repeat retrieve (lid = m.list_id) where m.member_type = @type and 
914 ##      m.member_id = @mid {
915             cl->lists[count++] = lid;
916             if (count >= NLISTS)
917 ##            endretrieve
918 ##  }
919     if (count >= NLISTS) {
920         cl->lists[0] = 0;
921         com_err(whoami, 0, "too many lists to cache");
922     } else
923       cl->lists[count] = 0;
924 ##}
925
926
927 /* For now this just checks the argc's.  It should also see that there
928  * are no duplicate names.
929  */
930
931 sanity_check_queries()
932 {
933     register int i;
934     int maxv = 0, maxa = 0;
935 #ifdef MULTIPROTOCOLS
936     extern int QueryCount1, QueryCount2;
937     extern struct query Queries1[], Queries2[];
938 #else
939     extern int QueryCount2;
940     extern struct query Queries2[];
941 #endif MULTIPROTOCOLS
942
943 #define MAX(x,y) ((x) > (y) ? (x) : (y))
944
945 #ifdef MULTIPROTOCOLS
946     for (i = 0; i < QueryCount1; i++) {
947         maxv = MAX(maxv, Queries1[i].vcnt);
948         maxa = MAX(maxa, Queries1[i].argc);
949     }
950 #endif MULTIPROTOCOLS
951     for (i = 0; i < QueryCount2; i++) {
952         maxv = MAX(maxv, Queries2[i].vcnt);
953         maxa = MAX(maxa, Queries2[i].argc);
954     }
955     if (MAX(maxv, maxa) > QMAXARGS) {
956         com_err(whoami, 0, "A query has more args than QMAXARGS");
957         exit(1);
958     }
959 }
This page took 0.107897 seconds and 5 git commands to generate.