Annotation of 42BSD/ingres/source/support/ingres.y, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.