Annotation of 42BSD/ingres/source/support/ingres.y, revision 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.