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
checkdbname defined in line 1556; used 1 times
checkpipes defined in line 1371; used 1 times
doflag defined in line 502; used 3 times
dolocks defined in line 649; used 1 times
expand defined in line 1096; used 4 times
fillpipe defined in line 1323; used 1 times
flagval defined in line 916; used 2 times
getptline defined in line 1025; used 5 times
ingexec defined in line 1440; used 1 times
main defined in line 195; never used
rubproc defined in line 382; never used
satisfypt defined in line 1244; used 1 times
scanpt defined in line 963; used 5 times

Defined variables

Admin defined in line 185; used 2 times
Database defined in line 183; used 6 times
Fdesc defined in line 186; used 9 times
Fileset defined in line 182; used 2 times
Flagok defined in line 457; used 1 times
Lock defined in line 187; never used
No_exec defined in line 192; used 3 times
Nopts defined in line 191; used 2 times
Opt defined in line 190; used 3 times
Params defined in line 719; used 3 times
Proctab defined in line 711; used 3 times
Ptbuf defined in line 188; used 10 times
Ptptr defined in line 189; used 17 times
Relmode defined in line 488; used 1 times
User_ovrd defined in line 193; used 2 times

Defined struct's

flag defined in line 433; used 4 times
param defined in line 713; used 6 times
proc defined in line 695; used 18 times

Defined macros

CLOSED defined in line 180; used 4 times
EQUELFLAG defined in line 178; used 1 times
F_ACCPT defined in line 448; used 14 times
F_CHAR defined in line 452; used 1 times
F_C_SPEC defined in line 449; used 1 times
F_DBA defined in line 444; used 1 times
F_DROP defined in line 445; used 2 times
F_EQUEL defined in line 455; used 3 times
F_F_SPEC defined in line 451; used 1 times
F_INTERNAL defined in line 454; used 1 times
F_I_SPEC defined in line 450; used 1 times
F_MODE defined in line 453; used 2 times
F_PLD defined in line 443; used 6 times
F_PLOK defined in line 442; used 9 times
MAXOPTNS defined in line 175; used 2 times
MAXPARAMS defined in line 174; used 2 times
MAXPROCS defined in line 176; used 2 times
NETFLAG defined in line 179; used 1 times
PR_CLSDOUT defined in line 709; used 1 times
PR_CLSSIN defined in line 708; used 1 times
PR_NOCHDIR defined in line 707; used 1 times
PR_REALUID defined in line 706; used 1 times
PTDELIM defined in line 173; used 1 times
PTPARAM defined in line 172; used 1 times
PTSIZE defined in line 171; used 6 times
PVECTSIZE defined in line 177; used 3 times
Last modified: 1996-03-23
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4105
Valid CSS Valid XHTML 1.0 Strict