Annotation of 42BSD/ingres/source/qrymod/protect.c, revision 1.1

1.1     ! root        1: # include      <ingres.h>
        !             2: # include      <aux.h>
        !             3: # include      <catalog.h>
        !             4: # include      <symbol.h>
        !             5: # include      <tree.h>
        !             6: # include      "qrymod.h"
        !             7: # include      <sccs.h>
        !             8: 
        !             9: SCCSID(@(#)protect.c   7.1     2/5/81)
        !            10: 
        !            11: /*
        !            12: **  PROTECT -- protection algorithm
        !            13: **
        !            14: **     This module performs the INGRES protection algorithm, as
        !            15: **     presented in Stonebraker & Rubinstein, "The INGRES Protection
        !            16: **     System", with a few modifications.
        !            17: **
        !            18: **     The basic algorithm is as follows:
        !            19: **
        !            20: **     The algorithm is applied once to each variable used in the
        !            21: **     query.  Each variable has an initial check performed to
        !            22: **     determine applicability -- if the current user owns the
        !            23: **     relation, or if the relation is specially marked as being
        !            24: **     "all access to everyone", then the algorithm is skipped,
        !            25: **     thereby having effectively no restriction.
        !            26: **
        !            27: **     The set of all such variables is computed in 'protect',
        !            28: **     and then 'dopro' is called to process each of those.  This
        !            29: **     is so the protection algorithm does not get applied recursively
        !            30: **     to constraints which define more than one variable.  Notice
        !            31: **     that this could in itself be a protection violation, if it
        !            32: **     were acceptable to reference a relation you do not own in a
        !            33: **     PERMIT statement.
        !            34: **
        !            35: **     The effective query mode for this variable is then computed.
        !            36: **     This is the same as the query mode of the whole query if
        !            37: **     the variable in question is the result variable, otherwise
        !            38: **     it is "retrieve" mode.
        !            39: **
        !            40: **     The next step is to scan the query tree and create sets of
        !            41: **     domains referenced.  Four sets are created:
        !            42: **             uset -- the set of domains updated (actually,
        !            43: **                     referenced in the target list -- on a
        !            44: **                     retrieve, this will be the set of domains
        !            45: **                     retrieved to the user).
        !            46: **             rset -- the set of domains retrieved in some
        !            47: **                     context other than the left hand side of
        !            48: **                     an equal sign.
        !            49: **             aset -- the set of domains aggregated.  This only
        !            50: **                     includes domains aggregated with a simple
        !            51: **                     aggregate (not an aggregate function) with
        !            52: **                     no qualification, since it may be possible
        !            53: **                     to come up with too much information other-
        !            54: **                     wise.
        !            55: **             qset -- the set of domains retrieved for use in
        !            56: **                     a qualification, but never stored.  This
        !            57: **                     includes domains in a qualification of an
        !            58: **                     aggregate or aggregate function.
        !            59: **     For more details of domains in each of these sets, look at
        !            60: **     the routine 'makedset'.
        !            61: **
        !            62: **     If we had a retrieve operation in the first place, we will
        !            63: **     then merge 'uset' into 'rset' and clear 'uset', so that
        !            64: **     now 'uset' only contains domains which are actually updated,
        !            65: **     and 'rset' contains all domains which are retrieved.
        !            66: **
        !            67: **     Now that we know what is referenced, we can scan the protection
        !            68: **     catalog.  We scan the entire catalog once for each variable
        !            69: **     mentioned in the query (except as already taken care of as
        !            70: **     described above).
        !            71: **
        !            72: **     We must create a set of all operations on this variable which
        !            73: **     are not yet resolved, that is, for which no PERMIT statements
        !            74: **     which qualify have been issued.  We store this set in the
        !            75: **     variable "noperm".  As PERMIT statements are found, bits will
        !            76: **     be cleared.  If the variable is not zero by the end of the
        !            77: **     scan of the protection catalog, then we reject the query,
        !            78: **     saying that we don't have permission -- giving us default
        !            79: **     to deny.
        !            80: **
        !            81: **     For each tuple in the protection catalog for this relation,
        !            82: **     we call "proappl" to see if it applies to this query.  This
        !            83: **     routine checks the user, terminal, time of day, and so forth
        !            84: **     (in fact, everything which is query-independent) and tells
        !            85: **     whether this tuple might apply.
        !            86: **
        !            87: **     If the tuple passes this initial check, we then do the query-
        !            88: **     dependent checking.  This amounts to calling "prochk" once
        !            89: **     for each operation (and domain set) in the query.  What we
        !            90: **     get back is a set of operations which this tuple applies to.
        !            91: **     If zero, the tuple doesn't apply at all; otherwise, it
        !            92: **     applies to at least one operation.  If it applies to some-
        !            93: **     thing, we call it "interesting".
        !            94: **
        !            95: **     For "interesting" tuples, we now get the corresponding
        !            96: **     qualification (if one exists), and disjoin it to a set of
        !            97: **     protection constraints held in "pqual".  Also, we mark
        !            98: **     any operations we found as having been done, by clearing
        !            99: **     bits in "noperm".
        !           100: **
        !           101: **     When we have completed scanning the protection catalog,
        !           102: **     we check "noperm".  If it is non-zero, then we have some
        !           103: **     operation for which a PERMIT statement has not been issued,
        !           104: **     and we issue an error message.  If this variable is ok,
        !           105: **     then we go on and try the next variable.
        !           106: **
        !           107: **     When all variables have been accounted for, we check to
        !           108: **     see if we have any qualifications collected from the
        !           109: **     protection algorithm.  If so, we conjoin them to the
        !           110: **     query tree.
        !           111: **
        !           112: **     Finally, we return the root of the modified tree.  This
        !           113: **     tree is guaranteed to have no authorization violations,
        !           114: **     and may be run as a regular query.
        !           115: **
        !           116: **     Parameters:
        !           117: **             root -- the root of the tree.
        !           118: **
        !           119: **     Returns:
        !           120: **             The root of the modified and authorized tree.
        !           121: **
        !           122: **     Side Effects:
        !           123: **             A possible non-local return on access violation.
        !           124: **
        !           125: **     Trace Flags:
        !           126: **             50 - 59
        !           127: */
        !           128: 
        !           129: int Proopmap[MAXPROQM + 1] =
        !           130: {
        !           131:        PRO_RETR,               /* 0 -- mdRETTERM */
        !           132:        PRO_RETR,               /* 1 -- mdRETR */
        !           133:        PRO_APP,                /* 2 -- mdAPP */
        !           134:        PRO_REPL,               /* 3 -- mdREPL */
        !           135:        PRO_DEL,                /* 4 -- mdDEL */
        !           136: };
        !           137: 
        !           138: extern QTREE   Prodes;
        !           139: extern char    Terminal[];
        !           140: extern QTREE   *gettree();
        !           141: 
        !           142: 
        !           143: QTREE *
        !           144: protect(root)
        !           145: QTREE  *root;
        !           146: {
        !           147:        register QTREE  *r;
        !           148:        register int    i;
        !           149:        register int    vn;
        !           150:        register DESC   *d;
        !           151:        int             qmode;
        !           152:        int             varset;
        !           153: 
        !           154:        r = root;
        !           155: 
        !           156: #      ifdef xQTR1
        !           157:        tTfp(50, -1, "\n->PROTECT\n\n");
        !           158: #      endif
        !           159: 
        !           160:        varset = 0;
        !           161: 
        !           162:        /*
        !           163:        **  Scan the range table and create a set of all variables
        !           164:        **  which are 'interesting', that is, on which the protectin
        !           165:        **  algorithm should be performed.
        !           166:        */
        !           167: 
        !           168:        for (vn = 0; vn < MAXVAR + 1; vn++)
        !           169:        {
        !           170:                if (!Qt.qt_rangev[vn].rngvmark)
        !           171:                        continue;
        !           172:                d = Qt.qt_rangev[vn].rngvdesc;
        !           173:                if (d == NULL)
        !           174:                        syserr("null desc vn=%d", vn);
        !           175: 
        !           176:                /* if owner, accept any query */
        !           177:                if (bequal(d->reldum.relowner, Usercode, 2))
        !           178:                        continue;
        !           179: 
        !           180:                /* check for "no restriction" bit asserted (= clear) */
        !           181:                if (!bitset(S_PROTALL, d->reldum.relstat))
        !           182:                        continue;
        !           183:                if (!bitset(S_PROTRET, d->reldum.relstat) &&
        !           184:                    (Qt.qt_qmode == mdRETR || Qt.qt_qmode == mdRET_UNI))
        !           185:                        continue;
        !           186: 
        !           187:                varset |= 1 << vn;
        !           188:        }
        !           189: 
        !           190:        /*
        !           191:        **  For each variable specified in varset (that is, for each
        !           192:        **  variable in the initial query), do the real algorithm.
        !           193:        */
        !           194: 
        !           195:        for (vn = 0; vn < MAXVAR + 1; vn++)
        !           196:        {
        !           197:                if ((varset & (1 << vn)) == 0)
        !           198:                        continue;
        !           199:                d = Qt.qt_rangev[vn].rngvdesc;
        !           200: 
        !           201: #              ifdef xQTR1
        !           202:                if (tTf(50, 1))
        !           203:                        printf("\nvn=%d: %.12s\n", vn, d->reldum.relid);
        !           204: #              endif
        !           205: 
        !           206:                /*
        !           207:                **  Determine the query mode for this variable.  This
        !           208:                **  is not the query mode of the original query,
        !           209:                **  unless the variable is the result variable.
        !           210:                */
        !           211: 
        !           212:                qmode = Qt.qt_qmode;
        !           213:                if (vn != Qt.qt_resvar || qmode == mdRET_UNI)
        !           214:                        qmode = mdRETTERM;
        !           215: 
        !           216: #              ifdef xQTR3
        !           217:                if (qmode == 1 || qmode > 4 || qmode < 0)
        !           218:                        syserr("protect: bad qmode %d", qmode);
        !           219: #              endif
        !           220: 
        !           221:                /* do the interesting part of the algorithm */
        !           222:                dopro(vn, r, qmode, NULL);
        !           223:        }
        !           224: 
        !           225:        /* return the (authorized) tree */
        !           226: #      ifdef xQTR1
        !           227:        if (tTf(50, 15))
        !           228:                treepr(r, "PROTECT->");
        !           229: #      endif
        !           230:        return (r);
        !           231: }
        !           232: /*
        !           233: **  DOPRO -- actually do the protection algorithm
        !           234: **
        !           235: **     This is the guts of it, broken off because it must be called
        !           236: **     recursively on aggregates.  The algorithm is as discussed
        !           237: **     in the module header.
        !           238: **
        !           239: **     Parameters:
        !           240: **             varno -- the variable number of interest.
        !           241: **             root -- the root of the tree to modify.
        !           242: **             qmode -- the effective query mode for this relation.
        !           243: **             byset -- if non-NULL, a set of domains passed back
        !           244: **                     which gets bound out of the aggregate func,
        !           245: **                     in other words, the by list.
        !           246: **
        !           247: **     Returns:
        !           248: **             none
        !           249: **
        !           250: **     Side Effects:
        !           251: **             The tree pointed at by 'root' gets modified.
        !           252: **             Quite possibly 'Qt.qt_rangev' and 'Qt.qt_remap' get clobbered.
        !           253: **
        !           254: **     Called By:
        !           255: **             protect
        !           256: **             makedset -- on aggregates and aggregate functions.
        !           257: **
        !           258: **     Trace Flags:
        !           259: **             51
        !           260: */
        !           261: 
        !           262: dopro(varno, root, qmode, byset)
        !           263: int    varno;
        !           264: QTREE  *root;
        !           265: int    qmode;
        !           266: int    byset[8];
        !           267: {
        !           268:        int             qset[8];
        !           269:        int             uset[8];
        !           270:        int             aset[8];
        !           271:        int             rset[8];
        !           272:        int             zeros[8];
        !           273:        QTREE           *p;
        !           274:        QTREE           *pqual;
        !           275:        register int    i;
        !           276:        register int    vn;
        !           277:        register QTREE  *t;
        !           278:        int             noperm;
        !           279:        int             noqual;
        !           280:        struct protect  prokey, protup;
        !           281:        struct tup_id   lotid, hitid;
        !           282:        struct qvect
        !           283:        {
        !           284:                QTREE   *q_qual;
        !           285:                int     q_mode;
        !           286:        };
        !           287:        struct qvect    quals[4];
        !           288:        int             j;
        !           289:        extern QTREE    *norml();
        !           290:        extern QTREE    *tree();
        !           291:        extern QTREE    *trimqlend();
        !           292: 
        !           293: 
        !           294:        t = root;
        !           295:        vn = varno;
        !           296: 
        !           297:        /* create domain usage sets */
        !           298:        for (i = 0; i < 8; i++)
        !           299:        {
        !           300:                zeros[i] = uset[i] = rset[i] = qset[i] = aset[i] = 0;
        !           301:                if (byset != NULL)
        !           302:                        byset[i] = 0;
        !           303:        }
        !           304: 
        !           305:        /*
        !           306:        **  Create domain usage set for target list side.  There are
        !           307:        **  two general cases: this is the root of the tree, or this
        !           308:        **  is the head of an aggregate.
        !           309:        */
        !           310: 
        !           311:        switch (t->sym.type)
        !           312:        {
        !           313:          case AGHEAD:
        !           314:                /*
        !           315:                **  An aggregate head falls into two classes: simple
        !           316:                **  aggregate and aggregate function.  In an aggregate
        !           317:                **  function, care must be taken to bind the variables
        !           318:                **  in the by-list outside of the aggregate.  We use
        !           319:                **  'rset' as a temporary here.
        !           320:                */
        !           321: 
        !           322:                if (t->left->sym.type == BYHEAD)
        !           323:                {
        !           324:                        /* make by-list set */
        !           325:                        makedset(vn, t->left->left, NULL, rset, aset, qset);
        !           326: 
        !           327:                        /* merge by-list set into qualification set */
        !           328:                        for (i = 0; i < 8; i++)
        !           329:                        {
        !           330:                                if (byset != NULL)
        !           331:                                        byset[i] |= rset[i];
        !           332:                                qset[i] |= rset[i];
        !           333:                                rset[i] = 0;
        !           334:                        }
        !           335: 
        !           336:                        /* make aggregate list set */
        !           337:                        makedset(vn, t->left->right->right, NULL, rset, aset, qset);
        !           338:                }
        !           339:                else
        !           340:                {
        !           341:                        /* simple aggregate */
        !           342: #                      ifdef xQTR3
        !           343:                        if (t->left->sym.type != AOP)
        !           344:                                syserr("dopro: AGHEAD->left %d", t->left->sym.type);
        !           345: #                      endif
        !           346:                        
        !           347:                        /* check for qualification */
        !           348:                        if (t->right->sym.type == QLEND)
        !           349:                        {
        !           350:                                /* simple, unqualified aggregate */
        !           351:                                makedset(vn, t->left->right, NULL, aset, aset, qset);
        !           352:                        }
        !           353:                        else
        !           354:                        {
        !           355: #                              ifdef xQTR3
        !           356:                                if (t->right->sym.type != AND)
        !           357:                                        syserr("dopro: AND=%d", t->right->sym.type);
        !           358: #                              endif
        !           359:                                makedset(vn, t->left->right, NULL, rset, aset, qset);
        !           360:                        }
        !           361:                }
        !           362:                break;
        !           363:        
        !           364:          case ROOT:
        !           365:                makedset(vn, t->left, uset, rset, aset, qset);
        !           366:                break;
        !           367:        }
        !           368: 
        !           369:        /* scan qualification */
        !           370:        makedset(vn, t->right, NULL, qset, aset, qset);
        !           371: 
        !           372:        /* if retrieval, drop the 'update' set */
        !           373:        /* if delete or append, force an apparent update */
        !           374:        switch (qmode)
        !           375:        {
        !           376:          case mdRETTERM:
        !           377:                for (i = 0; i < 8; i++)
        !           378:                        uset[i] = 0;
        !           379:                break;
        !           380: 
        !           381:          case mdDEL:
        !           382:          case mdAPP:
        !           383:                for (i = 0; i < 8; i++)
        !           384:                        uset[i] = -1;
        !           385:                break;
        !           386:        }
        !           387: 
        !           388: #      ifdef xQTR1
        !           389:        if (tTf(51, 2))
        !           390:        {
        !           391:                printf("qmode %d\n", qmode);
        !           392:                pr_set(uset, "uset");
        !           393:                pr_set(rset, "rset");
        !           394:                pr_set(aset, "aset");
        !           395:                pr_set(qset, "qset");
        !           396:        }
        !           397: #      endif
        !           398: 
        !           399:        /* create a bit map of all referenced operations */
        !           400:        noperm = 0;
        !           401:        if (!bequal(uset, zeros, sizeof zeros))
        !           402:                noperm |= Proopmap[qmode];
        !           403:        if (!bequal(rset, zeros, sizeof zeros))
        !           404:                noperm |= PRO_RETR;
        !           405:        if (!bequal(aset, zeros, sizeof zeros))
        !           406:                noperm |= PRO_AGGR;
        !           407:        if (!bequal(qset, zeros, sizeof zeros))
        !           408:                noperm |= PRO_TEST;
        !           409: 
        !           410:        /* if no operation, something is wrong */
        !           411:        if (noperm == 0)
        !           412:                syserr("protect: no oper");
        !           413:        
        !           414:        /* initialize qualification portion */
        !           415:        for (i = 0; i < 4; )
        !           416:                quals[i++].q_qual = NULL;
        !           417:        noqual = FALSE;
        !           418: 
        !           419:        /* check the protection catalog */
        !           420:        opencatalog("protect", 0);
        !           421:        setkey(&Prodes, &prokey, Qt.qt_rangev[vn].rngvdesc->reldum.relid, PRORELID);
        !           422:        setkey(&Prodes, &prokey, Qt.qt_rangev[vn].rngvdesc->reldum.relowner, PRORELOWN);
        !           423:        find(&Prodes, EXACTKEY, &lotid, &hitid, &prokey);
        !           424: 
        !           425:        while ((i = get(&Prodes, &lotid, &hitid, &protup, TRUE)) == 0)
        !           426:        {
        !           427:                if (kcompare(&Prodes, &prokey, &protup) != 0)
        !           428:                        continue;
        !           429: 
        !           430: #              ifdef xQTR2
        !           431:                if (tTf(51, 4))
        !           432:                {
        !           433:                        printf("PROTECT: ");
        !           434:                        printup(&Prodes, &protup);
        !           435:                }
        !           436: #              endif
        !           437: 
        !           438:                /* check if this is the correct user, terminal, etc */
        !           439:                if (!proappl(&protup))
        !           440:                        continue;
        !           441:                
        !           442:                /* alright, let's check the operation */
        !           443:                i = 0;
        !           444:                if (qmode != mdRETTERM)
        !           445:                        i = quals[0].q_mode = prochk(Proopmap[qmode], uset, &protup);
        !           446:                i |= quals[1].q_mode = prochk(PRO_RETR, rset, &protup);
        !           447:                i |= quals[2].q_mode = prochk(PRO_AGGR, aset, &protup);
        !           448:                i |= quals[3].q_mode = prochk(PRO_TEST, qset, &protup);
        !           449: 
        !           450: #              ifdef xQTR2
        !           451:                if (tTf(51, 5))
        !           452:                        printf("Satisfies operations %o\n", i);
        !           453: #              endif
        !           454: 
        !           455:                /* see if this tuple is "interesting" */
        !           456:                if (i == 0)
        !           457:                        continue;
        !           458:                
        !           459:                /* it is!  get the qualification (if any) */
        !           460:                if (protup.protree >= 0)
        !           461:                {
        !           462:                        p = gettree(Qt.qt_rangev[vn].rngvdesc->reldum.relid,
        !           463:                                    Qt.qt_rangev[vn].rngvdesc->reldum.relowner,
        !           464:                                    mdPROT, protup.protree, FALSE);
        !           465: #                      ifdef xQTR2
        !           466:                        if (tTf(51, 6))
        !           467:                                treepr(p, "Protection Clause");
        !           468: #                      endif
        !           469:                        p = trimqlend(p->right);
        !           470: #                      ifdef xQTR3
        !           471:                        /* check for a non-null qualification */
        !           472:                        if (p == NULL)
        !           473:                                syserr("protect: null tree");
        !           474: #                      endif
        !           475: 
        !           476:                        /* translate to the interesting variable */
        !           477:                        j = protup.proresvar;
        !           478:                        if (Qt.qt_remap[j] >= 0)
        !           479:                                j = Qt.qt_remap[j];
        !           480:                        mergevar(j, varno, p);
        !           481: 
        !           482:                        /* disjoin the protection qual to real qual */
        !           483:                        for (j = 0; j < 4; j++)
        !           484:                        {
        !           485:                                if (quals[j].q_mode == 0)
        !           486:                                        continue;
        !           487:                                if (quals[j].q_qual == NULL)
        !           488:                                        quals[j].q_qual = p;
        !           489:                                else
        !           490:                                        quals[j].q_qual = tree(quals[j].q_qual, p, OR, 0);
        !           491:                        }
        !           492:                }
        !           493:                else
        !           494:                        noqual = TRUE;
        !           495: 
        !           496:                /* mark this operation as having been handled */
        !           497:                noperm &= ~i;
        !           498:        }
        !           499: 
        !           500:        /* test 'get' return code */
        !           501:        if (i < 0)
        !           502:                syserr("protect: get");
        !           503: 
        !           504: #      ifdef xQTR1
        !           505:        if (tTf(51, 12))
        !           506:                printf("No perm on %o\n", noperm);
        !           507: #      endif
        !           508: 
        !           509:        /* see if no tuples applied for some operation */
        !           510:        if (noperm != 0)
        !           511:                qmerror(3500, Qt.qt_qmode, vn, 0);
        !           512:        
        !           513:        /* see if we want to modify the query at all */
        !           514:        if (!noqual)
        !           515:        {
        !           516:                /* conjoin the qualification */
        !           517:                pqual = NULL;
        !           518:                for (i = 0; i < 4; i++)
        !           519:                        if (quals[i].q_qual != NULL)
        !           520:                                if (pqual == NULL)
        !           521:                                        pqual = quals[i].q_qual;
        !           522:                                else
        !           523:                                        pqual = tree(pqual, quals[i].q_qual, AND, 0);
        !           524:                pqual = tree(pqual, tree(NULL, NULL, QLEND, 0), AND, 0);
        !           525:                appqual(pqual, t);
        !           526: 
        !           527:                /* normalize the tree */
        !           528:                t->right = norml(trimqlend(t->right));
        !           529:        }
        !           530: }
        !           531: /*
        !           532: **  MAKEDSET -- make domain reference sets
        !           533: **
        !           534: **     This routine creates some sets which reflect the usage of
        !           535: **     domains for a particular variable.
        !           536: **
        !           537: **     The interesting nodes are 'case' labels in the large
        !           538: **     switch statement which comprises most of the code.  To
        !           539: **     describe briefly:
        !           540: **
        !           541: **     VAR nodes are easy: if they are for the current variable,
        !           542: **             set the bit corresponding to the domain in the
        !           543: **             'retrieval' set.  They can have no descendents,
        !           544: **             so just return.
        !           545: **     RESDOM nodes are also easy: they can be handled the same,
        !           546: **             but the bit is set in the 'update' set instead.
        !           547: **     AGHEAD nodes signal the beginning of an aggregate or
        !           548: **             aggregate function.  In this case, we scan the
        !           549: **             qualification first (noting that RESDOM and VAR
        !           550: **             nodes are processed as 'qualification' sets
        !           551: **             instead of 'retrieval' or 'update' sets).  Then,
        !           552: **             if the aggregate has a WHERE clause or a BY list,
        !           553: **             we treat it as a retrieve; otherwise, we call our-
        !           554: **             selves recursively treating VAR nodes as 'aggregate'
        !           555: **             types rather than 'retrieve' types.
        !           556: **     BYHEAD nodes signal the beginning of a BY list.  The left
        !           557: **             subtree (the actual BY-list) is processed with
        !           558: **             RESDOM nodes ignored (since they are pseudo-domains
        !           559: **             anyhow) and VAR nodes mapped into the 'qualification'
        !           560: **             set.  Then we check the right subtree (which better
        !           561: **             begin with an AOP node!) and continue processing.
        !           562: **     AOP nodes must have a null left subtree, so we just drop
        !           563: **             to the right subtree and iterate.  Notice that we
        !           564: **             do NOT map VAR nodes into the 'aggregate' set for
        !           565: **             this node, since this has already been done by the
        !           566: **             AGHEAD node; also, this aggregate might be counted
        !           567: **             as a retrieve operation instead of an aggregate
        !           568: **             operation (as far as the protection system is con-
        !           569: **             cerned) -- this has been handled by the AGHEAD
        !           570: **             node.
        !           571: **     All other nodes are processed recursively along both edges.
        !           572: **
        !           573: **     Parameters:
        !           574: **             vn -- the variable number that we are currently
        !           575: **                     interested in.
        !           576: **             tree -- the root of the tree to scan.  Notice that this
        !           577: **                     will in general be only one half of the tree --
        !           578: **                     makedset will be called once for the target
        !           579: **                     list and once for the qualification, with
        !           580: **                     different sets for the following parameters.
        !           581: **             uset -- adjusted to be the set of all domains
        !           582: **                     updated.
        !           583: **             rset -- adjusted to be the set of all domains
        !           584: **                     retrieved implicitly, that is, on the right-
        !           585: **                     hand-side of an assignment operator.
        !           586: **             aset -- adjusted to be the set of all domains
        !           587: **                     aggregated.  Notice that this set is not
        !           588: **                     adjusted explicitly, but rather is passed
        !           589: **                     to recursive incarnations of this routine
        !           590: **                     as 'rset'.
        !           591: **             qset -- adjusted to be the set of domains retrieved
        !           592: **                     implicitly in a qualification.  Like 'aset',
        !           593: **                     this is passed as 'rset' to recursive
        !           594: **                     incarnations.
        !           595: **
        !           596: **     Returns:
        !           597: **             none
        !           598: **
        !           599: **     Side Effects:
        !           600: **             none
        !           601: **
        !           602: **     Called By:
        !           603: **             protect() -- in two places.
        !           604: **
        !           605: **     Trace Flags:
        !           606: **             53
        !           607: **
        !           608: */
        !           609: 
        !           610: makedset(vn, tree, uset, rset, aset, qset)
        !           611: int    vn;
        !           612: QTREE  *tree;
        !           613: int    uset[8];
        !           614: int    rset[8];
        !           615: int    aset[8];
        !           616: int    qset[8];
        !           617: {
        !           618:        register QTREE  *t;
        !           619:        register int    i;
        !           620:        int             byset[8];
        !           621: 
        !           622:        t = tree;
        !           623: 
        !           624: #      ifdef xQTR1
        !           625:        if (tTf(53, 0))
        !           626:        {
        !           627:                printf("->makedset\n");
        !           628:                pr_set(uset, "uset");
        !           629:                pr_set(rset, "rset");
        !           630:                pr_set(aset, "aset");
        !           631:                pr_set(qset, "qset");
        !           632:        }
        !           633: #      endif
        !           634: 
        !           635:        while (t != NULL)
        !           636:        {
        !           637:                switch (t->sym.type)
        !           638:                {
        !           639:                  case VAR:
        !           640:                        if (t->sym.value.sym_var.varno == vn)
        !           641:                                lsetbit(t->sym.value.sym_var.attno, rset);
        !           642:                        break;
        !           643: 
        !           644:                  case AGHEAD:
        !           645:                        /* do protection on qualification */
        !           646:                        dopro(vn, t, -1, byset);
        !           647: 
        !           648:                        /* merge by-list set into qualification set */
        !           649:                        for (i = 0; i < 8; i++)
        !           650:                                qset[i] |= byset[i];
        !           651: 
        !           652:                        break;
        !           653: 
        !           654:                  case BYHEAD:
        !           655:                  case AOP:
        !           656:                        syserr("makedset: node %d", t->sym.type);
        !           657: 
        !           658:                  case RESDOM:
        !           659:                        if (t->sym.value.sym_resdom.resno == 0)
        !           660:                        {
        !           661:                                /* tid -- ignore right subtree (and this node) */
        !           662:                                t = t->left;
        !           663:                                continue;
        !           664:                        }
        !           665:                        if (uset != NULL)
        !           666:                                lsetbit(t->sym.value.sym_resdom.resno, uset);
        !           667:                        /* explicit fall-through to "default" case */
        !           668: 
        !           669:                  default:
        !           670:                        /* handle left subtree (recursively) */
        !           671:                        makedset(vn, t->left, uset, rset, aset, qset);
        !           672: 
        !           673:                        /* handle right subtree (iteratively) */
        !           674:                        t = t->right;
        !           675:                        continue;
        !           676:                }
        !           677:                break;
        !           678:        }
        !           679: 
        !           680: #      ifdef xQTR1
        !           681:        if (tTf(53, 15))
        !           682:        {
        !           683:                printf("makedset->\n");
        !           684:                pr_set(uset, "uset");
        !           685:                pr_set(rset, "rset");
        !           686:                pr_set(aset, "aset");
        !           687:                pr_set(qset, "qset");
        !           688:        }
        !           689: #      endif
        !           690: 
        !           691:        return;
        !           692: }
        !           693: /*
        !           694: **  PROAPPL -- check for protection tuple applicable
        !           695: **
        !           696: **     A given protection catalog tuple is checked in a query-
        !           697: **     independent way for applicability.
        !           698: **
        !           699: **     This routine checks such environmental constraints as the
        !           700: **     user, the terminal, and the time of day.  The code is
        !           701: **     fairly straightforward, just take a look.
        !           702: **
        !           703: **     One note: the user and terminal codes contained in the
        !           704: **     protection catalog are blank to mean 'any value' of the
        !           705: **     corresponding field.
        !           706: **
        !           707: **     Parameters:
        !           708: **             protup -- the protection tuple to compare against.
        !           709: **
        !           710: **     Returns:
        !           711: **             TRUE -- this tuple applies to the current environment.
        !           712: **             FALSE -- this tuple does not apply.
        !           713: **
        !           714: **     Side Effects:
        !           715: **             none (unless you include trashing the static vector
        !           716: **                     returned by localtime).
        !           717: **
        !           718: **     Called By:
        !           719: **             protect()
        !           720: **
        !           721: **     Trace Flags:
        !           722: **             54
        !           723: */
        !           724: 
        !           725: proappl(protup)
        !           726: struct protect *protup;
        !           727: {
        !           728:        register struct protect *p;
        !           729:        int                     tvect[2];
        !           730:        register int            *tt;
        !           731:        extern int              *localtime();
        !           732:        register int            mtime;
        !           733: 
        !           734:        p = protup;
        !           735: 
        !           736:        /* check for correct user [insert clique code here] */
        !           737:        if (!bequal("  ", p->prouser, 2))
        !           738:        {
        !           739:                if (!bequal(p->prouser, Usercode, 2))
        !           740:                {
        !           741: # ifdef xQTR2
        !           742:                        if (tTf(54, 0))
        !           743:                                printf("  ~user\n");
        !           744: # endif
        !           745:                        return (FALSE);
        !           746:                }
        !           747:        }
        !           748: 
        !           749:        /* check for correct terminal */
        !           750:        if (p->proterm[0] != ' ')
        !           751:        {
        !           752:                if (!sequal(p->proterm, Terminal))
        !           753:                {
        !           754: # ifdef xQTR2
        !           755:                        if (tTf(54, 0))
        !           756:                                printf("  ~term\n");
        !           757: # endif
        !           758:                        return (FALSE);
        !           759:                }
        !           760:        }
        !           761: 
        !           762:        /* check for correct time of day & week */
        !           763:        time(tvect);
        !           764:        tt = localtime(tvect);
        !           765:        mtime = tt[2] * 60 + tt[1];
        !           766: 
        !           767:        if (p->protodbgn > mtime || p->protodend < mtime)
        !           768:        {
        !           769: # ifdef xQTR2
        !           770:                if (tTf(54, 0))
        !           771:                        printf("  ~tod\n");
        !           772: # endif
        !           773:                return (FALSE);
        !           774:        }
        !           775:        if (p->prodowbgn > tt[6] || p->prodowend < tt[6])
        !           776:        {
        !           777: # ifdef xQTR2
        !           778:                if (tTf(54, 0))
        !           779:                        printf("  ~dow\n");
        !           780: # endif
        !           781:                return (FALSE);
        !           782:        }
        !           783: 
        !           784:        /* hasn't failed yet -- I guess it's ok */
        !           785:        return (TRUE);
        !           786: }
        !           787: /*
        !           788: **  PROCHK -- query-dependent protection tuple check
        !           789: **
        !           790: **     This routine does the query-dependent part of checking
        !           791: **     the validity of a protection tuple.  Unlike proappl,
        !           792: **     which looked at aspects of the environment but not the
        !           793: **     query being run, this routine assumes that the environ-
        !           794: **     ment is ok, and checks that if it applies to this tuple.
        !           795: **
        !           796: **     Two things are checked.  The first is if this tuple applies
        !           797: **     to the operation in question (passed as 'inbit').  The
        !           798: **     second is if the set of domains in the tuple contains the
        !           799: **     set of domains in the query.  If either of these fail,
        !           800: **     the return is zero.  Otherwise the return is the operation
        !           801: **     bit.  In otherwise, the return is the operation to which
        !           802: **     this tuple applies (if any).
        !           803: **
        !           804: **     As a special check, the domain set is checked for all
        !           805: **     zero.  If so, no domains have been referenced for this
        !           806: **     operation at all, and we return zero.  In other words, this
        !           807: **     tuple might apply to this operation, but since we don't
        !           808: **     use the operation anyhow we will ignore it.  It is important
        !           809: **     to handle things in this way so that the qualification for
        !           810: **     this tuple doesn't get appended if the variable is not
        !           811: **     used in a particular context.
        !           812: **
        !           813: **     Parameters:
        !           814: **             inbit -- the bit describing the operation to be
        !           815: **                     checked.  Note that only one bit should
        !           816: **                     be set in this word, although this is
        !           817: **                     not checked.
        !           818: **             domset -- the set of domains actually referenced
        !           819: **                     in this query for the operation described
        !           820: **                     by 'inbit'.
        !           821: **             protup -- the tuple in question.
        !           822: **
        !           823: **     Returns:
        !           824: **             The operation (if any) to which this tuple applies.
        !           825: **
        !           826: **     Side Effects:
        !           827: **             none
        !           828: **
        !           829: **     Called By:
        !           830: **             protect() -- in four places.
        !           831: **
        !           832: **     Trace Flags:
        !           833: **             55
        !           834: */
        !           835: 
        !           836: prochk(inbit, domset, protup)
        !           837: int            inbit;
        !           838: int            domset[8];
        !           839: struct protect *protup;
        !           840: {
        !           841:        register struct protect *p;
        !           842:        register int            *d;
        !           843:        register int            i;
        !           844: 
        !           845:        p = protup;
        !           846:        d = domset;
        !           847: 
        !           848: #      ifdef xQTR1
        !           849:        if (tTf(55, 0))
        !           850:        {
        !           851:                printf("->prochk, inbit=%o, proopset=%o\n", inbit, p->proopset);
        !           852:                pr_set(d, "domset");
        !           853:                pr_set(p->prodomset, "prodomset");
        !           854:        }
        !           855: #      endif
        !           856: 
        !           857:        /* check for null domain set, if so return zero */
        !           858:        for (i = 0; i < 8; i++)
        !           859:                if (d[i] != 0)
        !           860:                        break;
        !           861:        if (i >= 8)
        !           862:        {
        !           863: #              ifdef xQTR2
        !           864:                tTfp(55, 15, "prochk-> null set\n");
        !           865: #              endif
        !           866:                return (0);
        !           867:        }
        !           868: 
        !           869:        /* see if this tuple applies to this operation */
        !           870:        if ((inbit & p->proopset) == 0)
        !           871:        {
        !           872: #              ifdef xQTR2
        !           873:                tTfp(55, 15, "prochk-> no op\n");
        !           874: #              endif
        !           875:                return (0);
        !           876:        }
        !           877: 
        !           878:        /* check if domains are a subset */
        !           879:        for (i = 0; i < 8; i++)
        !           880:        {
        !           881:                if ((d[i] & ~p->prodomset[i]) != 0)
        !           882:                {
        !           883:                        /* failure */
        !           884: #                      ifdef xQTR2
        !           885:                        tTfp(55, 15, "prochk-> not subset\n");
        !           886: #                      endif
        !           887:                        return (0);
        !           888:                }
        !           889:        }
        !           890: 
        !           891:        /* this is hereby an "interesting" tuple */
        !           892: #      ifdef xQTR2
        !           893:        if (tTf(55, 15))
        !           894:                printf("prochk-> %d\n", inbit);
        !           895: #      endif
        !           896:        return (inbit);
        !           897: }
        !           898: 
        !           899: # ifdef xQTR1
        !           900: 
        !           901: /*
        !           902: **  PR_SET -- print set for debugging
        !           903: **
        !           904: **     This routine prints a 128-bit set for debugging.
        !           905: **
        !           906: **     Parameters:
        !           907: **             xset -- the set to convert.
        !           908: **             labl -- a label to print before the set.
        !           909: **
        !           910: **     Returns:
        !           911: **             a pointer to the converted string.
        !           912: **
        !           913: **     Side Effects:
        !           914: **             none
        !           915: */
        !           916: 
        !           917: pr_set(xset, labl)
        !           918: short  xset[8];
        !           919: char   *labl;
        !           920: {
        !           921:        register short  *x;
        !           922:        register int    i;
        !           923:        register long   *y;
        !           924: 
        !           925:        printf("\t%s: ", labl);
        !           926:        x = xset;
        !           927:        y = (long *) x;
        !           928:        if (x == NULL)
        !           929:        {
        !           930:                printf("<NULL>\n");
        !           931:                return;
        !           932:        }
        !           933:        for (i = 7; i >= 0; i--)
        !           934:                printf("%x/", x[i]);
        !           935:        printf(" <> ");
        !           936:        for (i = 0; i < 4; i++)
        !           937:                printf("/%ld", y[i]);
        !           938:        printf("\n");
        !           939: }
        !           940: 
        !           941: # endif

unix.superglobalmegacorp.com

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