|
|
1.1 root 1: %{
2:
3: # include <stdio.h>
4: # include <ctype.h>
5: # include <ingres.h>
6: # include <aux.h>
7: # include <version.h>
8: # include <access.h>
9: # include <lock.h>
10: # include <opsys.h>
11: # include <ctlmod.h>
12: # include <sccs.h>
13:
14:
15: /*
16: ** INGRES -- INGRES startup
17: **
18: ** This program starts up the entire system.
19: **
20: ** Parameters:
21: ** 1 -- database name
22: ** 2 -- optional process table name
23: ** x -- flags of the form +x or -x may be freely inter-
24: ** sperced in the argument list.
25: **
26: ** Return:
27: ** none if successful
28: ** 1 -- user error (no database, etc)
29: ** -1 -- system error
30: **
31: ** Flags:
32: ** -&xxxx -- EQUEL flag: xxxx are file descriptors for the
33: ** status return pipe, the command write pipe, the
34: ** data return pipe, and the data transfer pipe
35: ** respectively.
36: ** -@xxxx -- xxxx is same as EQUEL flag, but no flags
37: ** are set.
38: ** -*?? -- Masterid flag. Gives the siteid of the master
39: ** site in a distributed ingres. (Used in dist.
40: ** ingres' initproc() function.)
41: ** -|xxxx -- Network flag. This flag is just passed to
42: ** the other processes, to be processed by the
43: ** DBU's.
44: ** -uusername -- set effective user to be username. You
45: ** must be INGRES or the DBA for the database to
46: ** use this option.
47: ** -cN -- set minimum character field output width to be
48: ** N, default 6. This is the fewest number of
49: ** characters which may be output in any "c" type
50: ** field.
51: ** -inN -- integer output width. this is the width of
52: ** an integer field. The small "n" is the size
53: ** of the internal field ("1", "2", or "4") and
54: ** N is the width of the field for that flag.
55: ** The defaults are -i16, -i26, and -i413.
56: ** -fnxN.M -- floating point output width and precision.
57: ** Small "n" is the internal width in bytes ("4"
58: ** or "8"), x is the format (f, F, g, G, e, E,
59: ** n, or N), N is the field width, and M is the
60: ** precision (number of digits after the decimal
61: ** point). The formats are:
62: ** "f" or "F": FORTRAN-style F format: digits,
63: ** decimal point, digits, no exponent.
64: ** "e" or "E": FORTRAN-style E format: digits,
65: ** decimal point, digits, letter "e" (or
66: ** "E", depending on "x" in the param-
67: ** eter), and an exponent. The scaling
68: ** factor is always one, that is, there
69: ** is always one digit before the decimal
70: ** point.
71: ** "g" or "G": F format if it will fit in the
72: ** field, otherwise E format. Space is
73: ** always left at the right of the field
74: ** for the exponent, so that decimal
75: ** points will align.
76: ** "n" or "N": like G, except that space is not
77: ** left for the decimal point in F style
78: ** format (useful if you expect everything
79: ** to fit, but you're not sure).
80: ** The default is -fn10.3.
81: ** -vx -- set vertical seperator for print operations
82: ** and retrieves to the terminal to be "x". The
83: ** default is vertical bar ("|").
84: ** +w -- database wait state. If set ("+w"), you will
85: ** wait until the database is not busy. If clear,
86: ** you will be informed if the database is busy.
87: ** If not specified, the same operations take
88: ** place depending on whether or not you are
89: ** running in background (determined by whether
90: ** or not your input is a teletype). If in fore-
91: ** ground, you are informed; if in background,
92: ** you wait.
93: ** -M -- monitor trace flag
94: ** -P -- parser trace flag
95: ** -O -- ovqp trace flag
96: ** -Q -- qrymod trace flag
97: ** -D -- decomp trace flag
98: ** -Z -- dbu trace flag. These flags require the 020 bit
99: ** in the status field of the users file to be
100: ** set. The syntax is loose and is described
101: ** elsewhere. Briefly, "-Z" sets all flags except
102: ** the last 20, "-Z4" sets flag 4, and "-Z5/7"
103: ** sets all flags from 5 through 7.
104: ** +L -- enable/disable upper to lower case mapping in the
105: ** parser. Used for debugging.
106: ** -rmode -- retrieve into mode
107: ** -nmode -- index mode. These flags give the default
108: ** modify mode for retrieve into and index. They
109: ** default to cheapsort and isam. "Mode" can be
110: ** any mode to modify except "truncated".
111: ** +a -- enable/disable autoclear function in monitor.
112: ** Default on.
113: ** +b -- enable/disable batch update. Default on.
114: ** The 02 bit is needed to clear this flag.
115: ** +d -- enable/disable printing of the dayfile. Default
116: ** on.
117: ** +s -- enable/disable printing of almost everything from
118: ** the monitor.
119: ** +U -- enable/disable direct update of system catalogs.
120: ** Default off. The 04 bit is needed to set this
121: ** option.
122: **
123: ** Files:
124: ** .../files/usage -- to print a "usage: ..." message.
125: ** .../data/base/<database>/admin -- to determine
126: ** existance and some info about <database>.
127: ** .../files/dayfile<VERSION> -- dayfile (printed by
128: ** monitor).
129: ** .../files/users -- file with UNIX uid -> INGRES code
130: ** mapping, plus a pile of other information about
131: ** the user.
132: ** .../files/proctab<VERSION> -- default process table
133: */
134:
135: SCCSID(%W% %G%)
136:
137: # define MAXOPTNS 10 /* maximum number of options you can specify */
138: # define MAXPROCS 10 /* maximum number of processes in the system */
139: # define EQUELFLAG '&'
140: # define NETFLAG '|' /* network slave flag */
141: # define CLOSED '?'
142:
143: char Fileset[10];
144: char *Database;
145: extern char *Dbpath; /* defined in initucode */
146: struct admin Admin; /* set in initucode */
147: struct lockreq Lock;
148: FILE *ProcFile; /* fildes for the process table */
149: char *DefProcTab = NULL; /* default process table name */
150: char *Opt[MAXOPTNS + 1];
151: int Nopts;
152: int No_exec; /* if set, don't execute */
153: int NumProcs; /* number of processes this system */
154:
155:
156: /*
157: ** Internal form of process descriptions.
158: */
159:
160: struct proc
161: {
162: short prstat; /* status bits, see below */
163: char prmpipe; /* initial pipe to this process */
164: char prtflag; /* trace flag for CM this proc */
165: char prpath[50]; /* pathname of this process */
166: struct _cm_t prcm; /* cm info passed to this proc */
167: };
168:
169: /* bits for prstat */
170: # define PR_REALUID 0001 /* run as the user, not INGRES */
171: # define PR_NOCHDIR 0002 /* don't chdir into database */
172: # define PR_CLSSIN 0004 /* close standard input */
173: # define PR_CLSDOUT 0010 /* close diagnostic output */
174:
175: struct proc ProcTab[CM_MAXPROC];
176:
177:
178: /*
179: ** Open pipe info.
180: */
181:
182: struct pipeinfo
183: {
184: char pip_rfd; /* read file descriptor */
185: char pip_wfd; /* write file descriptor */
186: short pip_rcnt; /* read reference count */
187: short pip_wcnt; /* write reference count */
188: };
189:
190: struct pipeinfo Pipe[128];
191:
192:
193: /*
194: ** Macro definitions
195: */
196:
197: char Macro[26][80];
198:
199:
200: /* system error messages, etc. */
201: extern int sys_nerr;
202: extern char *sys_errlist[];
203: extern int errno;
204:
205: /* globals used by the grammar. */
206: struct proc *Proc;
207: state_t *StateP;
208: proc_t *ProcP;
209: int ProcNo;
210: int RemStat;
211:
212:
213: %}
214:
215: %union
216: {
217: int yyint; /* integer */
218: char *yystr; /* string */
219: char yypip; /* pipe id */
220: char yychar; /* single character */
221: }
222:
223: %token <yyint> INT
224: %token <yystr> STR
225:
226: %type <yyint> procno stateno funcno
227: %type <yyint> flags
228: %type <yystr> pathname printname
229: %type <yypip> pipe_id
230: %type <yychar>macro_id tflag
231:
232: %%
233:
234: proctab: spec_list
235: ;
236:
237: spec_list: spec
238: | spec_list spec
239: ;
240:
241: spec: proc_line states
242: | macro_defn
243: ;
244:
245: /*
246: ** Lines beginning with "P" introduce new processes.
247: **
248: ** procno is the number of the process being defined.
249: ** pathname is the pathname of the executable object
250: ** of this module.
251: ** printname is the name to be used as "Procname" in
252: ** this module for activities unconnected with
253: ** particular modules.
254: ** pipe_id is the pipe to use as the normal input for
255: ** this process. It must be listed as a pipe
256: ** in at least one of the constituent state
257: ** definitions.
258: ** flags are flags associated with this process. They
259: ** are not actually passed to the process, but
260: ** are used internally. See the #defines after
261: ** /^struct proc/.
262: */
263:
264: proc_line: 'P' procno pathname printname pipe_id flags tflag
265: {
266: NumProcs++;
267: Proc = &ProcTab[$2];
268: smove($3, Proc->prpath);
269: Proc->prmpipe = Proc->prcm.cm_input = Proc->prcm.cm_rinput
270: = Proc->prcm.cm_proc[$2].pr_ninput = $5;
271: smove($4, Proc->prcm.cm_myname);
272: Proc->prcm.cm_myproc = $2;
273: Proc->prstat = $6;
274: Proc->prtflag = $7;
275: Pipe[$5].pip_rcnt += 3;
276: Pipe[$5].pip_wcnt++;
277: }
278: ;
279:
280: states: state_line
281: | states state_line
282: ;
283:
284: state_line: local_line
285: | remote_line
286: ;
287:
288: local_line: 'L' stateno flags funcno stateno
289: {
290: StateP = &Proc->prcm.cm_state[$2];
291: StateP->st_type = ST_LOCAL;
292: StateP->st_stat = $3;
293: StateP->st_v.st_loc.st_funcno = $4;
294: StateP->st_v.st_loc.st_next = $5;
295: }
296: ;
297:
298: remote_line: remote_header stateno_list
299: ;
300:
301: remote_header: 'R' procno flags pipe_id pipe_id flags
302: {
303: ProcNo = $2;
304: ProcP = &Proc->prcm.cm_proc[ProcNo];
305: RemStat = $3;
306: ProcP->pr_file = $4;
307: ProcP->pr_ninput = $5;
308: ProcP->pr_stat = $6;
309: Pipe[$4].pip_wcnt++;
310: Pipe[$5].pip_rcnt++;
311: }
312: ;
313:
314: stateno_list: /* empty */
315: | stateno_list remote_stateno
316: ;
317:
318: remote_stateno: stateno
319: {
320: StateP = &Proc->prcm.cm_state[$1];
321: StateP->st_type = ST_REMOT;
322: StateP->st_stat = RemStat;
323: StateP->st_v.st_rem.st_proc = ProcNo;
324: }
325: ;
326:
327: /*
328: ** Macro definitions.
329: */
330:
331: macro_defn: 'D' macro_id STR
332: {
333: smove($3, Macro[$2 - 'A']);
334: }
335:
336: /*
337: ** Productions for things that perhaps ought to be in the scanner.
338: */
339:
340: procno: INT
341: {
342: if ($1 < 0 || $1 >= CM_MAXPROC)
343: {
344: usrerr("Illegal proc number %d", $1);
345: YYERROR;
346: }
347: }
348: ;
349:
350: stateno: INT
351: {
352: if ($1 < 0 || $1 >= CM_MAXST)
353: {
354: usrerr("Illegal state number %d", $1);
355: YYERROR;
356: }
357: }
358: ;
359:
360: funcno: INT
361: {
362: if ($1 < 0)
363: {
364: usrerr("Illegal funcno %d", $1);
365: YYERROR;
366: }
367: }
368: ;
369:
370: pathname: STR
371: ;
372:
373: printname: STR
374: ;
375:
376: pipe_id: STR
377: {
378: if ((islower($1[0]) || $1[0] == CLOSED) && $1[1] == '\0')
379: $$ = $1[0];
380: else if ($1[0] == '|' && isdigit($1[1]) && $1[2] == '\0')
381: $$ = $1[1];
382: else
383: {
384: usrerr("Invalid pipe id \"%s\"", $1);
385: YYERROR;
386: }
387: }
388: ;
389:
390: tflag: STR
391: {
392: if ($1[1] != '\0')
393: {
394: usrerr("Invalid trace flag \"%s\"", $1);
395: YYERROR;
396: }
397: else
398: $$ = $1[0];
399: }
400: ;
401:
402: flags: INT
403: ;
404:
405: macro_id: STR
406: {
407: if ($1[0] < 'A' || $1[0] > 'Z' || $1[1] != '\0')
408: {
409: usrerr("Invalid macro name \"%s\"", $1);
410: YYERROR;
411: }
412: else
413: $$ = $1[0];
414: }
415:
416: %%
417:
418: main(argc, argv)
419: int argc;
420: char **argv;
421: {
422: register int i;
423: register int j;
424: extern char *Proc_name;
425: int fd;
426: extern int Status;
427: char *proctab;
428: register char *p;
429: char *ptr;
430: extern char *Flagvect[]; /* defined in initucode.c */
431: extern char *Parmvect[]; /* ditto */
432: char *uservect[4];
433: char buf[MAXLINE+1];
434: char str[MAXLINE+1]; /* a string to put the Alockdes value into */
435: char str2[MAXLINE+1];
436: extern int Wait_action; /* action on lock driver */
437:
438: Proc_name = "INGRES";
439: itoa(getpid(), Fileset);
440: proctab = NULL;
441: Database = NULL;
442:
443: /*
444: ** Initialize everything, like Flagvect, Parmvect, Usercode,
445: ** etc.
446: */
447:
448: for (i = 0; i < 128; i++)
449: Pipe[i].pip_rfd = Pipe[i].pip_wfd = -1;
450:
451: i = initucode(argc, argv, TRUE, uservect, -1);
452: switch (i)
453: {
454: case 0: /* ok */
455: case 5:
456: break;
457:
458: case 1: /* database does not exist */
459: case 6:
460: printf("Database %s does not exist\n", Parmvect[0]);
461: goto usage;
462:
463: case 2: /* you are not authorized */
464: printf("You may not access database %s\n", Database);
465: goto usage;
466:
467: case 3: /* not a valid user */
468: printf("You are not a valid INGRES user\n");
469: goto usage;
470:
471: case 4: /* no database name specified */
472: printf("No database name specified\n");
473: goto usage;
474:
475: default:
476: syserr("initucode %d", i);
477: }
478:
479: /*
480: ** Extract database name and process table name from
481: ** parameter vector.
482: ** Initialize the $P macro.
483: */
484:
485: Database = Parmvect[0];
486: proctab = Parmvect[1];
487: smove(Pathname, Macro['P' - 'A']);
488:
489: /* scan flags in users file */
490: for (p = uservect[0]; *p != '\0'; p++)
491: {
492: /* skip initial blanks and tabs */
493: if (*p == ' ' || *p == '\t')
494: continue;
495: ptr = p;
496:
497: /* find end of flag and null-terminate it */
498: while (*p != '\0' && *p != ' ' && *p != '\t')
499: p++;
500: i = *p;
501: *p = '\0';
502:
503: /* process the flag */
504: doflag(ptr, 1);
505: if (i == '\0')
506: break;
507: }
508:
509: /* scan flags on command line */
510: for (i = 0; (p = Flagvect[i]) != NULL; i++)
511: doflag(p, 0);
512:
513: /* check for query modification specified for this database */
514: if ((Admin.adhdr.adflags & A_QRYMOD) == 0)
515: doflag("-q", -1);
516:
517: /* close any extraneous files, being careful not to close anything we need */
518: for (i = 3; i < NOFILE; i++)
519: {
520: for (j = '0'; j <= '9'; j++)
521: {
522: if (Pipe[j].pip_wfd == i || Pipe[j].pip_rfd == i)
523: break;
524: }
525: if (j > '9')
526: close(i);
527: }
528:
529: /* determine process table */
530: if (proctab == NULL)
531: {
532: /* use default proctab */
533: if (DefProcTab == NULL)
534: {
535: if (argv[0][length(argv[0]) - 1] == 'x')
536: DefProcTab = "=procx";
537: else
538: DefProcTab = "=proctab";
539: proctab = uservect[1];
540: }
541: if (proctab == NULL || proctab[0] == 0)
542: {
543: /* no proctab in users file */
544: concat(DefProcTab, VERSION, buf);
545: proctab = buf;
546: }
547: }
548: else
549: {
550: /* proctab specified; check permissions */
551: if ((Status & (proctab[0] == '=' ? U_EPROCTAB : U_APROCTAB)) == 0)
552: {
553: printf("You may not specify this process table\n");
554: goto usage;
555: }
556: }
557:
558: /* expand process table name */
559: if (proctab[0] == '=')
560: {
561: smove(ztack(ztack(Pathname, "/files/"), &proctab[1]), buf);
562: proctab = buf;
563: }
564:
565: /* open and read the process table */
566: if ((ProcFile = fopen(proctab, "r")) == NULL)
567: {
568: printf("Proctab %s: %s\n", proctab, sys_errlist[errno]);
569: goto usage;
570: }
571:
572: /* build internal form of the process table */
573: if (yyparse())
574: No_exec++;
575:
576: /* don't bother executing if we have found errors */
577: if (No_exec)
578: {
579: usage:
580: /* cat .../files/usage */
581: cat(ztack(Pathname, "/files/usage"));
582: exit(1);
583: }
584:
585: fclose(ProcFile);
586:
587: /* set locks on the database */
588: dolocks();
589: if ( Alockdes >= 0 )
590: {
591: sprintf(str,"-l%d",(flagval('E') >0 ?M_EXCL : M_SHARE));
592: doflag(str,-1);
593: sprintf(str2,"-W%d",Wait_action);
594: doflag(str2,-1);
595: close(Alockdes);
596: }
597:
598: /* satisfy process table (never returns) */
599: satisfypt();
600: }
601:
602:
603:
604: /*
605: ** Process rubouts (just exit)
606: */
607:
608: rubproc()
609: {
610: exit(2);
611: }
612: /*
613: ** DOFLAG -- process flag
614: **
615: ** Parameters:
616: ** flag -- the flag (as a string)
617: ** where -- where it is called from
618: ** -1 -- internally inserted
619: ** 0 -- on user command line
620: ** 1 -- from users file
621: **
622: ** Return:
623: ** none
624: **
625: ** Side effects:
626: ** All flags are inserted on the end of the
627: ** "Flaglist" vector for passing to the processes.
628: ** The "No_exec" flag is set if the flag is bad or you
629: ** are not authorized to use it.
630: **
631: ** Requires:
632: ** Status -- to get the status bits set for this user.
633: ** syserr -- for the obvious
634: ** printf -- to print errors
635: ** atoi -- to check syntax on numerically-valued flags
636: **
637: ** Defines:
638: ** doflag()
639: ** Flagok -- a list of legal flags and attributes (for
640: ** local use only).
641: ** Relmode -- a list of legal relation modes.
642: **
643: ** Called by:
644: ** main
645: **
646: ** History:
647: ** 11/6/79 (6.2/8) (eric) -- -u flag processing dropped,
648: ** since initucode does it anyhow. -E flag
649: ** removed (what is it?). F_USER code dropped.
650: ** F_DROP is still around; we may need it some-
651: ** day. Also, test of U_SUPER flag and/or DBA
652: ** status was wrong.
653: ** 7/5/78 (eric) -- NETFLAG added to list.
654: ** 3/27/78 (eric) -- EQUELFLAG added to the list.
655: ** 1/29/78 -- do_u_flag broken off by eric
656: ** 1/4/78 -- written by eric
657: */
658:
659: struct flag
660: {
661: char flagname; /* name of the flag */
662: char flagstat; /* status of flag (see below) */
663: int flagsyntx; /* syntax code for this flag */
664: int flagperm; /* status bits needed to use this flag */
665: char *flagpt; /* default proctab to use with this flag */
666: };
667:
668: /* status bits for flag */
669: # define F_PLOK 01 /* allow +x form */
670: # define F_PLD 02 /* defaults to +x */
671: # define F_DBA 04 /* must be the DBA to use */
672: # define F_DROP 010 /* don't save in Flaglist */
673:
674: /* syntax codes */
675: # define F_ACCPT 1 /* always accept */
676: # define F_C_SPEC 3 /* -cN spec */
677: # define F_I_SPEC 4 /* -inN spec */
678: # define F_F_SPEC 5 /* -fnxN.M spec */
679: # define F_CHAR 6 /* single character */
680: # define F_MODE 7 /* a modify mode */
681: # define F_INTERNAL 8 /* internal flag, e.g., -q */
682: # define F_EQUEL 9 /* EQUEL flag */
683:
684: struct flag Flagok[] =
685: {
686: 'a', F_PLD|F_PLOK, F_ACCPT, 0, NULL,
687: 'b', F_PLD|F_PLOK, F_ACCPT, U_DRCTUPDT, NULL,
688: 'c', 0, F_C_SPEC, 0, NULL,
689: 'd', F_PLD|F_PLOK, F_ACCPT, 0, NULL,
690: 'f', 0, F_F_SPEC, 0, NULL,
691: 'i', 0, F_I_SPEC, 0, NULL,
692: 'l', F_PLOK, F_INTERNAL, 0, NULL,
693: 'n', 0, F_MODE, 0, NULL,
694: 'q', F_PLD|F_PLOK, F_INTERNAL, 0, NULL,
695: 'r', 0, F_MODE, 0, NULL,
696: 's', F_PLD|F_PLOK, F_ACCPT, 0, NULL,
697: 'v', 0, F_CHAR, 0, NULL,
698: 'w', F_PLOK|F_DROP, F_ACCPT, 0, NULL,
699: 'D', 0, F_ACCPT, U_TRACE, NULL,
700: 'L', F_PLOK, F_ACCPT, 0, NULL,
701: 'M', 0, F_ACCPT, U_TRACE, NULL,
702: 'O', 0, F_ACCPT, U_TRACE, NULL,
703: 'P', 0, F_ACCPT, U_TRACE, NULL,
704: 'Q', 0, F_ACCPT, U_TRACE, NULL,
705: 'T', 0, F_ACCPT, U_TRACE, NULL,
706: 'U', F_PLOK, F_ACCPT, U_UPSYSCAT, NULL,
707: 'W', 0, F_INTERNAL, 0, NULL,
708: 'Z', 0, F_ACCPT, U_TRACE, NULL,
709: EQUELFLAG, 0, F_EQUEL, 0, "=equel",
710: NETFLAG, 0, F_EQUEL, 0, "=slave",
711: '@', 0, F_EQUEL, 0, NULL,
712: '*', 0, F_ACCPT, 0, NULL,
713: 0, 0, 0, 0, NULL,
714: };
715:
716: /* list of valid retrieve into or index modes */
717: char *Relmode[] =
718: {
719: "isam",
720: "cisam",
721: "hash",
722: "chash",
723: "heap",
724: "cheap",
725: "heapsort",
726: "cheapsort",
727: NULL
728: };
729:
730:
731: doflag(flag, where)
732: char *flag;
733: int where;
734: {
735: register char *p;
736: register struct flag *f;
737: auto int intxx;
738: register char *ptr;
739: int i;
740: int j;
741: extern int Status;
742:
743: p = flag;
744:
745: /* check for valid flag format (begin with + or -) */
746: if (p[0] != '+' && p[0] != '-')
747: goto badflag;
748:
749: /* check for flag in table */
750: for (f = Flagok; f->flagname != p[1]; f++)
751: {
752: if (f->flagname == 0)
753: goto badflag;
754: }
755:
756: /* check for +x form allowed */
757: if (p[0] == '+' && (f->flagstat & F_PLOK) == 0)
758: goto badflag;
759:
760: /* check for permission to use the flag */
761: if ((f->flagperm != 0 && (Status & f->flagperm) == 0 &&
762: (((f->flagstat & F_PLD) == 0) ? (p[0] == '+') : (p[0] == '-'))) ||
763: ((f->flagstat & F_DBA) != 0 && (Status & U_SUPER) == 0 &&
764: !bequal(Usercode, Admin.adhdr.adowner, 2)))
765: {
766: printf("You are not authorized to use the %s flag\n", p);
767: No_exec++;
768: }
769:
770: /* check syntax */
771: switch (f->flagsyntx)
772: {
773: case F_ACCPT:
774: break;
775:
776: case F_C_SPEC:
777: if ((intxx = atoi(&p[2])) > MAXFIELD)
778: goto badflag;
779: break;
780:
781: case F_I_SPEC:
782: if (p[2] != '1' && p[2] != '2' && p[2] != '4')
783: goto badflag;
784: if ((intxx = atoi(&p[3])) > MAXFIELD)
785: goto badflag;
786: break;
787:
788: case F_F_SPEC:
789: if (p[2] != '4' && p[2] != '8')
790: goto badflag;
791: switch (p[3])
792: {
793: case 'e':
794: case 'E':
795: case 'f':
796: case 'F':
797: case 'g':
798: case 'G':
799: case 'n':
800: case 'N':
801: break;
802:
803: default:
804: goto badflag;
805:
806: }
807: ptr = &p[4];
808: while (*ptr != '.')
809: if (*ptr == 0)
810: goto badflag;
811: else
812: ptr++;
813: *ptr = 0;
814: if ((intxx = atoi(&p[4])) > MAXFIELD)
815: goto badflag;
816: *ptr++ = '.';
817: if ((intxx = atoi(ptr)) > MAXFIELD)
818: goto badflag;
819: break;
820:
821: case F_CHAR:
822: if (p[2] == 0 || p[3] != 0)
823: goto badflag;
824: break;
825:
826: case F_MODE:
827: for (i = 0; (ptr = Relmode[i]) != NULL; i++)
828: {
829: if (sequal(&p[2], ptr))
830: break;
831: }
832: if (ptr == NULL)
833: goto badflag;
834: break;
835:
836: case F_INTERNAL:
837: if (where >= 0)
838: goto badflag;
839: break;
840:
841: case F_EQUEL:
842: ptr = &p[2];
843: for (i = 0; i < 20; i++, ptr++)
844: {
845: if (*ptr == CLOSED)
846: continue;
847: if (*ptr < 0100 || *ptr >= 0100 + NOFILE)
848: break;
849: j = (i / 2) + '0';
850: if ((i & 01) == 0)
851: {
852: Pipe[j].pip_rfd = *ptr & 077;
853: }
854: else
855: {
856: Pipe[j].pip_wfd = *ptr & 077;
857: }
858: }
859: break;
860:
861: default:
862: syserr("doflag: syntx %d", f->flagsyntx);
863:
864: }
865:
866: /* save flag */
867: if (Nopts >= MAXOPTNS)
868: {
869: printf("Too many options to INGRES\n");
870: exit(1);
871: }
872: if ((f->flagstat & F_DROP) == 0)
873: Opt[Nopts++] = p;
874:
875: /* change to new process table as appropriate */
876: if (f->flagpt != NULL)
877: DefProcTab = f->flagpt;
878:
879: return;
880:
881: badflag:
882: printf("Bad flag format: %s\n", p);
883: No_exec++;
884: return;
885: }
886: /*
887: ** DOLOCKS -- set database lock
888: **
889: ** A lock is set on the database.
890: */
891:
892: dolocks()
893: {
894: db_lock(flagval('E') > 0 ? M_EXCL : M_SHARE);
895: }
896: /*
897: ** FLAGVAL -- return value of flag
898: **
899: ** Parameter:
900: ** flag -- the name of the flag
901: **
902: ** Return:
903: ** -1 -- flag is de-asserted (-x)
904: ** 0 -- flag is not specified
905: ** 1 -- flag is asserted (+x)
906: **
907: ** Requires:
908: ** Opt -- to scan the flags
909: **
910: ** Defines:
911: ** flagval
912: **
913: ** Called by:
914: ** buildint
915: ** dolocks
916: **
917: ** History:
918: ** 3/27/78 (eric) -- changed to handle EQUEL flag
919: ** normally.
920: ** 1/4/78 -- written by eric
921: */
922:
923: flagval(flag)
924: char flag;
925: {
926: register char f;
927: register char **p;
928: register char *o;
929:
930: f = flag;
931:
932: /* start scanning option list */
933: for (p = Opt; (o = *p) != 0; p++)
934: {
935: if (o[1] == f)
936: if (o[0] == '+')
937: return (1);
938: else
939: return (-1);
940: }
941: return (0);
942: }
943: /*
944: ** SATISFYPT -- satisfy the process table
945: **
946: ** Well folks, now that you've read this far, this is it!!! I
947: ** mean, this one really does it!!! It takes the internal form
948: ** built by the parser and creates pipes as necessary, forks, and
949: ** execs the INGRES processes. Isn't that neat?
950: **
951: ** Parameters:
952: ** none
953: **
954: ** Returns:
955: ** never
956: **
957: ** Requires:
958: ** Proctab -- the internal form
959: ** ingexec -- to actually exec the process
960: ** pipe -- to create the pipe
961: ** syserr -- for the obvious
962: ** fillpipe -- to extend a newly opened pipe through all
963: ** further references to it.
964: ** checkpipes -- to see if a given pipe will ever be
965: ** referenced again.
966: ** fork -- to create a new process
967: **
968: ** Defines:
969: ** satisfypt
970: **
971: ** Called by:
972: ** main
973: **
974: ** History:
975: ** 3/14/80 (eric) -- changed for version 7.0.
976: ** 7/24/78 (eric) -- Actual file descriptors stored in
977: ** 'prpipes' are changed to have the 0100 bit
978: ** set internally (as well as externally), so
979: ** fd 0 will work correctly.
980: ** 1/4/78 -- written by eric
981: */
982:
983: satisfypt()
984: {
985: register struct proc *pr;
986: register proc_t *pp;
987: register int i;
988: int procno;
989: register int pip;
990:
991: /* scan the process table */
992: for (procno = CM_MAXPROC-1; procno >= 0; procno--)
993: {
994: pr = &ProcTab[procno];
995: if (pr->prpath[0] == '\0')
996: continue;
997:
998: /* scan pipe vector, creating new pipes as needed */
999: pipeopen(pr->prmpipe, TRUE);
1000: pipeopen(pr->prcm.cm_input, FALSE);
1001: pipeopen(pr->prcm.cm_rinput, FALSE);
1002: for (i = 0; i < CM_MAXPROC; i++)
1003: {
1004: pp = &pr->prcm.cm_proc[i];
1005: pipeopen(pp->pr_file, TRUE);
1006: pipeopen(pp->pr_ninput, FALSE);
1007: }
1008:
1009: /* substitute real file descriptors throughout */
1010: pipexlat(&pr->prmpipe, TRUE);
1011: pipexlat(&pr->prcm.cm_input, FALSE);
1012: pipexlat(&pr->prcm.cm_rinput, FALSE);
1013: for (i = 0; i < CM_MAXPROC; i++)
1014: {
1015: pp = &pr->prcm.cm_proc[i];
1016: pipexlat(&pp->pr_file, TRUE);
1017: pipexlat(&pp->pr_ninput, FALSE);
1018: }
1019:
1020: /* fork if necessary */
1021: if (--NumProcs <= 0 || (i = fork()) == 0 )
1022: {
1023: /* child!! */
1024: ingexec(procno);
1025: }
1026:
1027: /* parent */
1028: if (i < 0)
1029: syserr("satisfypt: fork");
1030:
1031: /* scan pipes. close all not used in the future */
1032: for (i = 0; i < 128; i++)
1033: {
1034: if (i == CLOSED)
1035: continue;
1036: if (Pipe[i].pip_rcnt <= 0 && Pipe[i].pip_rfd >= 0)
1037: {
1038: if (close(Pipe[i].pip_rfd) < 0)
1039: syserr("satisfypt: close-r(%d)", Pipe[i].pip_rfd);
1040: Pipe[i].pip_rfd = -1;
1041: }
1042: if (Pipe[i].pip_wcnt <= 0 && Pipe[i].pip_wfd >= 0)
1043: {
1044: if (close(Pipe[i].pip_wfd) < 0)
1045: syserr("satisfypt: close-w(%d)", Pipe[i].pip_wfd);
1046: Pipe[i].pip_wfd = -1;
1047: }
1048: }
1049: }
1050: syserr("satisfypt: fell out");
1051: }
1052: /*
1053: ** PIPEOPEN -- open pipe if necessary.
1054: */
1055:
1056: pipeopen(pipid, rw)
1057: char pipid;
1058: int rw;
1059: {
1060: register struct pipeinfo *pi;
1061: int pipex[2];
1062:
1063: if (pipid == '\0')
1064: return;
1065:
1066: pi = &Pipe[pipid];
1067:
1068: if ((rw ? pi->pip_wfd : pi->pip_rfd) >= 0)
1069: return;
1070: if (pi->pip_rfd >= 0 || pi->pip_wfd >= 0)
1071: syserr("pipeopen %o %d: rfd=%d, wfd=%d", pipid, rw, pi->pip_rfd, pi->pip_wfd);
1072: if (pipid == CLOSED)
1073: pi->pip_rfd = pi->pip_wfd = CLOSED;
1074: else
1075: {
1076: if (pipe(pipex) < 0)
1077: syserr("pipeopen: pipe");
1078: pi->pip_rfd = pipex[0];
1079: pi->pip_wfd = pipex[1];
1080: }
1081: }
1082: /*
1083: ** CHECKPIPES -- check for pipe referenced in the future
1084: **
1085: ** Parameters:
1086: ** proc -- point in the process table to start looking
1087: ** from.
1088: ** fd -- the file descriptor to look for.
1089: **
1090: ** Return:
1091: ** zero -- it will be referenced in the future.
1092: ** one -- it is never again referenced.
1093: **
1094: ** Requires:
1095: ** nothing
1096: **
1097: ** Defines:
1098: ** checkpipes
1099: **
1100: ** Called by:
1101: ** satisfypt
1102: **
1103: ** History:
1104: ** 7/24/78 (eric) -- 0100 bit on file descriptors handled.
1105: ** 1/4/78 -- written by eric
1106: */
1107:
1108: checkpipes(proc, fd)
1109: struct proc *proc;
1110: register int fd;
1111: {
1112: register struct proc *pr;
1113: register proc_t *pp;
1114: register int i;
1115:
1116: for (pr = proc; pr < &ProcTab[CM_MAXPROC]; pr++)
1117: {
1118: if (pr->prpath[0] == '\0')
1119: continue;
1120: for (i = 0; i < CM_MAXPROC; i++)
1121: {
1122: pp = &pr->prcm.cm_proc[i];
1123: if (pp->pr_file == fd || pp->pr_ninput == fd)
1124: return (0);
1125: }
1126: }
1127: return (1);
1128: }
1129: /*
1130: ** INGEXEC -- execute INGRES process
1131: **
1132: ** This routine handles all the setup of the argument vector
1133: ** and then executes a process.
1134: **
1135: ** Parameters:
1136: ** process -- a pointer to the process table entry which
1137: ** describes this process.
1138: **
1139: ** Returns:
1140: ** never
1141: **
1142: ** Side Effects:
1143: ** never returns, but starts up a new overlay. Notice
1144: ** that it does NOT fork.
1145: **
1146: ** Requires:
1147: ** none
1148: **
1149: ** Called By:
1150: ** satisfypt
1151: **
1152: ** Trace Flags:
1153: ** none
1154: **
1155: ** Diagnostics:
1156: ** none
1157: **
1158: ** Syserrs:
1159: ** chdir %s -- could not change directory into the data-
1160: ** base.
1161: ** creat %s -- could not create the redirected standard
1162: ** output file.
1163: ** %s not executable -- could not execute the process.
1164: **
1165: ** History:
1166: ** 8/9/78 (eric) -- changed "prparam" to be a colon-
1167: ** separated list of parameters (so the number
1168: ** is variable); also, moved parameter expansion
1169: ** into this routine from buildint() so that
1170: ** the colons in the dbu part of the proctab
1171: ** would not confuse things.
1172: ** 7/24/78 (eric) -- changed the technique of closing
1173: ** files 0 & 2 so that they will never be closed
1174: ** (even if requested in the status field)
1175: ** if they are mentioned in the pipe vector.
1176: ** Also, some fiddling is done to handle the
1177: ** 0100 bit on file descriptors correctly.
1178: */
1179:
1180: ingexec(procno)
1181: int procno;
1182: {
1183: char *vect[30];
1184: register char **v;
1185: char **opt;
1186: int i;
1187: register struct proc *pr;
1188: register proc_t *pp;
1189: register char *p;
1190: int outfd;
1191: char closeit[NOFILE];
1192: char fdbuf[3];
1193:
1194: v = vect;
1195: pr = &ProcTab[procno];
1196:
1197: *v++ = pr->prpath;
1198: fdbuf[0] = pr->prcm.cm_rinput | 0100;
1199: fdbuf[1] = pr->prtflag;
1200: fdbuf[2] = '\0';
1201: *v++ = fdbuf;
1202: *v++ = Fileset;
1203: *v++ = Usercode;
1204: *v++ = Database;
1205: *v++ = Pathname;
1206:
1207: /* insert flag parameters */
1208: for (opt = Opt; *opt; opt++)
1209: *v++ = *opt;
1210: *v = 0;
1211:
1212: /* set up 'closeit' to tell which pipes to close */
1213: for (i = 0; i < NOFILE; i++)
1214: closeit[i] = TRUE;
1215: closeit[pr->prmpipe & 077] = FALSE;
1216: closeit[pr->prcm.cm_input & 077] = FALSE;
1217: closeit[pr->prcm.cm_rinput & 077] = FALSE;
1218: for (i = 0; i < CM_MAXPROC; i++)
1219: {
1220: pp = &pr->prcm.cm_proc[i];
1221: if (pp->pr_ninput != CLOSED)
1222: closeit[pp->pr_ninput & 077] = FALSE;
1223: if (pp->pr_file != CLOSED)
1224: closeit[pp->pr_file & 077] = FALSE;
1225: }
1226: closeit[1] = FALSE;
1227: if ((pr->prstat & PR_CLSSIN) == 0)
1228: closeit[0] = FALSE;
1229: if ((pr->prstat & PR_CLSDOUT) == 0)
1230: closeit[2] = FALSE;
1231:
1232: /* close extra pipes (those not used by this process) */
1233: for (i = 0; i < NOFILE; i++)
1234: {
1235: if (closeit[i])
1236: close(i);
1237: }
1238:
1239: /* change to the correct directory */
1240: if ((pr->prstat & PR_NOCHDIR) == 0)
1241: {
1242: if (chdir(Dbpath))
1243: syserr("ingexec: chdir %s", Dbpath);
1244: }
1245:
1246: /* change to normal userid/groupid if a non-dangerous process */
1247: if ((pr->prstat & PR_REALUID) != 0)
1248: {
1249: setuid(getuid());
1250: # ifndef xB_UNIX
1251: setgid(getgid());
1252: # endif
1253: }
1254:
1255: # ifdef LEAVEOUT
1256: /* change standard output if specified in proctab */
1257: p = pr->prstdout;
1258: if (*p != 0)
1259: {
1260: /* chew up fd 0 (just in case) */
1261: outfd = dup(1);
1262: close(1);
1263: if (creat(p, 0666) != 1)
1264: {
1265: /* restore standard output and print error */
1266: close(1);
1267: dup(outfd); /* better go into slot 1 */
1268: syserr("ingexec: creat %s", p);
1269: }
1270: close(outfd);
1271: }
1272: # endif LEAVEOUT
1273:
1274: /*
1275: ** PLEASE NOTE THE TRICKERY USED HERE.
1276: ** In this code I depend on UNIX buffering pipes at least
1277: ** enough to handle one "CM" struct. If not, the following
1278: ** write will hang before the exec will call the process
1279: ** that will read it.
1280: **
1281: ** The "correct" way to do this is to fork & have the
1282: ** parent write the CM struct. But how do I handle the
1283: ** last one (that does not fork)? I could also do an
1284: ** extra fork of a process to do the write. But some
1285: ** systems have a limit on processes, and besides, it
1286: ** seems like a lot of overhead for such a little thing.
1287: **
1288: ** Perhaps I should encode the CM struct into argv
1289: ** instead & do it "right".
1290: */
1291:
1292: /* output the control structure to the awaiting process... */
1293: write(pr->prmpipe & 077, &pr->prcm, sizeof pr->prcm);
1294: close(pr->prmpipe & 077);
1295:
1296: /* give it the old college (or in this case, University) try */
1297: execv(vect[0], vect);
1298: syserr("\"%s\" not executable", vect[0]);
1299: }
1300:
1301:
1302:
1303: pipexlat(ppip, rw)
1304: char *ppip;
1305: int rw;
1306: {
1307: register struct pipeinfo *pi;
1308: int cnt;
1309: int fd;
1310:
1311: if (*ppip == '\0' || *ppip == CLOSED)
1312: return;
1313: pi = &Pipe[*ppip];
1314:
1315: if (rw)
1316: {
1317: cnt = --(pi->pip_wcnt);
1318: fd = pi->pip_wfd;
1319: }
1320: else
1321: {
1322: cnt = --(pi->pip_rcnt);
1323: fd = pi->pip_rfd;
1324: }
1325:
1326: if (cnt < 0)
1327: syserr("pipexlat: cnt=%d: %o %d", cnt, *ppip, rw);
1328: if (fd < 0 || fd > NOFILE)
1329: syserr("pipexlat: fd=%d: %o %d", fd, *ppip, rw);
1330:
1331: *ppip = fd;
1332: }
1333: /*
1334: ** YYLEX -- Return next token from proctab
1335: **
1336: ** Parameters:
1337: ** none
1338: **
1339: ** Returns:
1340: ** Next token
1341: **
1342: ** Side Effects:
1343: ** Input from proctab
1344: */
1345:
1346: # define BOLSTATE 0 /* beginning of line */
1347: # define NORMSTATE 1 /* normal token */
1348: # define EOFSTATE 2 /* end of file */
1349: int LineNo; /* current line number */
1350:
1351: yylex()
1352: {
1353: static int state;
1354: static char *ptp;
1355: auto int ix;
1356: static char line[MAXLINE];
1357: register int c;
1358: register char *p;
1359:
1360: switch (state)
1361: {
1362: case EOFSTATE:
1363: return (0);
1364:
1365: case BOLSTATE:
1366: ptp = line;
1367: for (;;)
1368: {
1369: LineNo++;
1370: c = getc(ProcFile);
1371: if (c < 0)
1372: {
1373: state = EOFSTATE;
1374: return (0);
1375: }
1376: switch (c)
1377: {
1378: case '*':
1379: case '#':
1380: case '\n':
1381: while (c != '\n' && (c = getc(ProcFile)) > 0)
1382: continue;
1383: break;
1384:
1385: case ':':
1386: while (c != '\n' && (c = getc(ProcFile)) > 0)
1387: putchar(c);
1388: break;
1389:
1390: default:
1391: /* regular line, return header */
1392: state = NORMSTATE;
1393: return (c);
1394: }
1395: }
1396:
1397: case NORMSTATE:
1398: yylval.yystr = ptp;
1399: while ((c = getc(ProcFile)) != ':' && c != '\n' && c > 0)
1400: {
1401: *ptp++ = c;
1402: if (c == '$')
1403: {
1404: c = getc(ProcFile);
1405: if (c < 'A' || c > 'Z')
1406: *ptp++ = c;
1407: else
1408: {
1409: ptp--;
1410: for (p = Macro[c - 'A']; (*ptp++ = *p++) != '\0'; )
1411: continue;
1412: ptp--;
1413: }
1414: }
1415: }
1416:
1417: /* compute next state */
1418: if (c != ':')
1419: state = BOLSTATE;
1420:
1421: *ptp++ = '\0';
1422: ix = atoi(yylval.yystr);
1423: if ( *yylval.yystr <= '9' && *yylval.yystr >= '0')
1424: {
1425: if (yylval.yystr[0] == '0')
1426: ix = oatoi(yylval.yystr);
1427: yylval.yyint = ix;
1428: return (INT);
1429: }
1430: else
1431: return (STR);
1432:
1433: default:
1434: syserr("yylex: state %d", state);
1435: }
1436: }
1437:
1438:
1439:
1440:
1441: yyerror(s)
1442: char *s;
1443: {
1444: syserr("Line %d: Yacc error: %s", LineNo, s);
1445: }
1446:
1447:
1448: /*VARARGS1*/
1449: usrerr(f, p1, p2, p3)
1450: char *f;
1451: {
1452: printf("Line %d: ", LineNo);
1453: printf(f, p1, p2, p3);
1454: printf("\n");
1455: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.