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