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: }

Defined functions

_checkpipes defined in line 1268; never used
_doflag defined in line 805; used 5 times
_dolocks defined in line 966; used 1 times
_flagval defined in line 997; used 2 times
_ingexec defined in line 1340; used 1 times
_main defined in line 424; never used
_pipeopen defined in line 1216; used 5 times
_pipexlat defined in line 1463; used 5 times
_rubproc defined in line 682; never used
_satisfypt defined in line 1059; used 1 times
_sysflag defined in line 1153; used 1 times
_usrerr defined in line 1609; used 6 times
_yyerror defined in line 1601; never used
_yylex defined in line 1511; never used

Defined variables

_Flagok defined in line 758; used 1 times
_LineNo defined in line 1509; used 3 times
_Relmode defined in line 791; used 1 times

Defined struct's

flag defined in line 733; used 4 times
pipeinfo defined in line 190; used 6 times
proc defined in line 168; used 14 times

Defined macros

BOLSTATE defined in line 1506; used 1 times
CLOSED defined in line 149; used 8 times
EOFSTATE defined in line 1508; used 1 times
EQUELFLAG defined in line 147; used 1 times
F_ACCPT defined in line 749; used 15 times
F_CHAR defined in line 753; used 1 times
F_C_SPEC defined in line 750; used 1 times
F_DBA defined in line 745; used 1 times
F_DROP defined in line 746; used 2 times
F_EQUEL defined in line 756; used 3 times
F_F_SPEC defined in line 752; used 1 times
F_INTERNAL defined in line 755; used 3 times
F_I_SPEC defined in line 751; used 1 times
F_MODE defined in line 754; used 2 times
F_PLD defined in line 744; used 6 times
F_PLOK defined in line 743; used 10 times
MAXOPTNS defined in line 144; used 2 times
MAXPROCS defined in line 146; never used
NETFLAG defined in line 148; used 1 times
NORMSTATE defined in line 1507; used 1 times
PR_CLSDOUT defined in line 181; used 1 times
PR_CLSSIN defined in line 180; used 1 times
PR_NOCHDIR defined in line 179; used 1 times
PR_REALUID defined in line 178; used 1 times
SYSMAXOPTNS defined in line 145; used 1 times
Last modified: 1986-04-17
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2831
Valid CSS Valid XHTML 1.0 Strict