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