]> andersk Git - moira.git/blob - server/qrtn.qc
make sure we clear sms_errcode between queries
[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     static first_open = 1;
73
74     if (first_open) {
75         first_open = 0;
76
77         /* initialize local argv */
78         for (i = 0; i < 16; i++)
79           Argv[i] = malloc(ARGLEN);
80
81         IIseterr(ingerr);
82         incremental_init();
83         flush_cache();
84     }
85         
86     ingres_errno = 0;
87     sms_errcode = 0;
88
89     /* open the database */
90 ##  ingres sms
91 ##  set lockmode session where level = table, timeout = query_timeout
92 ##  set lockmode on capacls where readlock = shared
93 ##  set lockmode on alias where readlock = shared
94     return ingres_errno;
95 }
96
97 int sms_close_database()
98 {
99     flush_cache();
100 ##  exit
101 }
102
103 sms_check_access(cl, name, argc, argv_ro)
104     client *cl;
105     char *name;
106     int argc;
107     char *argv_ro[];
108 {
109     struct query *q;
110     struct query *get_query_by_name();
111
112     ingres_errno = 0;
113     sms_errcode = 0;
114
115     q = get_query_by_name(name, cl->args->sms_version_no);
116     if (q == (struct query *)0)
117         return(SMS_NO_HANDLE);
118
119     return(sms_verify_query(cl, q, argc, argv_ro));
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 status;
132     register struct validate *v;
133     char qual[256];
134     char sort[32];
135     char *pqual;
136     char *psort;
137 ##  char *table, *rvar;
138     struct save_queue *sq;
139     struct query *get_query_by_name();
140     int sq_save_args();
141     struct save_queue *sq_create();
142     char *build_sort();
143
144     ingres_errno = 0;
145     sms_errcode = 0;
146
147     /* list queries command */
148     if (!strcmp(name, "_list_queries")) {
149         list_queries(cl->args->sms_version_no, action, actarg);
150         return(SMS_SUCCESS);
151     }
152
153     /* help query command */
154     if (!strcmp(name, "_help")) {
155         if (argc < 1)
156             return(SMS_ARGS);
157         q = get_query_by_name(argv_ro[0], cl->args->sms_version_no);
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, cl->args->sms_version_no);
165     if (q == (struct query *)0) return(SMS_NO_HANDLE);
166     v = q->validate;
167
168     if (q->type != RETRIEVE) {
169 ##      begin transaction
170     }
171
172     /* setup argument vector, verify access and arguments */
173     if ((status = sms_verify_query(cl, q, argc, argv_ro)) != SMS_SUCCESS)
174         goto out;
175
176     /* perform any special query pre-processing */
177     if (v && v->pre_rtn) {
178         status = (*v->pre_rtn)(q, Argv, cl, 0);
179         if (status != SMS_SUCCESS)
180             goto out;
181     }
182
183     switch (q->type) {
184     case RETRIEVE:
185         /* for queries that do not permit wildcarding, check if row
186            uniquely exists */
187         if (v && v->field) {
188             status = validate_row(q, Argv, v);
189             if (status != SMS_EXISTS) break;
190         }
191
192         /* build "where" clause if needed */
193         if (q->qual) {
194             build_qual(q->qual, q->argc, Argv, qual);
195             pqual = qual;
196         } else {
197             pqual = 0;
198         }
199
200         /* build "sort" clause if needed */
201         if (v && v->valobj) {
202             psort = build_sort(v, sort);
203         } else {
204             psort = 0;
205         }
206
207         /* if there is a followup routine, then we must save the results */
208         /* of the first query for use by the followup routine */
209         /* if q->rvar = NULL, perform post_rtn only */
210         if (q->rvar) {
211             if (v && v->post_rtn) {
212                 sq = sq_create();
213                 status = do_retrieve(q, pqual, psort, sq_save_args, sq);
214                 if (status != SMS_SUCCESS) {
215                     sq_destroy(sq);
216                     break;
217                 }
218                 status = (*v->post_rtn)(q, sq, v, action, actarg, cl);
219             } else {
220                 /* normal retrieve */
221                 status = do_retrieve(q, pqual, psort, action, actarg);
222             }
223             if (status != SMS_SUCCESS) break;
224         } else {
225             status = (*v->post_rtn)(q, Argv, cl, action, actarg);
226         }
227
228         break;
229
230     case UPDATE:
231         /* see if row already exists */
232         if (v->field) {
233             status = validate_row(q, Argv, v);
234             if (status != SMS_EXISTS) break;
235         }
236
237         /* build "where" clause and perform update */
238         /* if q->rvar = NULL, perform post_rtn only */
239         if (q->rvar) {
240             build_qual(q->qual, q->argc, Argv, qual);
241             incremental_before(q->rtable, qual, argv_ro);
242             status = do_update(q, &Argv[q->argc], qual, action, actarg);
243             incremental_after(q->rtable, qual, argv_ro);
244             if (status != SMS_SUCCESS) break;
245             flush_name(argv_ro[0], q->rtable);
246             table = q->rtable;
247             if (strcmp(q->shortname, "sshi") && strcmp(q->shortname, "ssif")) {
248 ##              repeat replace tblstats (updates = tblstats.updates + 1,
249 ##                                       modtime = "now")
250 ##                  where tblstats.#table = @table
251             }
252         }
253
254         /* execute followup routine (if any) */
255         if (v->post_rtn) status = (*v->post_rtn)(q, Argv, cl);
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) {
268             status = set_next_object_id(v->object_id, q->rtable);
269             if (status != SMS_SUCCESS) break;
270         }
271
272         /* build "where" clause if needed */
273         if (q->qual) {
274             build_qual(q->qual, q->argc, Argv, qual);
275             pqual = qual;
276         } else {
277             pqual = 0;
278         }
279
280         /* perform the append */
281         /* if q->rvar = NULL, perform post_rtn only */
282         if (q->rvar) {
283             incremental_clear_before();
284             status = do_append(q, &Argv[q->argc], pqual, action, actarg);
285             if (status != SMS_SUCCESS) break;
286             if (v && v->object_id) {
287                 sprintf(qual, "%s.%s = values.value and values.name = \"%s\"",
288                         q->rvar, v->object_id, v->object_id);
289                 incremental_after(q->rtable, qual, argv_ro);
290             } else
291               incremental_after(q->rtable, pqual, argv_ro);
292
293             table = q->rtable;
294 ##          repeat replace tblstats (appends = tblstats.appends + 1,
295 ##                                   modtime = "now")
296 ##              where tblstats.#table = @table
297         }
298         
299         /* execute followup routine */
300         if (v->post_rtn) status = (*v->post_rtn)(q, Argv, cl);
301         break;
302
303     case DELETE:
304         /* see if row already exists */
305         if (v->field) {
306             status = validate_row(q, Argv, v);
307             if (status != SMS_EXISTS) break;
308         }
309
310         /* build "where" clause and perform delete */
311         /* if q->rvar = NULL, perform post_rtn only */
312         if (q->rvar) {
313             build_qual(q->qual, q->argc, Argv, qual);
314             table = q->rtable;
315             rvar = q->rvar;
316 ##          range of rvar is table
317             incremental_before(q->rtable, qual, argv_ro);
318             status = do_delete(q, qual, action, actarg);
319             incremental_clear_after();
320             if (status != SMS_SUCCESS) break;
321             flush_name(argv_ro[0], q->rtable);
322 ##          repeat replace tblstats (deletes = tblstats.deletes + 1,
323 ##                                   modtime = "now")
324 ##              where tblstats.#table = @table
325         }
326
327         /* execute followup routine */
328         if (v->post_rtn) status = (*v->post_rtn)(q, Argv, cl);
329         break;
330
331     }
332
333 out:
334     if (status == SMS_SUCCESS && ingres_errno != 0) {
335         com_err(whoami, SMS_INTERNAL, "Server didn't notice INGRES ERROR %d",
336                        ingres_errno);
337         status = sms_errcode;
338     }
339
340     if (q->type != RETRIEVE) {
341         if (status == SMS_SUCCESS) {
342 ##          end transaction     /* commit to this */
343             if (journal) {
344                 char buf[1024], *bp;
345                 int i;
346                 extern time_t now;
347
348                 fprintf(journal, "%% %s %s %s",
349                         cl->clname, cl->entity, ctime(&now));
350                 fprintf(journal, "%s[%d] ", q->name, cl->args->sms_version_no);
351                 for (i = 0; i < argc; i++) {
352                     if (i != 0) {
353                         putc(' ', journal);
354                     }
355                     requote(buf, argv_ro[i], sizeof(buf));
356                     fputs(buf, journal);
357                 }
358                 putc('\n', journal);
359                 fflush(journal);
360             }
361             incremental_update();
362         } else {
363             if (ingres_errno != INGRES_DEADLOCK) {
364 ##              abort           /* it never happened */
365             }
366             incremental_flush();
367         }
368 ##      set lockmode session where readlock = system
369     }
370
371     if (status != SMS_SUCCESS && log_flags & LOG_RES)
372         com_err(whoami, status, " (Query failed)");
373     return(status);
374 }
375
376 build_qual(fmt, argc, argv, qual)
377         char *fmt;
378         int argc;
379         char *argv[];
380         char *qual;
381 {
382     register char *c;
383     register int i;
384     char *args[4];
385     char *index();
386
387     c = fmt;
388     for (i = 0; i < argc; i++) {
389         c = index(c, '%');
390         if (c++ == (char *)0) return(SMS_ARGS);
391         if (*c == 's')
392             args[i] = argv[i];
393         else if (*c == 'd')
394             *(int *)&args[i] = *(int *)argv[i]; /* sigh */
395         else
396             return(SMS_INGRES_ERR);
397     }
398
399     switch (argc) {
400     case 0:
401         strcpy(qual, fmt);
402         break;
403
404     case 1:
405         sprintf(qual, fmt, args[0]);
406         break;
407
408     case 2:
409         sprintf(qual, fmt, args[0], args[1]);
410         break;
411
412     case 3:
413         sprintf(qual, fmt, args[0], args[1], args[2]);
414         break;
415
416     case 4:
417         sprintf(qual, fmt, args[0], args[1], args[2], args[3]);
418         break;
419     }
420     return(SMS_SUCCESS);
421 }
422
423 char *
424 build_sort(v, sort)
425     register struct validate *v;
426     char *sort;
427 {
428     register struct valobj *vo;
429     register int n;
430     char elem[16];
431
432     n = v->objcnt;
433     vo = v->valobj;
434     *sort = 0;
435
436     while (--n >= 0) {
437         if (vo->type == V_SORT) {
438             sprintf(elem, "RET_VAR%d", vo->index + 1);
439             if (*sort) strcat(sort, ", ");
440             strcat(sort, elem);
441         }
442         vo++;
443     }
444
445     return ((*sort) ? sort : 0);
446 }
447
448
449 /* Build arguement vector, verify query and arguments */
450
451 sms_verify_query(cl, q, argc, argv_ro)
452     client *cl;
453     struct query *q;
454     int argc;
455     char *argv_ro[];
456 {
457     register int argreq;
458     register int status;
459     register struct validate *v = q->validate;
460     register int i;
461     register int privileged = 0;
462     int len;
463
464     /* copy the arguments into a local argv that we can modify */
465     if (argc >= QMAXARGS)
466       return(SMS_ARGS);
467     for (i = 0; i < argc; i++) {
468         if ((len = strlen(argv_ro[i])) < ARGLEN)
469             strcpy(Argv[i], argv_ro[i]);
470         else
471             return(SMS_ARG_TOO_LONG);
472         if (Argv[i][len-1] == '\\')
473           return(SMS_BAD_CHAR);
474     }
475
476     /* check initial query access */
477     status = check_query_access(q, Argv, cl);
478     if (status != SMS_SUCCESS && status != SMS_PERM)
479         return(status);
480     if (status == SMS_SUCCESS)
481         privileged++;
482
483     /* check argument count */
484     argreq = q->argc;
485     if (q->type == UPDATE || q->type == APPEND) argreq += q->vcnt;
486     if (argc != argreq) return(SMS_ARGS);
487
488     /* validate arguments */
489     if (v && v->valobj) {
490         status = validate_fields(q, Argv, v->valobj, v->objcnt);
491         if (status != SMS_SUCCESS) return(status);
492     }
493
494     /* perform special query access check */
495     if (!privileged && v && v->acs_rtn) {
496         status = (*v->acs_rtn)(q, Argv, cl);
497         if (status != SMS_SUCCESS && status != SMS_PERM)
498             return(status);
499         if (status == SMS_SUCCESS)
500             privileged++;
501     }
502
503     return(privileged ? SMS_SUCCESS : SMS_PERM);
504 }
505
506
507 /* This routine caches info from the database.  Each query acl is stored
508  * in the query structure, and whether that acl contains everybody.
509  */
510
511 check_query_access(q, argv, cl)
512     struct query *q;
513     char *argv[];
514     client *cl;
515 ##{
516 ##  char *name;
517 ##  int acl_id;
518 ##  int exists;
519 ##  int rowcount;
520 ##  int errorno;
521 ##  static int def_uid;
522     int status;
523     int client_id;
524     char *client_type;
525
526     /* initialize default uid */
527     if (def_uid == 0) {
528 ##      retrieve (def_uid = users.users_id) where users.login = "default"
529     }
530
531     /* get query access control list */
532     if (q->acl != 0)
533       acl_id = q->acl;
534     else {
535         name = q->shortname;
536 ##      retrieve (acl_id = capacls.list_id) where capacls.tag = name
537 ##      inquire_equel (rowcount = "rowcount", errorno = "errorno")
538         if (errorno != 0) return(SMS_INGRES_ERR);
539         if (rowcount == 0) return(SMS_PERM);
540         q->acl = acl_id;
541
542         /* check for default access */
543 ##      retrieve (exists = any(imembers.#member_id where
544 ##                             imembers.list_id = acl_id and
545 ##                             imembers.member_type = "USER" and
546 ##                             imembers.#member_id = def_uid))
547         q->everybody = exists;
548     }
549
550     if (q->everybody)
551       return(SMS_SUCCESS);
552
553     if (get_client(cl, &client_type, &client_id) != SMS_SUCCESS)
554       return(SMS_PERM);
555     if (find_member("LIST", acl_id, client_type, client_id, 0))
556       return(SMS_SUCCESS);
557     else
558       return(SMS_PERM);
559 ##}
560
561
562 get_client(cl, client_type, client_id)
563     client *cl;
564     char **client_type;
565     int *client_id;
566 {
567     if (cl->users_id > 0) {
568         *client_id = cl->users_id;
569         *client_type = "USER";
570         return(SMS_SUCCESS);
571     }
572
573     if (cl->client_id < 0) {
574         *client_id = -cl->users_id;
575         *client_type = "KERBEROS";
576         return(SMS_SUCCESS);
577     }
578
579     return(SMS_PERM);
580 }
581
582 ##find_member(list_type, list_id, member_type, member_id)
583     char *list_type;
584 ##  int list_id;
585 ##  char *member_type;
586 ##  int member_id;
587 ##{
588 ##  int exists, errorno;
589
590     if (!strcmp(strtrim(list_type), strtrim(member_type)) &&
591         list_id == member_id)
592         return(1);
593
594     /* see if client is a direct member of list */
595 ##  repeat retrieve (exists = any(imembers.#member_id where 
596 ##                                imembers.#list_id = @list_id and
597 ##                                imembers.#member_type = @member_type and 
598 ##                                imembers.#member_id = @member_id))
599 ##  inquire_equel(errorno = "errorno")
600     if (errorno == 0)
601       return(exists);
602     else
603       return(0);
604 ##}
605
606
607 do_retrieve(q, pqual, psort, action, actarg)
608     register struct query *q;
609     char *pqual;
610     char *psort;
611     int (*action)();
612     char *actarg;
613 ##{
614 ##  char *rvar;
615 ##  char *rtable;
616 ##  char *cqual;
617 ##  char *csort;
618 ##  int rowcount;
619 ##  int errorno;
620     static char **vaddrs = (char **)NULL;
621
622     if (!vaddrs) {
623         register int i;
624
625         if ((vaddrs = (char **)malloc(sizeof(char *) * QMAXARGS)) == NULL) {
626             com_err(whoami, SMS_NO_MEM, "setting up static argv");
627             exit(1);
628         }
629         for (i = 0; i < QMAXARGS; i++) {
630             if ((vaddrs[i] = malloc(QMAXARGSIZE)) == NULL) {
631                 com_err(whoami, SMS_NO_MEM, "setting up static argv");
632                 exit(1);
633             }
634         }
635     }
636
637     if (q->rvar) {
638         rvar = q->rvar;
639         rtable = q->rtable;
640 ##      range of rvar is rtable
641     }
642
643     if (psort) {
644         csort = psort;
645         if (pqual) {
646             cqual = pqual;
647 ##          retrieve unique (param (q->tlist, vaddrs)) where cqual
648 ##                   sort by csort
649 ##          {
650                  (*action)(q->vcnt, vaddrs, actarg);
651 ##          }
652         } else {
653 ##          retrieve unique (param (q->tlist, vaddrs))
654 ##                   sort by csort
655 ##          {
656                  (*action)(q->vcnt, vaddrs, actarg);
657 ##          }
658         }
659
660     } else {
661         if (pqual) {
662             cqual = pqual;
663 ##          retrieve unique (param (q->tlist, vaddrs)) where cqual
664 ##          {
665                  (*action)(q->vcnt, vaddrs, actarg);
666 ##          }
667         } else {
668 ##          retrieve unique (param (q->tlist, vaddrs))
669 ##          {
670                  (*action)(q->vcnt, vaddrs, actarg);
671 ##          }
672         }
673     }
674
675     if (sms_errcode) return(sms_errcode);
676 ##  inquire_equel (rowcount = "rowcount")
677     return ((rowcount == 0) ? SMS_NO_MATCH : SMS_SUCCESS);
678 ##}
679
680 do_update(q, argv, qual, action, actarg)
681     register struct query *q;
682     char *argv[];
683     char *qual;
684     int (*action)();
685     char *actarg;
686 ##{
687 ##  char *rvar;
688 ##  char *rtable;
689 ##  char *cqual;
690 ##  int errorno;
691       
692     rvar = q->rvar;
693     rtable = q->rtable;
694 ##  range of rvar is rtable
695
696     cqual = qual;
697 ##  replace rvar (param (q->tlist, argv))
698 ##  where cqual
699
700     if (sms_errcode) return(sms_errcode);
701     return(SMS_SUCCESS);
702 ##}
703
704 do_append(q, argv, pqual, action, actarg)
705     register struct query *q;
706     char *argv[];
707     char *pqual;
708     int (*action)();
709     char *actarg;
710 ##{
711 ##  char *rvar;
712 ##  char *rtable;
713 ##  char *cqual;
714 ##  int errorno;
715
716     rvar = q->rvar;
717     rtable = q->rtable;
718 ##  range of rvar is rtable
719
720     if (pqual) {
721         cqual = pqual;
722 ##      append to rtable (param (q->tlist, argv)) where cqual
723     } else {
724 ##      append to rtable (param (q->tlist, argv))
725     }
726
727     if (sms_errcode) return(sms_errcode);
728     return(SMS_SUCCESS);
729 ##}
730
731 do_delete(q, qual, action, actarg)
732     register struct query *q;
733     char *qual;
734     int (*action)();
735     char *actarg;
736 ##{
737 ##  char *rvar;
738 ##  char *rtable;
739 ##  char *cqual;
740 ##  int errorno;
741
742     rvar = q->rvar;
743     rtable = q->rtable;
744 ##  range of rvar is rtable
745
746     cqual = qual;
747 ##  delete rvar where cqual
748
749     if (sms_errcode) return(sms_errcode);
750     return(SMS_SUCCESS);
751 ##}
752
753
754 /**
755  ** set_next_object_id - set next object id in values table
756  **
757  ** Inputs: object - object name in values table and in objects
758  **         table - name of table objects are found in
759  **
760  ** - called before an APPEND operation to set the next object id to
761  **   be used for the new record to the next free value
762  **
763  **/
764
765 set_next_object_id(object, table)
766     char *object;
767     char *table;
768 ##{
769 ##  char *name, *tbl;
770 ##  int rowcount, exists, value;
771
772     name = object;
773     tbl = table;
774 ##  repeat retrieve (value = values.#value) where values.#name = @name
775 ##  inquire_equel(rowcount = "rowcount")
776     if (rowcount != 1)
777         return(SMS_NO_ID);
778
779 ##  retrieve (exists = any(tbl.name where tbl.name = value))
780 ##  inquire_equel(rowcount = "rowcount")
781     if (rowcount != 1)
782         return(SMS_NO_ID);
783     while (exists) {
784         value++;
785         if (value > MAX_ID_VALUE)
786             value = MIN_ID_VALUE;
787 ##      retrieve (exists = any(tbl.name where tbl.name = value))
788     }
789
790     if (LOG_RES)
791         com_err(whoami, 0, "setting ID %s to %d", name, value);
792 ##  repeat replace values (#value = @value) where values.#name = @name
793     return(SMS_SUCCESS);
794 ##}
795
796
797 /* Turn a kerberos name into the user's ID of the account that principal
798  * owns.  Sets the kerberos ID and user ID.
799  */
800
801 set_krb_mapping(name, login, ok, kid, uid)
802 char *name;
803 char *login;
804 int ok;
805 int *kid;
806 int *uid;
807 ##{
808 ##  int u_id, k_id, rowcount;
809 ##  char *krbname;
810
811     krbname = name;
812     *kid = 0;
813     *uid = 0;
814
815 ##  repeat retrieve (u_id = krbmap.#users_id, k_id = krbmap.#string_id)
816 ##      where krbmap.string_id = strings.string_id and strings.string = @krbname
817 ##  inquire_equel (rowcount = "rowcount")
818     
819     if (rowcount == 1) {
820         *kid = -k_id;
821         *uid = u_id;
822         return;
823     }
824
825     if (name_to_id(name, "STRINGS", &k_id) == SMS_SUCCESS)
826       *kid = -k_id;
827
828     if (!ok) {
829         *uid = *kid;
830         return;
831     }
832
833     if (name_to_id(login, "USERS", uid) != SMS_SUCCESS)
834       *uid = 0;
835
836     if (*kid == 0)
837       *kid = *uid;
838 ##}
839
840
841 /* For now this just checks the argc's.  It should also see that there
842  * are no duplicate names.
843  */
844
845 sanity_check_queries()
846 {
847     register int i;
848     int maxv = 0, maxa = 0;
849 #ifdef MULTIPROTOCOLS
850     extern int QueryCount1, QueryCount2;
851     extern struct query Queries1[], Queries2[];
852 #else
853     extern int QueryCount2;
854     extern struct query Queries2[];
855 #endif MULTIPROTOCOLS
856
857 #define MAX(x,y) ((x) > (y) ? (x) : (y))
858
859 #ifdef MULTIPROTOCOLS
860     for (i = 0; i < QueryCount1; i++) {
861         maxv = MAX(maxv, Queries1[i].vcnt);
862         maxa = MAX(maxa, Queries1[i].argc);
863     }
864 #endif MULTIPROTOCOLS
865     for (i = 0; i < QueryCount2; i++) {
866         maxv = MAX(maxv, Queries2[i].vcnt);
867         maxa = MAX(maxa, Queries2[i].argc);
868     }
869     if (MAX(maxv, maxa) > QMAXARGS) {
870         com_err(whoami, 0, "A query has more args than QMAXARGS");
871         exit(1);
872     }
873 }
This page took 0.122296 seconds and 5 git commands to generate.