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

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

unix.superglobalmegacorp.com

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