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

unix.superglobalmegacorp.com

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