|
|
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.