]> andersk Git - moira.git/blob - server/qrtn.qc
fix for incremental updates
[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, *rvar;
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             table = q->rtable;
304             rvar = q->rvar;
305 ##          range of rvar is table
306             incremental_before(q->rtable, qual, argv_ro);
307             status = do_delete(q, qual, action, actarg);
308             incremental_clear_after();
309             if (status != SMS_SUCCESS) break;
310 ##          repeat replace tblstats (deletes = tblstats.deletes + 1,
311 ##                                   modtime = "now")
312 ##              where tblstats.#table = @table
313         }
314
315         /* execute followup routine */
316         if (v->post_rtn) status = (*v->post_rtn)(q, Argv, cl);
317         break;
318
319     }
320
321 out:
322     if (status == SMS_SUCCESS && ingres_errno != 0) {
323         com_err(whoami, SMS_INTERNAL, "Server didn't notice INGRES ERROR %d",
324                        ingres_errno);
325         status = sms_errcode;
326     }
327
328     if (q->type != RETRIEVE) {
329         if (status == SMS_SUCCESS) {
330 ##          end transaction     /* commit to this */
331             if (journal) {
332                 char buf[1024], *bp;
333                 int i;
334                 extern time_t now;
335
336                 fprintf(journal, "%% %s %s %s",
337                         cl->clname, cl->entity, ctime(&now));
338                 fprintf(journal, "%s[%d] ", q->name, cl->args->sms_version_no);
339                 for (i = 0; i < argc; i++) {
340                     if (i != 0) {
341                         putc(' ', journal);
342                     }
343                     requote(buf, argv_ro[i], sizeof(buf));
344                     fputs(buf, journal);
345                 }
346                 putc('\n', journal);
347                 fflush(journal);
348             }
349             incremental_update();
350         } else {
351             if (ingres_errno != INGRES_DEADLOCK) {
352 ##              abort           /* it never happened */
353             }
354             incremental_flush();
355         }
356 ##      set lockmode session where readlock = system
357     }
358
359     if (status != SMS_SUCCESS && log_flags & LOG_RES)
360         com_err(whoami, status, " (Query failed)");
361     return(status);
362 }
363
364 build_qual(fmt, argc, argv, qual)
365         char *fmt;
366         int argc;
367         char *argv[];
368         char *qual;
369 {
370     register char *c;
371     register int i;
372     char *args[4];
373     char *index();
374
375     c = fmt;
376     for (i = 0; i < argc; i++) {
377         c = 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
387     switch (argc) {
388     case 0:
389         strcpy(qual, fmt);
390         break;
391
392     case 1:
393         sprintf(qual, fmt, args[0]);
394         break;
395
396     case 2:
397         sprintf(qual, fmt, args[0], args[1]);
398         break;
399
400     case 3:
401         sprintf(qual, fmt, args[0], args[1], args[2]);
402         break;
403
404     case 4:
405         sprintf(qual, fmt, args[0], args[1], args[2], args[3]);
406         break;
407     }
408     return(SMS_SUCCESS);
409 }
410
411 char *
412 build_sort(v, sort)
413     register struct validate *v;
414     char *sort;
415 {
416     register struct valobj *vo;
417     register int n;
418     char elem[16];
419
420     n = v->objcnt;
421     vo = v->valobj;
422     *sort = 0;
423
424     while (--n >= 0) {
425         if (vo->type == V_SORT) {
426             sprintf(elem, "RET_VAR%d", vo->index + 1);
427             if (*sort) strcat(sort, ", ");
428             strcat(sort, elem);
429         }
430         vo++;
431     }
432
433     return ((*sort) ? sort : 0);
434 }
435
436
437 /* Build arguement vector, verify query and arguments */
438
439 sms_verify_query(cl, q, argc, argv_ro)
440     client *cl;
441     struct query *q;
442     int argc;
443     char *argv_ro[];
444 {
445     register int argreq;
446     register int status;
447     register struct validate *v = q->validate;
448     register int i;
449     register int privileged = 0;
450     int len;
451
452     /* copy the arguments into a local argv that we can modify */
453     if (argc >= QMAXARGS)
454       return(SMS_ARGS);
455     for (i = 0; i < argc; i++) {
456         if ((len = strlen(argv_ro[i])) < ARGLEN)
457             strcpy(Argv[i], argv_ro[i]);
458         else
459             return(SMS_ARG_TOO_LONG);
460         if (Argv[i][len-1] == '\\')
461           return(SMS_BAD_CHAR);
462     }
463
464     /* check initial query access */
465     status = check_query_access(q, Argv, cl);
466     if (status != SMS_SUCCESS && status != SMS_PERM)
467         return(status);
468     if (status == SMS_SUCCESS)
469         privileged++;
470
471     /* check argument count */
472     argreq = q->argc;
473     if (q->type == UPDATE || q->type == APPEND) argreq += q->vcnt;
474     if (argc != argreq) return(SMS_ARGS);
475
476     /* validate arguments */
477     if (v && v->valobj) {
478         status = validate_fields(q, Argv, v->valobj, v->objcnt);
479         if (status != SMS_SUCCESS) return(status);
480     }
481
482     /* perform special query access check */
483     if (!privileged && v && v->acs_rtn) {
484         status = (*v->acs_rtn)(q, Argv, cl);
485         if (status != SMS_SUCCESS && status != SMS_PERM)
486             return(status);
487         if (status == SMS_SUCCESS)
488             privileged++;
489     }
490
491     return(privileged ? SMS_SUCCESS : SMS_PERM);
492 }
493
494
495 /* This routine caches info from the database.  Each query acl is stored
496  * in the query structure, and whether that acl contains everybody.
497  */
498
499 check_query_access(q, argv, cl)
500     struct query *q;
501     char *argv[];
502     client *cl;
503 ##{
504 ##  char *name;
505 ##  int acl_id;
506 ##  int exists;
507 ##  int rowcount;
508 ##  int errorno;
509 ##  static int def_uid;
510     int status;
511     int client_id;
512     char *client_type;
513
514     /* initialize default uid */
515     if (def_uid == 0) {
516 ##      retrieve (def_uid = users.users_id) where users.login = "default"
517     }
518
519     /* get query access control list */
520     if (q->acl != 0)
521       acl_id = q->acl;
522     else {
523         name = q->shortname;
524 ##      repeat retrieve (acl_id = capacls.list_id) where capacls.tag = @name
525 ##      inquire_equel (rowcount = "rowcount", errorno = "errorno")
526         if (errorno != 0) return(SMS_INGRES_ERR);
527         if (rowcount == 0) return(SMS_PERM);
528         q->acl = acl_id;
529
530         /* check for default access */
531 ##      repeat retrieve (exists = any(imembers.#member_id where
532 ##                                    imembers.list_id = @acl_id and
533 ##                                    imembers.member_type = "USER" and
534 ##                                    imembers.#member_id = def_uid))
535         q->everybody = exists;
536     }
537
538     if (q->everybody)
539       return(SMS_SUCCESS);
540
541     if (get_client(cl, &client_type, &client_id) != SMS_SUCCESS)
542       return(SMS_PERM);
543     if (find_member("LIST", acl_id, client_type, client_id, 0))
544       return(SMS_SUCCESS);
545     else
546       return(SMS_PERM);
547 ##}
548
549
550 get_client(cl, client_type, client_id)
551     client *cl;
552     char **client_type;
553     int *client_id;
554 {
555     if (cl->users_id > 0) {
556         *client_id = cl->users_id;
557         *client_type = "USER";
558         return(SMS_SUCCESS);
559     }
560
561     if (cl->client_id < 0) {
562         *client_id = -cl->users_id;
563         *client_type = "KERBEROS";
564         return(SMS_SUCCESS);
565     }
566
567     return(SMS_PERM);
568 }
569
570 ##find_member(list_type, list_id, member_type, member_id)
571     char *list_type;
572 ##  int list_id;
573 ##  char *member_type;
574 ##  int member_id;
575 ##{
576 ##  int exists, errorno;
577
578     if (!strcmp(strtrim(list_type), strtrim(member_type)) &&
579         list_id == member_id)
580         return(1);
581
582     /* see if client is a direct member of list */
583 ##  repeat retrieve (exists = any(imembers.#member_id where 
584 ##                                imembers.#list_id = @list_id and
585 ##                                imembers.#member_type = @member_type and 
586 ##                                imembers.#member_id = @member_id))
587 ##  inquire_equel(errorno = "errorno")
588     if (errorno == 0)
589       return(exists);
590     else
591       return(0);
592 ##}
593
594
595 do_retrieve(q, pqual, psort, action, actarg)
596     register struct query *q;
597     char *pqual;
598     char *psort;
599     int (*action)();
600     char *actarg;
601 ##{
602 ##  char *rvar;
603 ##  char *rtable;
604 ##  char *cqual;
605 ##  char *csort;
606 ##  int rowcount;
607 ##  int errorno;
608     static char **vaddrs = (char **)NULL;
609
610     if (!vaddrs) {
611         register int i;
612
613         if ((vaddrs = (char **)malloc(sizeof(char *) * QMAXARGS)) == NULL) {
614             com_err(whoami, SMS_NO_MEM, "setting up static argv");
615             exit(1);
616         }
617         for (i = 0; i < QMAXARGS; i++) {
618             if ((vaddrs[i] = malloc(QMAXARGSIZE)) == NULL) {
619                 com_err(whoami, SMS_NO_MEM, "setting up static argv");
620                 exit(1);
621             }
622         }
623     }
624
625     if (q->rvar) {
626         rvar = q->rvar;
627         rtable = q->rtable;
628 ##      range of rvar is rtable
629     }
630
631     if (psort) {
632         csort = psort;
633         if (pqual) {
634             cqual = pqual;
635 ##          retrieve unique (param (q->tlist, vaddrs)) where cqual
636 ##                   sort by csort
637 ##          {
638                  (*action)(q->vcnt, vaddrs, actarg);
639 ##          }
640         } else {
641 ##          retrieve unique (param (q->tlist, vaddrs))
642 ##                   sort by csort
643 ##          {
644                  (*action)(q->vcnt, vaddrs, actarg);
645 ##          }
646         }
647
648     } else {
649         if (pqual) {
650             cqual = pqual;
651 ##          retrieve unique (param (q->tlist, vaddrs)) where cqual
652 ##          {
653                  (*action)(q->vcnt, vaddrs, actarg);
654 ##          }
655         } else {
656 ##          retrieve unique (param (q->tlist, vaddrs))
657 ##          {
658                  (*action)(q->vcnt, vaddrs, actarg);
659 ##          }
660         }
661     }
662
663 ##  inquire_equel (rowcount = "rowcount", errorno = "errorno")
664     if (errorno != 0) return(SMS_INGRES_ERR);
665     return ((rowcount == 0) ? SMS_NO_MATCH : SMS_SUCCESS);
666 ##}
667
668 do_update(q, argv, qual, action, actarg)
669     register struct query *q;
670     char *argv[];
671     char *qual;
672     int (*action)();
673     char *actarg;
674 ##{
675 ##  char *rvar;
676 ##  char *rtable;
677 ##  char *cqual;
678 ##  int errorno;
679       
680     rvar = q->rvar;
681     rtable = q->rtable;
682 ##  range of rvar is rtable
683
684     cqual = qual;
685 ##  replace rvar (param (q->tlist, argv))
686 ##  where cqual
687
688 ##  inquire_equel (errorno = "errorno")
689     if (errorno == INGRES_BAD_INT)
690         return(SMS_INTEGER);
691     else if (errorno != 0)
692         return(SMS_INGRES_ERR);
693     return(SMS_SUCCESS);
694 ##}
695
696 do_append(q, argv, pqual, action, actarg)
697     register struct query *q;
698     char *argv[];
699     char *pqual;
700     int (*action)();
701     char *actarg;
702 ##{
703 ##  char *rvar;
704 ##  char *rtable;
705 ##  char *cqual;
706 ##  int errorno;
707
708     rvar = q->rvar;
709     rtable = q->rtable;
710 ##  range of rvar is rtable
711
712     if (pqual) {
713         cqual = pqual;
714 ##      append to rtable (param (q->tlist, argv)) where cqual
715     } else {
716 ##      append to rtable (param (q->tlist, argv))
717     }
718
719 ##  inquire_equel (errorno = "errorno")
720     if (errorno == INGRES_BAD_INT)
721         return(SMS_INTEGER);
722     else if (errorno != 0)
723         return(SMS_INGRES_ERR);
724     return(SMS_SUCCESS);
725 ##}
726
727 do_delete(q, qual, action, actarg)
728     register struct query *q;
729     char *qual;
730     int (*action)();
731     char *actarg;
732 ##{
733 ##  char *rvar;
734 ##  char *rtable;
735 ##  char *cqual;
736 ##  int errorno;
737
738     rvar = q->rvar;
739     rtable = q->rtable;
740 ##  range of rvar is rtable
741
742     cqual = qual;
743 ##  delete rvar where cqual
744
745 ##  inquire_equel (errorno = "errorno")
746     if (errorno != 0) return(SMS_INGRES_ERR);
747     return(SMS_SUCCESS);
748 ##}
749
750
751 /**
752  ** set_next_object_id - set next object id in values table
753  **
754  ** Inputs: object - object name in values table and in objects
755  **         table - name of table objects are found in
756  **
757  ** - called before an APPEND operation to set the next object id to
758  **   be used for the new record to the next free value
759  **
760  **/
761
762 set_next_object_id(object, table)
763     char *object;
764     char *table;
765 ##{
766 ##  char *name, *tbl;
767 ##  int rowcount, exists, value;
768
769     name = object;
770     tbl = table;
771 ##  range of v is values
772 ##  repeat retrieve (value = v.#value) where v.#name = @name
773 ##  inquire_equel(rowcount = "rowcount")
774     if (rowcount != 1)
775         return(SMS_NO_ID);
776
777 ##  retrieve (exists = any(tbl.name where tbl.name = value))
778 ##  inquire_equel(rowcount = "rowcount")
779     if (rowcount != 1)
780         return(SMS_NO_ID);
781     while (exists) {
782         value++;
783         if (value > MAX_ID_VALUE)
784             value = MIN_ID_VALUE;
785 ##      retrieve (exists = any(tbl.name where tbl.name = value))
786     }
787
788     if (LOG_RES)
789         com_err(whoami, 0, "setting ID %s to %d", name, value);
790 ##  repeat replace v (#value = @value) where v.#name = @name
791     return(SMS_SUCCESS);
792 ##}
793
794
795 /* This looks up a login name and returns the SMS internal ID.  It is used
796  * by authenticate to put the users_id in the client structure.
797  */
798
799 int get_users_id(name)
800 char *name;
801 ##{
802 ##  int id, rowcount;
803 ##  char *login;
804
805     login = name;
806
807 ##  range of u is users
808 ##  repeat retrieve (id = u.#users_id) where u.#login = @login
809 ##  inquire_equel (rowcount = "rowcount")
810     
811     if (rowcount == 1)
812         return(id);
813     else
814         return(0);
815 ##}
816
817
818 /* Turn a kerberos name into the user's ID of the account that principal
819  * owns.  Sets the kerberos ID and user ID.
820  */
821
822 set_krb_mapping(name, login, ok, kid, uid)
823 char *name;
824 char *login;
825 int ok;
826 int *kid;
827 int *uid;
828 ##{
829 ##  int u_id, k_id, rowcount;
830 ##  char *krbname;
831
832     krbname = name;
833     *kid = 0;
834     *uid = 0;
835
836 ##  range of k is krbmap
837 ##  range of s is strings
838 ##  repeat retrieve (u_id = k.#users_id, k_id = k.#string_id)
839 ##      where k.string_id = s.string_id and s.string = @krbname
840 ##  inquire_equel (rowcount = "rowcount")
841     
842     if (rowcount == 1) {
843         *kid = -k_id;
844         *uid = u_id;
845         return;
846     }
847
848 ##  repeat retrieve (k_id = s.#string_id) where s.string = @krbname
849 ##  inquire_equel (rowcount = "rowcount")
850
851     if (rowcount == 1) {
852         *kid = -k_id;
853     }
854
855     if (!ok) {
856         *uid = *kid;
857         return;
858     }
859
860     *uid = get_users_id(login);
861     if (*kid == 0)
862       *kid = *uid;
863 ##}
864
865
866 /* For now this just checks the argc's.  It should also see that there
867  * are no duplicate names.
868  */
869
870 sanity_check_queries()
871 {
872     register int i;
873     int maxv = 0, maxa = 0;
874 #ifdef MULTIPROTOCOLS
875     extern int QueryCount1, QueryCount2;
876     extern struct query Queries1[], Queries2[];
877 #else
878     extern int QueryCount2;
879     extern struct query Queries2[];
880 #endif MULTIPROTOCOLS
881
882 #define MAX(x,y) ((x) > (y) ? (x) : (y))
883
884 #ifdef MULTIPROTOCOLS
885     for (i = 0; i < QueryCount1; i++) {
886         maxv = MAX(maxv, Queries1[i].vcnt);
887         maxa = MAX(maxa, Queries1[i].argc);
888     }
889 #endif MULTIPROTOCOLS
890     for (i = 0; i < QueryCount2; i++) {
891         maxv = MAX(maxv, Queries2[i].vcnt);
892         maxa = MAX(maxa, Queries2[i].argc);
893     }
894     if (MAX(maxv, maxa) > QMAXARGS) {
895         com_err(whoami, 0, "A query has more args than QMAXARGS");
896         exit(1);
897     }
898 }
This page took 0.105225 seconds and 5 git commands to generate.