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