# 2.11BSD#431 - /usr/ingres/source/support/ingres.c

##### Functions

    buildint          X
    checkdbname       X
    checkpipes        X
    doflag            X
    dolocks           X
    expand            X
    fillpipe          X
    flagval           X
    getptline         X
    ingexec           X
    main              X
    rubproc           X
    satisfypt         X
    scanpt            X

##### Variables

    Admin             X
    Database          X
    Fdesc             X
    Fileset           X
    Flagok            X
    Lock              X
    No_exec           X
    Nopts             X
    Opt               X
    Params            X
    Proctab           X
    Ptbuf             X
    Ptptr             X
    Relmode           X
    User_ovrd         X

##### Macros

    CLOSED            X
    EQUELFLAG         X
    F_ACCPT           X
    F_CHAR            X
    F_C_SPEC          X
    F_DBA             X
    F_DROP            X
    F_EQUEL           X
    F_F_SPEC          X
    F_INTERNAL        X
    F_I_SPEC          X
    F_MODE            X
    F_PLD             X
    F_PLOK            X
    MAXOPTNS          X
    MAXPARAMS         X
    MAXPROCS          X
    NETFLAG           X
    PR_CLSDOUT        X
    PR_CLSSIN         X
    PR_NOCHDIR        X
    PR_REALUID        X
    PTDELIM           X
    PTPARAM           X
    PTSIZE            X
    PVECTSIZE         X

##### struct's

    flag              X
    param             X
    proc              X

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

#### Defined functions

buildint defined in line 722; used 1 times

- in line 358

checkdbname defined in line 1556; used 1 times

- in line 257

checkpipes defined in line 1371; used 1 times

- in line 1287

doflag defined in line 502; used 3 times

- in line 278, 285-289(2)

dolocks defined in line 649; used 1 times

- in line 370

expand defined in line 1096; used 4 times

- in line 1171-1175(2), 1454, 1474

fillpipe defined in line 1323; used 1 times

- in line 1268

flagval defined in line 916; used 2 times

- in line 651, 797

getptline defined in line 1025; used 5 times

- in line 731-735(2), 857, 866, 877

ingexec defined in line 1440; used 1 times

- in line 1275

main defined in line 195; never used
rubproc defined in line 382; never used
satisfypt defined in line 1244; used 1 times

- in line 373

scanpt defined in line 963; used 5 times

- in line 743-752(5)

#### Defined variables

Admin defined in line 185; used 2 times

- in line 288, 534

Database defined in line 183; used 6 times

- in line 215, 235, 255-259(3), 1458

Fdesc defined in line 186; used 9 times

- in line 298-303(5), 613(2), 619, 845

Fileset defined in line 182; used 2 times

- in line 213, 1456

Flagok defined in line 457; used 1 times

- in line 520

Lock defined in line 187; never used
No_exec defined in line 192; used 3 times

- in line 361, 537, 640

Nopts defined in line 191; used 2 times

- in line 629, 635

Opt defined in line 190; used 3 times

- in line 635, 926, 1478

Params defined in line 719; used 3 times

- in line 854, 860, 1144

Proctab defined in line 711; used 3 times

- in line 734-738(2), 1252

Ptbuf defined in line 188; used 10 times

- in line 189, 315-322(3), 338-339(2), 349, 355, 1119, 1132

Ptptr defined in line 189; used 17 times

- in line 887, 1031-1039(3), 1045, 1108, 1119-1121(2), 1127-1137(3), 1143, 1163, 1170, 1178-1183(2), 1194

Relmode defined in line 488; used 1 times

- in line 597

User_ovrd defined in line 193; used 2 times

- in line 292-293(2)

#### Defined struct's

flag defined in line 433; used 4 times

- in line 457(2), 507(2)

param defined in line 713; used 6 times

- in line 719(2), 730(2), 1100(2)

proc defined in line 695; used 18 times

- in line 711(2), 724(2), 1246(2), 1325-1328(4), 1372-1375(4), 1441(2), 1448(2)

#### Defined macros

CLOSED defined in line 180; used 4 times

- in line 615, 758, 1257, 1285

EQUELFLAG defined in line 178; used 1 times

- in line 480

F_ACCPT defined in line 448; used 14 times

- in line 459-462(3), 468-483(11)

F_CHAR defined in line 452; used 1 times

- in line 469

F_C_SPEC defined in line 449; used 1 times

- in line 461

F_DBA defined in line 444; used 1 times

- in line 533

F_DROP defined in line 445; used 2 times

- in line 470, 634

F_EQUEL defined in line 455; used 3 times

- in line 480-482(3)

F_F_SPEC defined in line 451; used 1 times

- in line 463

F_INTERNAL defined in line 454; used 1 times

- in line 466

F_I_SPEC defined in line 450; used 1 times

- in line 464

F_MODE defined in line 453; used 2 times

- in line 465-467(2)

F_PLD defined in line 443; used 6 times

- in line 459-468(5), 532

F_PLOK defined in line 442; used 9 times

- in line 459-478(8), 527

MAXOPTNS defined in line 175; used 2 times

- in line 190, 629

MAXPARAMS defined in line 174; used 2 times

- in line 719, 860

MAXPROCS defined in line 176; used 2 times

- in line 711, 738

NETFLAG defined in line 179; used 1 times

- in line 481

PR_CLSDOUT defined in line 709; used 1 times

- in line 1492

PR_CLSSIN defined in line 708; used 1 times

- in line 1491

PR_NOCHDIR defined in line 707; used 1 times

- in line 1497

PR_REALUID defined in line 706; used 1 times

- in line 1504

PTDELIM defined in line 173; used 1 times

- in line 1048

PTPARAM defined in line 172; used 1 times

- in line 1116

PTSIZE defined in line 171; used 6 times

- in line 188, 349-352(3), 1119, 1132

PVECTSIZE defined in line 177; used 3 times

- in line 701, 753-756(2)

Last modified: 1996-03-23 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 3693 |