1: # include   <stdio.h>
   2: 
   3: # include   "../ingres.h"
   4: # include   "../aux.h"
   5: # include   "../access.h"
   6: # include   "../pipes.h"
   7: # include   "../symbol.h"
   8: # include   "../unix.h"
   9: 
  10: /*
  11: **  CREATDB -- create database (or modify database status)
  12: **
  13: **	This program creates a new database.  It takes the name of
  14: **	the new database (syntax defined below) and a series of
  15: **	flags (also defined below).
  16: **
  17: **	In order to perform this command, you must be enabled by
  18: **	having the U_CREATDB bit set in the user status word
  19: **	of the users file.
  20: **
  21: **	The -m flag specifies that the directory for the database
  22: **	already exists.  It stands for "mounted-file-system",
  23: **	because this is presumably when you might use this feature.
  24: **	The directory must be empty.
  25: **
  26: **	The -e flag specifies that the database already exists.
  27: **	It must be in all ways a valid database.  This mode allows
  28: **	you to turn flags on and off, as controlled by the other
  29: **	flags.
  30: **
  31: **	Usage:
  32: **		creatdb [flags] databasename
  33: **
  34: **	Positional Parameters:
  35: **		databasename -- the name of the database to create.
  36: **			It must conform to all the usual rules
  37: **			about names.  Notice that this is more
  38: **			restrictive than UNIX usually is:  names
  39: **			must begin with an alpha, and must be
  40: **			composed of alphanumerics.  It may be
  41: **			at most 14 characters long.  Underscore
  42: **			counts as an alphabetic.
  43: **
  44: **	Flags:
  45: **		-m
  46: **			This is a mounted filesystem.  Actually,
  47: **			this just means that the directory in which
  48: **			the database is to reside already exists.
  49: **			It must be empty.
  50: **		-e
  51: **			This database exists.  When the -e flag is
  52: **			specified, the database is brought up to date,
  53: **			rather than created.  Things which may be
  54: **			changed with the -e flag is anything that
  55: **			affects the database status or the relation
  56: **			status bits.
  57: **		-uXX
  58: **			Run as user XX (usercode or login name).  This
  59: **			flag may only be used by the INGRES superuser.
  60: **			Normally, the database administrator for the
  61: **			new database is the user who performs the
  62: **			command, but the -u flag allows INGRES to
  63: **			give the database to someone else.  Thus, it
  64: **			is possible for someone to be a DBA without
  65: **			having the U_CREATDB bit set.
  66: **		-Fpathname
  67: **			Use the named file as the database template.
  68: **			This is, of course, for debugging use only.
  69: **		+-c
  70: **			Turn concurrency control on/off.  The default
  71: **			for a new database depends on the dbtmplt file,
  72: **			but as of this writing it defaults on.
  73: **		+-q
  74: **			Turn query modification on/off.
  75: **		+-l
  76: **			Turn protection violation logging on/off.
  77: **
  78: **	Files:
  79: **		.../files/dbtmplt<VERSION>
  80: **			This file drives the entire program.  The
  81: **			syntax of this file is defined below in
  82: **			readdbtemp().  Briefly, it tells the database
  83: **			status, the relations in an 'empty' database,
  84: **			and the status and format of those relations.
  85: **		.../data/base
  86: **			This directory is the directory in which all
  87: **			databases eventually reside.  Each database is
  88: **			a subdirectory of this directory.
  89: **
  90: **	Return Codes:
  91: **		zero -- success
  92: **		else -- failure.
  93: **
  94: **	Defined Constants:
  95: **		MAXRELNS
  96: **			This defines the maximum number of relations
  97: **			which may be declared in the dbtmplt file.
  98: **		MAXDBTEMP
  99: **			The maximum size of the dbtmplt file.  This
 100: **			determines the maximum number of characters
 101: **			which may be in the file.
 102: **
 103: **	Requires:
 104: **		Much.  Notably, be careful about changes to any
 105: **		access methods, especially automatic references to
 106: **			to the 'admin' file or relation relation.
 107: **		create() -- to actually create relations.
 108: **
 109: **	Compilation Flags:
 110: **		xB_UNIX -- if defined, says that we have a "Berkeley
 111: **			UNIX" system, with no group id's.  If
 112: **			undefined, specifies either a version seven
 113: **			UNIX (with 16-bit group id's) or version six
 114: **			UNIX (with 8-bit group id's); either way,
 115: **			"setgid(getgid())" will work.
 116: **
 117: **	Trace Flags:
 118: **		-Tn, as below:
 119: **
 120: **		1 -- makereln()
 121: **		2 -- create()
 122: **		10 -- makeadmin()
 123: **		12 -- makefile()
 124: **		20 -- makedb()
 125: **
 126: **	Diagnostics:
 127: **		No database name specified.
 128: **		You may not access this database
 129: **			Your entry in the users file says this is
 130: **			not a valid database for you.
 131: **		You are not a valid INGRES user
 132: **			You do not have a users file entry, and can
 133: **			not do anything with INGRES at all.
 134: **		You are not allowed this command
 135: **			The U_CREATDB bit is not set in your users
 136: **			file entry.
 137: **		You may not use the -u flag
 138: **			Only the INGRES superuser may say s/he is
 139: **			someone else.
 140: **		%s does not exist
 141: **			With -e or -m, the directory does not exist.
 142: **		%s already exists
 143: **			Without either -e or -m, the database
 144: **			(actually, the directory) already exists.
 145: **		%s is not empty
 146: **			With the -m flag, the directory you named
 147: **			must be empty.
 148: **		You are not the DBA for this database
 149: **			With the -e flag, you must be the database
 150: **			administrator.
 151: **
 152: **	Syserrs:
 153: **		fork
 154: **			A fork request (for the mkdir command) failed;
 155: **			probably if you try again later things will
 156: **			work
 157: **		setuid
 158: **			The call to setuid() (to reset the user id
 159: **			to that of the actual user) failed.  This
 160: **			"cannot happen".
 161: **		setgid
 162: **			Same for setgid().
 163: **		exec /bin/mkdir
 164: **			It was not possible to execute the mkdir
 165: **			command, used to create a directory for
 166: **			the database.
 167: **		chmod
 168: **			The chmod command on the database (after the
 169: **			return from mkdir) failed -- probably due
 170: **			to the mkdir command failing somehow before
 171: **			creating the directory.  Notice that we do
 172: **			not check the return from mkdir, since we
 173: **			are not sure that it is unpolluted on all
 174: **			systems.
 175: **		chdir %s
 176: **			After creating the database, we could not
 177: **			change directory into it.
 178: **		open .../files/dbtmplt
 179: **			The dbtmplt file does not exist or is not
 180: **			readable.
 181: **		creatdb: closer(rel) %d
 182: **			It was not possible to close the relation
 183: **			relation after finishing the bulk of the
 184: **			creatdb.
 185: **		closer(att) %d
 186: **			Ditto for attribute relation.
 187: **		main: creat admin
 188: **			It was not possible to create the 'admin'
 189: **			file in the database.  This is, of course,
 190: **			a total disaster.
 191: **		main: write Admin
 192: **			It was not possible to write the admin file
 193: **			out -- probably out of disk space.
 194: **
 195: **	Compilation Instructions:
 196: **		% setup creatdb
 197: **
 198: **		- which translates to -
 199: **
 200: **		% cc -n -O creatdb.c error.c ../../lib/dbulib \
 201: **			../../lib/access ../../lib/utility
 202: **		% chmod 4711 a.out
 203: **
 204: **	History:
 205: **		8/15/79 (eric) (6.2/7) -- changed 'mkdir' stuff to
 206: **			change into /mnt/ingres/data/base and then
 207: **			mkdir on 'database' instead of 'Dbpath' --
 208: **			to avoid dependence on a mkdir bug on our
 209: **			system.  Changed to assume that argv[argc]
 210: **			is NULL instead of -1 for v7.  Added #include
 211: **			of unix.h to get unix version flags.
 212: **		10/11/78 (eric) -- -F option added.
 213: **		8/3/78 (eric) -- written.
 214: */
 215: 
 216: 
 217: 
 218: 
 219: # define    MAXRELNS    20
 220: # define    MAXDBTEMP   2000
 221: 
 222: /* relation & attribute reln descriptors used in access methods */
 223: extern struct descriptor    Reldes;
 224: extern struct descriptor    Attdes;
 225: 
 226: extern int  Status;     /* user status, set by initucode */
 227: int     Dbstat;     /* database status */
 228: int     Dbson, Dbsoff;  /* same: bits turned on, bits turned off */
 229: struct reldes
 230: {
 231:     int bitson;
 232:     int bitsoff;
 233:     char    *parmv[MAXPARMS];
 234: };
 235: struct reldes   Rellist[MAXRELNS];
 236: char        Delim;
 237: extern char *Dbpath;
 238: 
 239: 
 240: 
 241: main(argc, argv)
 242: int argc;
 243: char    *argv[];
 244: {
 245:     register int        i;
 246:     int         admin;          /* file desc */
 247:     char            adminbuf[BUFSIZ];
 248:     extern struct admin Admin;
 249:     extern int      errno;
 250:     auto int        code;
 251:     struct relation     relk;
 252:     char            *database;
 253:     char            **av;
 254:     register char       *p;
 255:     char            *user_ovrd;
 256:     int         faterr;
 257:     register int        *flagv;
 258:     char            *dbtmpfile;
 259:     extern char     *Parmvect[];
 260:     extern char     *Flagvect[];
 261:     int         exists;
 262:     extern char     Version[];
 263:     int         *flaglkup();
 264:     char            *ztack();
 265: 
 266: #	ifdef xSTR1
 267:     tTrace(&argc, argv, 'T');
 268: #	endif
 269: 
 270:     /*
 271: 	**  Do a lot of magic initialization.
 272: 	*/
 273: 
 274:     exists = 0;
 275:     i = initucode(argc, argv, TRUE, NULL, -1);
 276:     switch (i)
 277:     {
 278:       case 0:
 279:       case 5:
 280:         exists = 1;
 281:         break;
 282: 
 283:       case 6:
 284:         exists = -1;
 285: 
 286:       case 1:
 287:         break;
 288: 
 289:       case 2:
 290:         printf("You are not authorized to create this database\n");
 291:         exit(-1);
 292: 
 293:       case 3:
 294:         printf("You are not a valid INGRES user\n");
 295:         exit(-1);
 296: 
 297:       case 4:
 298:         printf("No database name specified\n");
 299:     usage:
 300:         printf("Usage: creatdb [-uname] [-e] [-m] [+-c] [+-q] dbname\n");
 301:         exit(-1);
 302: 
 303:       default:
 304:         syserr("initucode %d", i);
 305:     }
 306: 
 307:     faterr = 0;
 308:     dbtmpfile = 0;
 309:     for (av = Flagvect; (p = *av) != NULL; av++)
 310:     {
 311:         if (p[0] != '-' && p[0] != '+')
 312:             syserr("flag %s", p);
 313:         switch (database[1])
 314:         {
 315:           case 'F':     /* dbtmplt file */
 316:             if (p[2] == 0)
 317:                 goto badflag;
 318:             dbtmpfile = &p[2];
 319:             break;
 320: 
 321:           default:
 322:             if (flagv = flaglkup(p[1], p[0]))
 323:             {
 324:                 if (p[0] == '+')
 325:                     *flagv = 1;
 326:                 else
 327:                     *flagv = -1;
 328:                 continue;
 329:             }
 330:         badflag:
 331:             printf("bad flag %s\n", p);
 332:             faterr++;
 333:             continue;
 334: 
 335:         }
 336:         if (p[0] == '+')
 337:             goto badflag;
 338:     }
 339: 
 340:     /* check for legality of database name */
 341:     database = Parmvect[0];
 342:     if (Parmvect[1] != NULL)
 343:     {
 344:         printf("Too many parameters to creatdb");
 345:         goto usage;
 346:     }
 347:     if (!check(database))
 348:     {
 349:         printf("Illegal database name %s\n", database);
 350:         exit(-1);
 351:     }
 352: 
 353:     if ((Status & U_CREATDB) == 0)
 354:     {
 355:         printf("You are not allowed this command\n");
 356:         exit(-1);
 357:     }
 358: 
 359:     /* end of input checking */
 360:     if (faterr != 0)
 361:         exit(2);
 362: 
 363:     /* now see if it should have been there */
 364:     if (flagval('m') || flagval('e'))
 365:     {
 366: #		ifdef xSTR3
 367:         if (tTf(1, 14))
 368:             printf("Dbpath = '%s'\n", Dbpath);
 369: #		endif
 370:         if (flagval('e') && exists <= 0)
 371:         {
 372:             printf("Database %s does not exist\n", database);
 373:             exit(-1);
 374:         }
 375: 
 376:         if (chdir(Dbpath) < 0)
 377:         {
 378:             printf("Directory for %s does not exist\n", database);
 379:             exit(-1);
 380:         }
 381: 
 382:         if (!flagval('e'))
 383:         {
 384:             /* make certain that it is empty */
 385:             freopen(".", "r", stdin);
 386:             for (i = 0; i < 16; i++)
 387:                 getw(stdin);
 388:             while ((i = getw(stdin)) != EOF)
 389:             {
 390:                 if (i != 0)
 391:                     syserr(0, "%s is not empty", database);
 392:                 for (i = 0; i < 7; i++)
 393:                     getw(stdin);
 394:             }
 395:         }
 396:         else
 397:         {
 398:             /* check for correct owner */
 399:             acc_init();
 400:             if (!bequal(Usercode, Admin.adhdr.adowner, 2))
 401:                 syserr(0, "You are not the DBA for this database");
 402:         }
 403:     }
 404:     else
 405:     {
 406:         if (exists != 0)
 407:         {
 408:             printf("Database %s already exists\n", database);
 409:             exit(-1);
 410:         }
 411: 
 412:         /* create it */
 413:         i = fork();
 414:         if (i < 0)
 415:             syserr("fork err");
 416:         if (i == 0)
 417:         {
 418:             /* enter database directory */
 419:             initdbpath(NULL, adminbuf, FALSE);
 420:             if (chdir(adminbuf) < 0)
 421:                 syserr("%s: cannot enter", adminbuf);
 422: 
 423:             /* arrange for proper permissions */
 424:             if (setuid(getuid()))
 425:                 syserr("setuid");
 426: #			ifndef xB_UNIX
 427:             if (setgid(getgid()))
 428:                 syserr("setgid");
 429: #			endif
 430:             execl("/bin/mkdir", "mkdir", database, 0);
 431:             syserr("exec /bin/mkdir");
 432:         }
 433:         while (wait(&code) != -1)
 434:             continue;
 435:         if (chdir(Dbpath) < 0)
 436:             syserr("could not chdir into %s; probably bad default mode in '/bin/mkdir'", Dbpath);
 437:         i = fork();
 438:         if (i < 0)
 439:             syserr("fork 2");
 440:         if (i == 0)
 441:         {
 442:             setuid(getuid());
 443:             if (chmod(".", 0777))
 444:                 syserr("chmod");
 445:             exit(0);
 446:         }
 447: 
 448:         while (wait(&code) != -1)
 449:             ;
 450:         if ((code & 0377) != 0)
 451:             exit(code);
 452: 
 453:     }
 454: 
 455:     /* reset 'errno', set from possibly bad chdir */
 456:     errno = 0;
 457: 
 458:     /* determine name of dbtmplt file and open */
 459:     if (dbtmpfile == NULL)
 460:     {
 461:         smove(Version, adminbuf);
 462:         for (i = 0; adminbuf[i] != 0; i++)
 463:             if (adminbuf[i] == '/')
 464:                 break;
 465:         adminbuf[i] = 0;
 466:         dbtmpfile = ztack(ztack(Pathname, "/files/dbtmplt"), adminbuf);
 467:     }
 468:     if (freopen(dbtmpfile, "r", stdin) == NULL)
 469:         syserr("dbtmplt open %s", dbtmpfile);
 470: 
 471:     readdbtemp();
 472: 
 473:     /* check for type -- update database status versus create */
 474:     if (flagval('e'))
 475:         changedb();
 476:     else
 477:         makedb();
 478: 
 479:     /* close the cache descriptors */
 480: #	ifdef xSTR3
 481:     if (tTf(50, 0))
 482:     {
 483:         printf("Attdes.reltid = ");
 484:         dumptid(&Attdes.reltid);
 485:         printf("Reldes.reltid = ");
 486:         dumptid(&Reldes.reltid);
 487:     }
 488: #	endif
 489:     if (i = closer(&Attdes))
 490:         syserr("creatdb: closer(att) %d", i);
 491:     if (i = closer(&Reldes))
 492:         syserr("creatdb: closer(rel) %d", i);
 493: 
 494:     /* bring tupcount in 'admin' file to date */
 495:     bmove(&Reldes.reltups, &Admin.adreld.reltups, sizeof Reldes.reltups);
 496:     bmove(&Attdes.reltups, &Admin.adattd.reltups, sizeof Attdes.reltups);
 497: 
 498:     /* clean up some of the fields to catch problems later */
 499:     Admin.adreld.relfp = Admin.adattd.relfp = -1;
 500:     Admin.adreld.relopn = Admin.adattd.relopn = 0;
 501: 
 502:     if ((admin = creat("admin", FILEMODE)) < 0)
 503:         syserr("main: creat admin");
 504:     if (write(admin, &Admin, sizeof Admin) != sizeof Admin)
 505:         syserr("main: write Admin");
 506:     close(admin);
 507: 
 508:     /* exit successfully */
 509:     exit(0);
 510: }
 511: 
 512: 
 513: 
 514: 
 515: /*
 516: **  Rubout processing.
 517: */
 518: 
 519: rubproc()
 520: {
 521:     exit(-2);
 522: }
 523: /*
 524: **  READDBTEMP -- read the dbtmplt file and build internal form
 525: **
 526: **	This routine reads the dbtmplt file (presumably openned as
 527: **	the standard input) and initializes the Dbstat (global database
 528: **	status word) and Rellist variables.
 529: **
 530: **	Rellist is an array of argument vectors, exactly as passed to
 531: **	'create'.
 532: **
 533: **	The syntax of the dbtmplt file is as follows:
 534: **
 535: **	The first line is a single status word (syntax defined below)
 536: **	which is the database status.
 537: **
 538: **	The rest of the file is sets of lines separated by blank lines.
 539: **	Each set of lines define one relation.  Two blank lines in a
 540: **	row or an end-of-file define the end of the file.  Each set
 541: **	of lines is broken down:
 542: **
 543: **	The first line is in the following format:
 544: **		relname:status
 545: **	which defines the relation name and the relation status for
 546: **	this relation (syntax defined in 'getstat' below).  Status
 547: **	may be omitted, in which case a default status is assumed.
 548: **
 549: **	Second through n'th lines of each set define the attributes.
 550: **	They are of the form:
 551: **		attname		format
 552: **	separated by a single tab.  'Format' is the same as on a
 553: **	'create' statement in QUEL.
 554: **
 555: **	Notice that we force the S_CATALOG bit to be on in any
 556: **	case.  This is because the changedb() routine will fail
 557: **	if the -e flag is ever used on this database if any
 558: **	relation appears to be a user relation.
 559: **
 560: **	Parameters:
 561: **		none
 562: **
 563: **	Returns:
 564: **		none
 565: **
 566: **	Side Effects:
 567: **		Dbstat gets the database status.
 568: **		Rellist is created with a list of the relations,
 569: **			(as parameter vectors -- just as passed to
 570: **			create).  The entry after the last entry
 571: **			has its pv[0] == NULL.
 572: **
 573: **	Requires:
 574: **		getstat -- to read status words.
 575: **		getname -- to read names.
 576: **		Delim -- set to the delimiter which terminated getstat
 577: **			or getname.
 578: **
 579: **	Called By:
 580: **		main
 581: **
 582: **	Trace Flags:
 583: **		none
 584: **
 585: **	Diagnostics:
 586: **		none
 587: **
 588: **	Syserrs:
 589: **		readdbtemp: bad Dbstat -- the Dbstat entry was not
 590: **			terminated with a newline.
 591: **		readdbtemp: bad rel delim -- a relation name entry
 592: **			did not terminate with a newline.
 593: **		readdbtemp: bad att delim -- an attribute entry
 594: **			did not terminate with a colon.
 595: **		readdbtemp: bad type delim -- an attribute type entry
 596: **			did not end with a newline.
 597: */
 598: 
 599: readdbtemp()
 600: {
 601:     static char     buf[MAXDBTEMP];
 602:     register struct reldes  *r;
 603:     register char       **q;
 604:     register int        i;
 605:     int         j;
 606:     char            *p;
 607:     int         defrstat;
 608:     auto int        bitson, bitsoff;
 609: 
 610:     /* read database status */
 611:     defrstat = S_CATALOG | S_NOUPDT | S_CONCUR | S_PROTALL;
 612:     bitson = bitsoff = 0;
 613:     Dbstat = getstat(A_DBCONCUR, &Dbson, &Dbsoff);
 614:     if (Delim == ':')
 615:         defrstat = getstat(defrstat, &bitson, &bitsoff);
 616:     if (Delim != '\n')
 617:         syserr("readdbtemp: bad Dbstat %c", Delim);
 618: 
 619:     /* compute default relation status */
 620: 
 621:     /* start reading relation info */
 622:     p = buf;
 623:     for (r = Rellist; ; r++)
 624:     {
 625:         r->bitson = bitson;
 626:         r->bitsoff = bitsoff;
 627: 
 628:         q = r->parmv;
 629: 
 630:         /* get relation name */
 631:         q[1] = p;
 632:         p += getname(p) + 1;
 633: 
 634:         /* test for end of dbtmplt file */
 635:         if (q[1][0] == 0)
 636:             break;
 637: 
 638:         /* get relation status */
 639:         i = getstat(defrstat, &r->bitson, &r->bitsoff);
 640:         i |= S_CATALOG;     /* guarantee system catalog */
 641:         *q++ = p;
 642:         *p++ = ((i >> 15) & 1) + '0';
 643:         for (j = 12; j >= 0; j -= 3)
 644:             *p++ = ((i >> j) & 07) + '0';
 645:         *p++ = 0;
 646:         q++;
 647:         if (Delim != '\n')
 648:             syserr("readdbtemp: bad rel %c", Delim);
 649: 
 650:         /* read attribute names and formats */
 651:         for (;;)
 652:         {
 653:             /* get attribute name */
 654:             *q++ = p;
 655:             p += getname(p) + 1;
 656:             if (q[-1][0] == 0)
 657:                 break;
 658:             if (Delim != '\t')
 659:                 syserr("readdbtemp: bad att %c", Delim);
 660: 
 661:             /* get attribute type */
 662:             *q++ = p;
 663:             p += getname(p) + 1;
 664:             if (Delim != '\n')
 665:                 syserr("readdbtemp: bad type %c", Delim);
 666:         }
 667: 
 668:         /* insert end of argv signal */
 669:         *--q = NULL;
 670: 
 671:         /* ad-hoc overflow test */
 672:         if (p >= &buf[MAXDBTEMP])
 673:             syserr("readdbtemp: overflow");
 674:     }
 675:     /* mark the end of list */
 676:     q[1] = NULL;
 677: }
 678: /*
 679: **  GETSTAT -- Get status word
 680: **
 681: **	A status word is read from the standard input (presumably
 682: **	'dbtmplt').  The string read is interpreted as an octal
 683: **	number.  The syntax is:
 684: **		N{+c+N[~N]}
 685: **	where N is a number, + is a plus or a minus sign, and c is
 686: **	a flag.  '+c+N1[~N2]' groups are interpreted as follows:
 687: **	If flag 'c' is set (assuming the preceeding character is a +,
 688: **	clear if it is a -), then set (clear) bits N1.  If tilde N2
 689: **	is present, then if flag 'c' is unset (called as '-c' ('+c'))
 690: **	clear (set) bits N2; if ~N2 is not present, clear (set)
 691: **	bits N1.
 692: **
 693: **	For example, an entry might be (but probably isn't):
 694: **		1-c-1+q+6~2
 695: **	having the following meaning:
 696: **
 697: **	1. Default to the 1 bit set.
 698: **
 699: **	2. If the -c flag is specified, clear the '1' bit.  If the
 700: **	+c flag is specified, set the '1' bit.  If it is unspecified,
 701: **	leave the '1' bit alone.
 702: **
 703: **	3. If the +q flag is specified, set the '2' bit and the '4'
 704: **	bit.  If the -q flag is specified, clear the '2' bit (but leave
 705: **	the '4' bit alone).  If the +-q flag is unspecified, leave
 706: **	those bits alone.
 707: **
 708: **	Thus, a database with this entry is initially created with
 709: **	the 1 bit on.  The '4' bit is a history, which says if the
 710: **	'q' flag has ever been set, while the '2' bit tells if it is
 711: **	currently set.
 712: **
 713: **	Parameters:
 714: **		def -- the default to return if there is no number
 715: **			there at all.
 716: **		bitson -- a pointer to a word to contain all the
 717: **			bits to be turned on -- used for the -e flag.
 718: **		bitsoff -- same, for bits turned off.
 719: **
 720: **	Returns:
 721: **		The value of the status word.
 722: **		There are no error returns.
 723: **
 724: **	Side Effects:
 725: **		File activity.
 726: **
 727: **	Requires:
 728: **		getchar -- to get input characters
 729: **		roctal -- to read an octal number.
 730: **		ungetc -- to give a character back during parsing.
 731: **		Delim -- set the the terminating delimitor in roctal().
 732: **		flagval() -- to get the value of a flag.
 733: **
 734: **	Called By:
 735: **		readdbtemp
 736: **
 737: **	Trace Flags:
 738: **		none
 739: **
 740: **	Diagnostics:
 741: **		none
 742: **
 743: **	Syserrs:
 744: **		getstat: bad fmt %c -- a '+' or '-' was expected.
 745: */
 746: 
 747: getstat(def, bitson, bitsoff)
 748: int def;
 749: int *bitson;
 750: int *bitsoff;
 751: {
 752:     register int    c;
 753:     register int    stat;
 754:     register int    i;
 755:     int     setbits;
 756:     int     clrbits;
 757:     char        ctlch;
 758: 
 759:     /* reset bits being turned on and off */
 760:     *bitson = *bitsoff = 0;
 761: 
 762:     /* check to see if a base status word is defined */
 763:     if (Delim == '\n' || (Delim = c = getchar()) < '0' || c > '7')
 764:     {
 765:         /* no, use default */
 766:         stat = def;
 767:     }
 768:     else
 769:     {
 770:         /* read base status field */
 771:         ungetc(c, stdin);
 772:         stat = roctal();
 773:     }
 774: 
 775:     /* scan '+c+N' entries */
 776:     for (;;)
 777:     {
 778:         /* check for a flag present */
 779:         c = Delim;
 780:         if (c == '\n' || c == ':')
 781:             return (stat);
 782:         if (c != '+' && c != '-')
 783:         {
 784:         badfmt:
 785:             syserr("getstat: bad fmt %c", c);
 786:         }
 787: 
 788:         /* we have some flag -- get it's value */
 789:         i = flagval(getchar());
 790: 
 791:         /* save sign char on flag */
 792:         ctlch = c;
 793: 
 794:         /* get sign on associated number and the number */
 795:         c = getchar();
 796:         if (c != '+' && c != '-')
 797:             goto badfmt;
 798:         setbits = roctal();
 799: 
 800:         /* test whether action on -X same as on +X */
 801:         if (Delim == '~')
 802:         {
 803:             /* they have different bits (see above) */
 804:             clrbits = roctal();
 805:         }
 806:         else
 807:         {
 808:             /* on 'creatdb -e -X', use opposite bits of +X */
 809:             clrbits = setbits;
 810:         }
 811: 
 812:         /* test for any effect at all */
 813:         if (i == 0)
 814:             continue;
 815: 
 816:         /* test whether we should process the '+N' */
 817:         if ((ctlch == '-') ? (i < 0) : (i > 0))
 818:             i = setbits;
 819:         else
 820:         {
 821:             i = clrbits;
 822: 
 823:             /* switch sense of bit action */
 824:             if (c == '+')
 825:                 c = '-';
 826:             else
 827:                 c = '+';
 828:         }
 829: 
 830:         if (c == '+')
 831:         {
 832:             stat |= i;
 833:             *bitson |= i;
 834:         }
 835:         else
 836:         {
 837:             stat &= ~i;
 838:             *bitsoff |= i;
 839:         }
 840:     }
 841: }
 842: /*
 843: **  ROCTAL -- Read an octal number from standard input.
 844: **
 845: **	This routine just reads a single octal number from the standard
 846: **	input and returns its value.  It will only read up to a non-
 847: **	octal digit.  It will also skip initial and trailing blanks.
 848: **	'Delim' is set to the next character in the input stream.
 849: **
 850: **	Parameters:
 851: **		none
 852: **
 853: **	Returns:
 854: **		value of octal number in the input stream.
 855: **
 856: **	Side Effects:
 857: **		'Delim' is set to the delimiter which terminated the
 858: **			number.
 859: **		File activity on stdin.
 860: **
 861: **	Requires:
 862: **		getchar() -- to get the input characters.
 863: **		Delim -- as noted above.
 864: **
 865: **	Called By:
 866: **		getstat()
 867: **
 868: **	Trace Flags:
 869: **		none
 870: **
 871: **	Diagnostics:
 872: **		none
 873: **
 874: **	Syserrs:
 875: **		none
 876: */
 877: 
 878: roctal()
 879: {
 880:     register int    c;
 881:     register int    val;
 882: 
 883:     val = 0;
 884: 
 885:     /* skip initial blanks */
 886:     while ((c = getchar()) == ' ')
 887:         continue;
 888: 
 889:     /* get numeric value */
 890:     while (c >= '0' && c <= '7')
 891:     {
 892:         val = (val << 3) | (c - '0');
 893:         c = getchar();
 894:     }
 895: 
 896:     /* skip trailing blanks */
 897:     while (c == ' ')
 898:         c = getchar();
 899: 
 900:     /* set Delim and return numeric value */
 901:     Delim = c;
 902:     return (val);
 903: }
 904: /*
 905: **  GETNAME -- get name from standard input
 906: **
 907: **	This function reads a name from the standard input.  A
 908: **	name is defined as a string of letters and digits.
 909: **
 910: **	The character which caused the scan to terminate is stored
 911: **	into 'Delim'.
 912: **
 913: **	Parameters:
 914: **		ptr -- a pointer to the buffer in which to dump the
 915: **			name.
 916: **
 917: **	Returns:
 918: **		The length of the string.
 919: **
 920: **	Side Effects:
 921: **		File activity on standard input.
 922: **
 923: **	Requires:
 924: **		getchar()
 925: **		Delim
 926: **
 927: **	Called By:
 928: **		readdbtemp
 929: **
 930: **	Trace Flags:
 931: **		none
 932: **
 933: **	Diagnostics:
 934: **		none
 935: **
 936: **	Syserrs:
 937: **		none
 938: */
 939: 
 940: getname(ptr)
 941: char    *ptr;
 942: {
 943:     register int    len;
 944:     register int    c;
 945:     register char   *p;
 946: 
 947:     len = 0;
 948: 
 949:     for (p = ptr; (c = getchar()) != EOF; len++)
 950:     {
 951:         /* check for end of name */
 952:         if ((c < 'a' || c > 'z') &&
 953:             (c < '0' || c > '9'))
 954:             break;
 955: 
 956:         /* store character into buffer */
 957:         *p++ = c;
 958:     }
 959: 
 960:     /* null-terminate the string */
 961:     *p = '\0';
 962: 
 963:     /* store the delimiting character and return length of string */
 964:     Delim = c;
 965:     return (len);
 966: }
 967: /*
 968: **  MAKEDB -- make a database from scratch
 969: **
 970: **	This is the code to make a database if the -e flag is off.
 971: **
 972: **	The first step is to make a copy of the admin file
 973: **	in the internal 'Admin' struct.  This is the code which
 974: **	subsequently gets used by openr and opencatalog.  Notice
 975: **	that the admin file is not written out; this happens after
 976: **	makedb returns.
 977: **
 978: **	Next, the physical files are created with one initial (empty)
 979: **	page.  This has to happen before the 'create' call so
 980: **	that it will be possible to flush 'relation' and 'attribute'
 981: **	relation pages during the creates of the 'relation' and
 982: **	'attribute' relations.  Other relations don't need this,
 983: **	but it is more convenient to be symmetric.
 984: **
 985: **	The next step is to create the relations.  Of course, all
 986: **	this really is is inserting stuff into the system catalogs.
 987: **
 988: **	When we are all done we open the relation relation for the
 989: **	admin cache (which of course should exist now).  Thus,
 990: **	the closer's in main (which must be around to update the
 991: **	tuple count) will work right.
 992: **
 993: **	Parameters:
 994: **		none
 995: **
 996: **	Returns:
 997: **		none
 998: **
 999: **	Side Effects:
1000: **		A database is created!!
1001: **		Several files will be created in the current directory,
1002: **			one for each relation mentioned in the
1003: **			'dbtmplt' file.
1004: **		The 'Admin' struct will be filled in.
1005: **
1006: **	Requires:
1007: **		makefile -- to create the physical file.
1008: **		makereln -- to create the relations.
1009: **		Rellist -- containing the list of relations to be
1010: **			created with specs.
1011: **		makeadmin -- to initialize the Admin struct.
1012: **
1013: **	Called By:
1014: **		main
1015: **
1016: **	Trace Flags:
1017: **		20
1018: **
1019: **	Diagnostics:
1020: **		none
1021: **
1022: **	Syserrs:
1023: **		open(rel)
1024: **			It was not possible to open the relation
1025: **			relation for the Admin.adreld cache.
1026: */
1027: 
1028: makedb()
1029: {
1030:     struct descriptor   d;
1031:     register struct reldes  *r;
1032:     register int        pc;
1033:     register char       **pv;
1034: 
1035: #	ifdef xSTR3
1036:     if (tTf(51, 0))
1037:         printf(">>makedb, Usercode = %s (%u)\n", Usercode, Usercode);
1038: #	endif
1039: 
1040:     /* create the physical files */
1041:     for (r = Rellist; r->parmv[1] != 0; r++)
1042:     {
1043:         makefile(r);
1044:     }
1045: 
1046:     /* initialize the admin file internal cache */
1047:     bmove(Usercode, Admin.adhdr.adowner, 2);
1048:     Admin.adhdr.adflags = Dbstat;
1049:     makeadmin(&Admin.adreld, Rellist[0].parmv);
1050:     makeadmin(&Admin.adattd, Rellist[1].parmv);
1051: 
1052:     /* done with admin initialization */
1053: 
1054:     /* initialize relations */
1055:     for (r = Rellist; r->parmv[1] != 0; r++)
1056:     {
1057:         makereln(r);
1058:     }
1059: }
1060: /*
1061: **  MAKEADMIN -- manually initialize descriptor for admin file
1062: **
1063: **	The relation descriptor pointed to by 'pv' is turned into
1064: **	a descriptor, returned in 'd'.  Presumably, this descriptor
1065: **	is later written out to the admin file.
1066: **
1067: **	Notice that the 'reltid' field is filled in sequentially.
1068: **	This means that the relations put into the admin file
1069: **	must be created in the same order that they are 'made'
1070: **	(by this routine), that the format of tid's must not
1071: **	change, and that there can not be over one page worth of
1072: **	relations in the admin file.  Our current system currently
1073: **	handles this easily.
1074: **
1075: **	Parameters:
1076: **		d -- the descriptor to get the result.
1077: **		pv -- a parm vector in 'create' format, which drives
1078: **			this routine.
1079: **
1080: **	Returns:
1081: **		none
1082: **
1083: **	Side Effects:
1084: **		none
1085: **
1086: **	Requires:
1087: **		ingresname
1088: **		oatoi
1089: **		atoi
1090: **		typeconv
1091: **
1092: **	Called By:
1093: **		main
1094: **
1095: **	Trace Flags:
1096: **		10
1097: **
1098: **	Diagnostics:
1099: **		none
1100: **
1101: **	Syserrs:
1102: **		makeadmin: type err %c -- a bad type specifier
1103: **			occured in the dbtmplt file.
1104: **		makeadmin: len err %s -- a length was specified
1105: **			which was not an integer.
1106: */
1107: 
1108: 
1109: 
1110: makeadmin(d, pv)
1111: struct descriptor   *d;
1112: char            *pv[];
1113: {
1114:     register struct descriptor  *des;
1115:     register char           **p;
1116:     register int            i;
1117:     auto int            len;
1118:     static int          tid;
1119:     char                fname[MAXNAME + 3];
1120: 
1121:     des = d;
1122:     p = pv;
1123: 
1124: #	ifdef xSTR2
1125:     if (tTf(10, -1))
1126:         printf("creating %s in admin\n", p[1]);
1127: #	endif
1128:     i = oatoi(*p++);
1129:     ingresname(*p++, Usercode, fname);
1130:     bmove(fname, des->relid, MAXNAME + 2);
1131:     des->relstat = i;
1132:     des->relatts = 0;
1133:     des->relwid = 0;
1134:     des->relspec = M_HEAP;
1135:     des->reltid = tid++;
1136:     des->relfp = open(fname, 2);
1137:     if (des->relfp < 0)
1138:         syserr("makeadmin: open %s", fname);
1139:     des->relopn = (des->relfp + 1) * -5;
1140: 
1141:     /* initialize domain info */
1142:     for (; *p++ != NULL; p++)
1143:     {
1144:         i = typeconv(p[0][0]);
1145:         if (i < 0)
1146:             syserr("dbtmplt: type err %c", p[0][0]);
1147:         des->relfrmt[++(des->relatts)] = i;
1148:         if (atoi(&p[0][1], &len) != 0)
1149:             syserr("makeadmin: len err %s", p[0]);
1150:         des->relfrml[des->relatts] = len;
1151:         des->reloff[des->relatts] = des->relwid;
1152:         des->relwid += len;
1153:     }
1154: }
1155: /*
1156: **  MAKEFILE -- make an 'empty' file for a relation
1157: **
1158: **	This routine creates a file with a single (empty) page
1159: **	on it -- it is part of the 'create' code, essentially.
1160: **
1161: **	Parameters:
1162: **		rr -- a pointer to the 'reldes' structure for this
1163: **			relation (file).
1164: **
1165: **	Returns:
1166: **		none
1167: **
1168: **	Side Effects:
1169: **		A file with one page is created.
1170: **
1171: **	Requires:
1172: **		ingresname -- to create the actual file name.
1173: **		formatpg -- to put the single page into the relation.
1174: **		creat -- to create the file
1175: **		FILEMODE -- the mode of the created file.
1176: **
1177: **	Called By:
1178: **		makedb
1179: **		changedb
1180: **
1181: **	Trace Flags:
1182: **		12
1183: **
1184: **	Diagnostics:
1185: **		none
1186: **
1187: **	Syserrs:
1188: **		creat %s
1189: **			The file named could not be created.
1190: **		formatpg
1191: **			The 'formatpg' call failed; check the
1192: **			access method error for why.
1193: */
1194: 
1195: makefile(rr)
1196: struct reldes   *rr;
1197: {
1198:     register struct reldes  *r;
1199:     struct descriptor   d;
1200:     long            npages;
1201: 
1202:     r = rr;
1203: 
1204:     ingresname(r->parmv[1], Usercode, d.relid);
1205: #	ifdef xSTR1
1206:     if (tTf(12, 0))
1207:         printf("creat %s\n", d.relid);
1208: #	endif
1209:     if ((d.relfp = creat(d.relid, FILEMODE)) < 0)
1210:         syserr("creat %s", d.relid);
1211:     npages = 1;
1212:     if (formatpg(&d, npages))
1213:         syserr("formatpg");
1214:     close(d.relfp);
1215: }
1216: /*
1217: **  MAKERELN -- make a relation
1218: **
1219: **	This is the second half of the create, started by 'makefile'.
1220: **
1221: **	This routine just sets up argument vectors and calls create,
1222: **	which does the real work.
1223: **
1224: **	Parameters:
1225: **		rr -- a pointer to the Rellist entry for the relation
1226: **			to be created.
1227: **
1228: **	Returns:
1229: **		none
1230: **
1231: **	Side Effects:
1232: **		Information will be inserted into the 'relation' and
1233: **			'attribute' relations.
1234: **
1235: **	Requires:
1236: **		Rellist -- with a list of relations to be created
1237: **			and data descriptions.
1238: **		create -- to actually do the create.
1239: **		'Admin' must be filled in.  Openr must use 'Admin'
1240: **			and never look at the physical 'admin' file.
1241: **
1242: **	Called By:
1243: **		makedb
1244: **		changedb
1245: **
1246: **	Trace Flags:
1247: **		1
1248: **
1249: **	Diagnostics:
1250: **		none
1251: **
1252: **	Syserrs:
1253: **		create %d
1254: **			The call to 'create' failed, for reason
1255: **			given.
1256: */
1257: 
1258: makereln(rr)
1259: struct reldes   *rr;
1260: {
1261:     register struct reldes  *r;
1262:     register int        pc;
1263:     register char       **pv;
1264:     int         i;
1265: 
1266:     r = rr;
1267: 
1268:     pc = 0;
1269:     for (pv = r->parmv; *pv != NULL; pv++)
1270:         pc++;
1271:     pv = r->parmv;
1272: #	ifdef xSTR1
1273:     if (tTf(1, 0))
1274:         prargs(pc, pv);
1275: #	endif
1276:     i = create(pc, pv);
1277:     if (i != 0)
1278:         syserr("create %d", i);
1279: }
1280: /*
1281: **  CHECK -- check database name syntax
1282: **
1283: **	The name of a database is checked for validity.  A valid
1284: **	database name is not more than 14 characters long, begins
1285: **	with an alphabetic character, and contains only alpha-
1286: **	numerics.  Underscore is considered numeric.
1287: **
1288: **	Parameters:
1289: **		st -- the string to check.
1290: **
1291: **	Returns:
1292: **		TRUE -- ok.
1293: **		FALSE -- failure.
1294: **
1295: **	Side Effects:
1296: **		none
1297: **
1298: **	Requires:
1299: **		length -- to check the length of the string.
1300: **
1301: **	Called By:
1302: **		main
1303: **
1304: **	Trace Flags:
1305: **		none
1306: **
1307: **	Diagnostics:
1308: **		none
1309: **
1310: **	Syserrs:
1311: **		none
1312: */
1313: 
1314: check(st)
1315: char    *st;
1316: {
1317:     register char   c;
1318:     register char   *p;
1319: 
1320:     p = st;
1321: 
1322:     /* check string length */
1323:     if (length(p) > 14)
1324:         return (FALSE);
1325: 
1326:     /* check the first character of the string for alphabetic */
1327:     c = *p++;
1328:     if (c < 'a' || c > 'z')
1329:         return (FALSE);
1330: 
1331:     /* check the rest for alphanumeric */
1332:     while ((c = *p++) != 0)
1333:     {
1334:         if (c == '_')
1335:             continue;
1336:         if (c >= '0' && c <= '9')
1337:             continue;
1338:         if (c >= 'a' && c <= 'z')
1339:             continue;
1340:         return (FALSE);
1341:     }
1342:     return (TRUE);
1343: }
1344: /*
1345: **  FLAGLKUP -- look up user flag
1346: **
1347: **	This routine helps support a variety of user flags.  The
1348: **	routine takes a given user flag and looks it up (via a
1349: **	very crude linear search) in the 'Flags' vector, and
1350: **	returns a pointer to the value.
1351: **
1352: **	The 'flag' struct defines the flags.  The 'flagname' field
1353: **	is the character which is the flag id, for example, 'c'
1354: **	in the flag '-c'.  The 'flagtype' field defines how the
1355: **	flag may appear; if negative, only '-c' may appear, if
1356: **	positive, only '+c' may appear; if zero, either form may
1357: **	appear.  Finally, the 'flagval' field is the value of the
1358: **	flag -- it may default any way the user wishes.
1359: **
1360: **	Parameters:
1361: **		flagname -- the name (as defined above) of the
1362: **			flag to be looked up.
1363: **		plusminus -- a character, '+' means the '+x' form
1364: **			was issued, '-' means the '-x' form was
1365: **			issued, something else means *don't care*.
1366: **			If an illegal form was issued (that is,
1367: **			that does not match the 'flagtype' field
1368: **			in the structure), the "not found" return
1369: **			is taken.
1370: **
1371: **	Returns:
1372: **		NULL -- flag not found, or was incorrect type,
1373: **			as when the '+x' form is specified in the
1374: **			parameters, but the 'Flags' struct says
1375: **			that only a '-x' form may appear.
1376: **		else -- pointer to the 'flagval' field of the correct
1377: **			field in the 'Flags' vector.
1378: **
1379: **	Side Effects:
1380: **		none
1381: **
1382: **	Requires:
1383: **		Flags vector -- of type 'struct flag', defined below.
1384: **			This vector should be terminated with a
1385: **			zero 'flagname'.
1386: **
1387: **	Called By:
1388: **		main
1389: **		flagval
1390: **
1391: **	Trace Flags:
1392: **		none
1393: **
1394: **	Diagnostics:
1395: **		none
1396: **
1397: **	Syserrs:
1398: **		none
1399: */
1400: 
1401: struct flag
1402: {
1403:     char    flagname;   /* the name of the flag */
1404:     char    flagtype;   /* -1: -x form; +1: +x form; 0: both */
1405:     int flagval;    /* user-defined value of the flag */
1406: };
1407: 
1408: struct flag Flags[] =
1409: {
1410:     'q',    0,  0,
1411:     'l',    0,  0,
1412:     'c',    0,  0,
1413:     'e',    -1, 0,
1414:     'm',    -1, 0,
1415:     0
1416: };
1417: 
1418: int *
1419: flaglkup(flagname, plusminus)
1420: char    flagname;
1421: char    plusminus;
1422: {
1423:     register char       f;
1424:     register struct flag    *p;
1425:     register char       pm;
1426: 
1427:     f = flagname;
1428:     pm = plusminus;
1429: 
1430:     /* look up flag in vector */
1431:     for (p = Flags; p->flagname != f; p++)
1432:     {
1433:         if (p->flagname == 0)
1434:             return (NULL);
1435:     }
1436: 
1437:     /* found in list -- check type */
1438:     if ((pm == '+' && p->flagtype < 0) ||
1439:         (pm == '-' && p->flagtype > 0))
1440:         return (NULL);
1441: 
1442:     /* type is OK -- return pointer to value */
1443:     return (&p->flagval);
1444: }
1445: /*
1446: **  FLAGVAL -- return value of a flag
1447: **
1448: **	Similar to 'flaglkup', except that the value is returned
1449: **	instead of the address, and no error return can occur.
1450: **
1451: **	Parameters:
1452: **		fx -- the flag to look up (see flaglkup).
1453: **
1454: **	Returns:
1455: **		The value of flag 'fx'.
1456: **
1457: **	Side Effects:
1458: **		none
1459: **
1460: **	Requires:
1461: **		flaglkup()
1462: **
1463: **	Called By:
1464: **		readdbtemp()
1465: **		main()
1466: **
1467: **	Trace Flags:
1468: **		none
1469: **
1470: **	Diagnostics:
1471: **		none
1472: **
1473: **	Syserrs:
1474: **		flagval: flag %c -- the value of a flag which does
1475: **			not exist was asked for.
1476: */
1477: 
1478: flagval(fx)
1479: char    fx;
1480: {
1481:     register char   f;
1482:     register char   *p;
1483: 
1484:     f = fx;
1485: 
1486:     /* get value of flag */
1487:     p = (char *) flaglkup(f, 0);
1488: 
1489:     /* test for error return, syserr if so */
1490:     if (p == NULL)
1491:         syserr("flagval: flag %c", f);
1492: 
1493:     /* return value */
1494:     return (*p);
1495: }
1496: /*
1497: **  CHANGEDB -- change status bits for database/relations
1498: **
1499: **	In this function we change the status bits for use with the
1500: **	-e flag.
1501: **
1502: **	This module always uses the differential status
1503: **	change information, so that existing bits are not touched.
1504: **
1505: **	We check to see that invalid updates, such as turning off
1506: **	query modification when it is already on, can not occur.
1507: **	This is because of potential syserr's when the system is
1508: **	later run, e.g., because of views without instantiations.
1509: **
1510: **	In the second step, the database status is updated.  This is
1511: **	done strictly in-core, and will be updated in the database
1512: **	after we return.
1513: **
1514: **	The list of valid relations are then scanned.  For each
1515: **	relation listed, a series of steps occurs:
1516: **
1517: **	(1) The relation is checked for existance.  If it does not
1518: **	exist, it is created, and we return to the beginning of the
1519: **	loop.  Notice that we don't have to change modes in this
1520: **	case, since it already has been done.
1521: **
1522: **	(2) If the relation does exist, we check to see that it
1523: **	is a system catalog.  If it is not, we have an error, since
1524: **	this is a user relation which just happenned to have the
1525: **	same name.  We inform the user and give up.
1526: **
1527: **	(3) If the relation exists, is a system catalog, and all
1528: **	that, then we check the changes we need to make in the
1529: **	bits.  If no change need be made, we continue the loop;
1530: **	otherwise, we change the bits and replace the tuple in
1531: **	the relation relation.
1532: **
1533: **	(4) If the relation being updated was the "relation" or
1534: **	"attribute" relation, we change the Admin struct accordingly.
1535: **
1536: **	Notice that the result of all this is that all relations
1537: **	which might ever be used exist and have the correct status.
1538: **
1539: **	Notice that it is fatal for either the attribute or relation
1540: **	relations to not exist, since the file is created at the
1541: **	same time that relation descriptors are filled in.  This
1542: **	should not be a problem, since this is only called on an
1543: **	existing database.
1544: **
1545: **	As a final note, we open the attribute relation cache not
1546: **	because we use it, but because we want to do a closer
1547: **	in main() to insure that the tupcount is updated in all
1548: **	cases.
1549: **
1550: **	Parameters:
1551: **		none
1552: **
1553: **	Returns:
1554: **		none
1555: **
1556: **	Side Effects:
1557: **		The database is brought up to date, as described
1558: **			above.
1559: **		Tuples may be added or changed in system catalogs.
1560: **		Files may be created.
1561: **
1562: **	Requires:
1563: **		Dbson, Dbsoff -- bits to set/clear for the database
1564: **			status.
1565: **		opencatalog() -- to open the relation relation.
1566: **		getequal() -- to get the relation relation tuple
1567: **			for specific relations.
1568: **		Rellist -- a list of needed relations and their
1569: **			data description.
1570: **		Reldes -- result of opencatalog() call.
1571: **		replace() -- to update the relstat in the relation
1572: **			relation for entries.
1573: **		Admin struct -- must be filled in with the current
1574: **			contents of the 'admin' file.
1575: **		makefile(), makereln() -- to make the relation
1576: **			if it does not exist at all.
1577: **
1578: **	Called By:
1579: **		main
1580: **
1581: **	Trace Flags:
1582: **		40
1583: **
1584: **	Diagnostics:
1585: **		Relation %s already exists
1586: **			A system catalog which must be created does
1587: **			already exists as a user relation.
1588: **		I'm sorry, it is not possible to turn query modification off.
1589: **			The user tried to turn query modification off.
1590: **			We can't allow this because it could cause
1591: **			a syserr later; for instance, if the user
1592: **			referenced a view which might still hang around
1593: **			the 'relation' catalog.  This would result in
1594: **			an attempt to open the file for the view, which
1595: **			of course does not exist.  BANG!
1596: **
1597: **	Syserrs:
1598: **		getequal
1599: **			getequal() failed.
1600: **		replace %d
1601: **			replace() failed.
1602: */
1603: 
1604: changedb()
1605: {
1606:     register struct reldes  *r;
1607:     struct relation     relk, relt;
1608:     struct tup_id       tid;
1609:     register int        i;
1610: 
1611: #	ifdef xSTR1
1612:     if (tTf(40, 0))
1613:         printf(">>> changedb: Dbson=%o, Dbsoff=%o\n", Dbson, Dbsoff);
1614: #	endif
1615: 
1616:     /* check to see we aren't doing anything illegal */
1617:     if (flagval('q') < 0)
1618:     {
1619:         syserr(0, "I'm sorry, it is not possible to turn query modification off");
1620:     }
1621: 
1622:     /* update the database status field */
1623:     Admin.adhdr.adflags = (Admin.adhdr.adflags | Dbson) & ~Dbsoff;
1624: 
1625:     /* open the system catalog caches */
1626:     opencatalog("relation", 2);
1627:     opencatalog("attribute", 0);
1628: 
1629:     /* scan the relation list:- Rellist */
1630:     for (r = Rellist; r->parmv[1] != 0; r++)
1631:     {
1632:         /* see if this relation exists */
1633:         clearkeys(&Reldes);
1634:         setkey(&Reldes, &relk, r->parmv[1], RELID);
1635:         i = getequal(&Reldes, &relk, &relt, &tid);
1636: 
1637:         if (i < 0)
1638:             syserr("changedb: getequal");
1639: 
1640:         if (i > 0)
1641:         {
1642:             /* doesn't exist, create it */
1643:             printf("Creating relation %s\n", r->parmv[1]);
1644:             makefile(r);
1645:             makereln(r);
1646:         }
1647:         else
1648:         {
1649:             /* exists -- check to make sure it is the right one */
1650:             if ((relt.relstat & S_CATALOG) == 0)
1651:             {
1652:                 /* exists as a user reln -- tough luck buster */
1653:                 printf("Relation %s already exists -- I cannot bring this database\n", r->parmv[1]);
1654:                 printf("  up to date.  Sorry.\n");
1655:                 exit(3);
1656:             }
1657: 
1658:             /* it exists and is the right one -- update status */
1659:             if (r->bitson == 0 && r->bitsoff == 0)
1660:                 continue;
1661: 
1662:             /* actual work need be done */
1663:             relt.relstat = (relt.relstat | r->bitson) & ~r->bitsoff;
1664: 
1665:             /* replace tuple in relation relation */
1666:             i = replace(&Reldes, &tid, &relt, FALSE);
1667:             if (i != 0)
1668:                 syserr("changedb: replace %d", i);
1669: 
1670:             /* update Admin struct if "relation" or "attribute" */
1671:             if (sequal(r->parmv[1], "relation"))
1672:                 Admin.adreld.relstat = relt.relstat;
1673:             else if (sequal(r->parmv[1], "attribute"))
1674:                 Admin.adattd.relstat = relt.relstat;
1675:         }
1676:     }
1677: }
1678: /*
1679: **  READADMIN -- read the admin file into the 'Admin' cache
1680: **
1681: **	This routine opens and reads the 'Admin' cache from the
1682: **	'admin' file in the current directory.
1683: **
1684: **	This version of the routine is modified for creatdb --
1685: **	the '-e' flag is checked, and nothing is performed
1686: **	unless it is set.
1687: **
1688: **	If not set, the 'relation' and 'attribute' relations
1689: **	are opened, and the descriptors for them in the Admin
1690: **	struct are filled in with their file descriptors.
1691: **
1692: **	Parameters:
1693: **		none
1694: **
1695: **	Returns:
1696: **		none
1697: **
1698: **	Side Effects:
1699: **		The 'Admin' struct is filled in.
1700: **		The 'relation...xx' and 'attribute...xx' files are
1701: **			opened.
1702: **
1703: **	Requires:
1704: **		'Admin' struct.
1705: **		'Usercode' must have the user code of the DBA.
1706: **		ingresname() -- to create the physical file name.
1707: **		flagval() -- to test the -e flag.
1708: **
1709: **	Called By:
1710: **		acc_init (accbuf.c)
1711: **		changedb
1712: **
1713: **	Trace Flags:
1714: **		none
1715: **
1716: **	Diagnostics:
1717: **		none
1718: **
1719: **	Syserrs:
1720: **		adminread: open admin
1721: **			It was not possible to open the admin file.
1722: **		adminread: read admin
1723: **			There was a read error when reading the 'admin'
1724: **			file.
1725: **		adminread: open rel
1726: **			It was not possible to open the 'relation..xx'
1727: **			file.
1728: **		adminread: open att
1729: **			It was not possible to open the 'attribute..xx'
1730: **			file.
1731: */
1732: 
1733: readadmin()
1734: {
1735:     register int        i;
1736:     char            relname[MAXNAME + 4];
1737: 
1738:     /* read the stuff from the admin file */
1739:     if (flagval('e'))
1740:     {
1741:         i = open("admin", 0);
1742:         if (i < 0)
1743:             syserr("readadmin: open admin %d", i);
1744:         if (read(i, &Admin, sizeof Admin) != sizeof Admin)
1745:             syserr("readadmin: read err admin");
1746:         close(i);
1747: 
1748:         /* open the physical files for 'relation' and 'attribute' */
1749:         ingresname(Admin.adreld.relid, Admin.adreld.relowner, relname);
1750:         if ((Admin.adreld.relfp = open(relname, 2)) < 0)
1751:             syserr("readadmin: open rel %d", Admin.adreld.relfp);
1752:         ingresname(Admin.adattd.relid, Admin.adattd.relowner, relname);
1753:         if ((Admin.adattd.relfp = open(relname, 2)) < 0)
1754:             syserr("readadmin: open att %d", Admin.adattd.relfp);
1755:         Admin.adreld.relopn = (Admin.adreld.relfp + 1) * -5;
1756:         Admin.adattd.relopn = (Admin.adattd.relfp + 1) * 5;
1757:     }
1758: 
1759:     return (0);
1760: }

Defined functions

changedb defined in line 1604; used 1 times
check defined in line 1314; used 1 times
flaglkup defined in line 1418; used 3 times
flagval defined in line 1478; used 10 times
getname defined in line 940; used 3 times
getstat defined in line 747; used 3 times
main defined in line 241; never used
makeadmin defined in line 1110; used 2 times
makedb defined in line 1028; used 1 times
makefile defined in line 1195; used 2 times
makereln defined in line 1258; used 2 times
readadmin defined in line 1733; never used
readdbtemp defined in line 599; used 1 times
roctal defined in line 878; used 3 times
rubproc defined in line 519; never used

Defined variables

Dbsoff defined in line 228; used 3 times
Dbson defined in line 228; used 3 times
Dbstat defined in line 227; used 2 times
Delim defined in line 236; used 15 times
Flags defined in line 1408; used 1 times
Rellist defined in line 235; used 6 times

Defined struct's

flag defined in line 1401; used 4 times
reldes defined in line 229; used 16 times

Defined macros

MAXDBTEMP defined in line 220; used 2 times
MAXRELNS defined in line 219; used 1 times
Last modified: 1995-02-12
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 6322
Valid CSS Valid XHTML 1.0 Strict