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