home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / ingres04.lzh / source / qrymod / d_prot.c < prev    next >
Encoding:
C/C++ Source or Header  |  1985-02-08  |  11.2 KB  |  488 lines

  1. # include    <ingres.h>
  2. # include    <aux.h>
  3. # include    <catalog.h>
  4. # include    <access.h>
  5. # include    <tree.h>
  6. # include    <symbol.h>
  7. # include    <lock.h>
  8. # include    <pv.h>
  9. # include    <func.h>
  10. # include    "qrymod.h"
  11. # include    <sccs.h>
  12. # include    <errors.h>
  13.  
  14. SCCSID(@(#)d_prot.c    8.3    2/8/85)
  15.  
  16.  
  17.  
  18. /*
  19. **  D_PROT -- define protection constraint
  20. **
  21. **    A protection constraint as partially defined by the last tree
  22. **    defined by d_tree is defined.
  23. **
  24. **    The stuff that comes through the pipe as parameters is complex.
  25. **    It comes as a sequence of strings:
  26. **     # The operation set, already encoded in the parser into a
  27. **       bit map.  If the PRO_RETR permission is set, the PRO_TEST
  28. **       and PRO_AGGR permissions will also be set.
  29. **     # The relation name.
  30. **     # The relation owner.
  31. **     # The user name.  This must be a user name as specified in
  32. **       the 'users' file, or the keyword 'all', meaning all users.
  33. **     # The terminal id.  Must be a string of the form 'ttyx' or
  34. **       the keyword 'all'.
  35. **     # The starting time of day, as minutes-since-midnight.
  36. **     # The ending time of day.
  37. **     # The starting day-of-week, with 0 = Sunday.
  38. **     # The ending dow.
  39. **
  40. **    The domain reference set is build automatically from the
  41. **    target list of the tree.  Thus, the target list must exist,
  42. **    but it is not inserted into the tree.  The target list must
  43. **    be a flat sequence of RESDOM nodes with VAR nodes hanging
  44. **    of the rhs; also, the VAR nodes must all be for Qt.qt_resvar.
  45. **    If there is no target list on the tree, the set of all var-
  46. **    iables is assumed.
  47. **
  48. **    The relstat field in the relation relation is updated to
  49. **    reflect any changes.
  50. **
  51. **    It only makes sense for the DBA to execute this command.
  52. **
  53. **    If there is one of the special cases
  54. **        permit all to all
  55. **        permit retrieve to all
  56. **    it is caught, and the effect is achieved by diddling
  57. **    relstat bits instead of inserting into the protect catalog.
  58. **
  59. **    Parameters:
  60. **        none
  61. **
  62. **    Returns:
  63. **        none
  64. **
  65. **    Side Effects:
  66. **        Activity in 'protect' and 'relation' catalogs.
  67. **
  68. **    Trace Flags:
  69. **        59
  70. */
  71.  
  72. extern struct admin    Admin;
  73. extern DESC        Prodes;
  74. extern DESC        Reldes;
  75.  
  76. extern        d_prot(), null_fn();
  77. extern short    tTqm[80];
  78.  
  79. struct fn_def    DefProFn =
  80. {
  81.     "DPROT",
  82.     d_prot,
  83.     null_fn,
  84.     null_fn,
  85.     NULL,
  86.     0,
  87.     tTqm,
  88.     80,
  89.     'Q',
  90.     0
  91. };
  92.  
  93. d_prot(pc, pv)
  94. int    pc;
  95. PARM    *pv;
  96. {
  97.     struct protect    protup;
  98.     struct tup_id    protid;
  99.     struct protect    prokey;
  100.     struct protect    proxtup;
  101.     char        buf[30];
  102.     char        ubuf[MAXLINE + 1];
  103.     register int    i;
  104.     auto short    ix;
  105.     int        treeid;
  106.     register QTREE    *t;
  107.     QTREE        *root;
  108.     register char    *p;
  109.     struct relation    reltup;
  110.     struct relation    relkey;
  111.     struct tup_id    reltid;
  112.     int        relstat;
  113.     int        all_pro;
  114.  
  115.     /*
  116.     **  Fill in the protection tuple with the information
  117.     **    from the parser, validating as we go.
  118.     **
  119.     **    Also, determine if we have a PERMIT xx to ALL
  120.     **    with no further qualification case.  The variable
  121.     **    'all_pro' is set to reflect this.
  122.     */
  123.  
  124.     clr_tuple(&Prodes, &protup);
  125.     all_pro = TRUE;
  126.  
  127.     /* read operation set */
  128.     if (pv->pv_type != PV_INT)
  129.         syserr("d_prot: opset");
  130.     protup.proopset = pv->pv_val.pv_int;
  131.     if ((protup.proopset & PRO_RETR) != 0)
  132.         protup.proopset |= PRO_TEST | PRO_AGGR;
  133.     pv++;
  134.  
  135.     /* read relation name */
  136.     if (pv->pv_type != PV_STR)
  137.         syserr("d_prot: relid");
  138.     pmove(pv->pv_val.pv_str, protup.prorelid, MAXNAME, ' ');
  139.     pv++;
  140.  
  141.     /* read relation owner */
  142.     if (pv->pv_type != PV_STR)
  143.         syserr("d_prot: relid");
  144.     bmove(pv->pv_val.pv_str, protup.prorelown, 2);
  145.     pv++;
  146.  
  147.     /* read user name */
  148.     if (pv->pv_type != PV_STR)
  149.         syserr("d_prot: user");
  150.     if (sequal(pv->pv_val.pv_str, "all"))
  151.         bmove("  ", protup.prouser, 2);
  152.     else
  153.     {
  154.         /* look up user in 'users' file */
  155.         if (getnuser(pv->pv_val.pv_str, ubuf))
  156.             qmerror(BADUSRNAME, -1, Qt.qt_resvar, pv->pv_val.pv_str, 0);
  157.         for (p = ubuf; *p != ':' && *p != 0; p++)
  158.             continue;
  159.         bmove(++p, protup.prouser, 2);
  160.         if (p[0] == ':' || p[1] == ':' || p[2] != ':')
  161.             syserr("d_prot: users %s", ubuf);
  162.         all_pro = FALSE;
  163.     }
  164.     pv++;
  165.  
  166.     /* read terminal id */
  167.     if (pv->pv_type != PV_STR)
  168.         syserr("d_prot: user");
  169.     if (sequal(pv->pv_val.pv_str, "all"))
  170.         pmove("", protup.proterm, sizeof protup.proterm, ' ');
  171.     else
  172.     {
  173.         pmove(pv->pv_val.pv_str, protup.proterm, sizeof protup.proterm, ' ');
  174.         if (!isttyname(pv->pv_val.pv_str))
  175.             qmerror(BADTERM, -1, Qt.qt_resvar, pv->pv_val.pv_str, 0);
  176.         all_pro = FALSE;
  177.     }
  178.     pv++;
  179.  
  180.     /* read starting time of day */
  181.     if (pv->pv_type != PV_INT)
  182.         syserr("d_prot: btod");
  183.     protup.protodbgn = pv->pv_val.pv_int;
  184.     if (pv->pv_val.pv_int > 0)
  185.         all_pro = FALSE;
  186.     pv++;
  187.     
  188.     /* read ending time of day */
  189.     if (pv->pv_type != PV_INT)
  190.         syserr("d_prot: etod");
  191.     protup.protodend = pv->pv_val.pv_int;
  192.     if (pv->pv_val.pv_int < 24 * 60 - 1)
  193.         all_pro = FALSE;
  194.     pv++;
  195.  
  196.     /* read beginning day of week */
  197.     if (pv->pv_type != PV_STR)
  198.         syserr("d_prot: bdow");
  199.     i = cvt_dow(pv->pv_val.pv_str);
  200.     if (i < 0)
  201.         qmerror(BADDOW, -1, Qt.qt_resvar, pv->pv_val.pv_str, 0);    /* bad dow */
  202.     protup.prodowbgn = i;
  203.     if (i > 0)
  204.         all_pro = FALSE;
  205.     pv++;
  206.  
  207.     /* read ending day of week */
  208.     if (pv->pv_type != PV_STR)
  209.         syserr("d_prot: edow");
  210.     i = cvt_dow(pv->pv_val.pv_str);
  211.     if (i < 0)
  212.         qmerror(BADDOW, -1, Qt.qt_resvar, pv->pv_val.pv_str, 0);    /* bad dow */
  213.     protup.prodowend = i;
  214.     if (i < 6)
  215.         all_pro = FALSE;
  216.     pv++;
  217.  
  218.     /*
  219.     **  Check for valid tree:
  220.     **    There must be a tree defined, and all variables
  221.     **    referenced must be owned by the current user; this
  222.     **    is because you could otherwise get at data by
  223.     **    mentioning it in a permit statement; see protect.c
  224.     **    for a better explanation of this.
  225.     */
  226.  
  227.     if (pv->pv_type != PV_QTREE)
  228.         syserr("d_prot: tree");
  229.     root = (QTREE *) pv->pv_val.pv_qtree;
  230.     pv++;
  231.  
  232.     for (i = 0; i < MAXVAR + 1; i++)
  233.     {
  234.         if (Qt.qt_rangev[i].rngvdesc == NULL)
  235.             continue;
  236.         if (!bequal(Qt.qt_rangev[i].rngvdesc->reldum.relowner, Usercode, UCODE_SZ))
  237.             qmerror(OWNEDNOT, -1, i, 0);
  238.     }
  239.  
  240.     /* test for dba */
  241.     if (!bequal(Usercode, Admin.adhdr.adowner, UCODE_SZ))
  242.         qmerror(NOTDBA, -1, Qt.qt_resvar, 0);
  243.     
  244.     /* get domain reference set from target list */
  245.     /* (also, find the TREE node) */
  246.     t = root->left;
  247.     if (t->sym.type == TREE)
  248.     {
  249.         for (i = 0; i < 8; i++)
  250.             protup.prodomset[i] = -1;
  251.     }
  252.     else
  253.     {
  254.         for (i = 0; i < 8; i++)
  255.             protup.prodomset[i] = 0;
  256.         for (; t->sym.type != TREE; t = t->left)
  257.         {
  258.             if (t->right->sym.type != VAR ||
  259.                 t->sym.type != RESDOM ||
  260.                 t->right->sym.value.sym_var.varno != Qt.qt_resvar)
  261.                 syserr("d_prot: garbage tree");
  262.             lsetbit(t->right->sym.value.sym_var.attno, protup.prodomset);
  263.         }
  264.         all_pro = FALSE;
  265.     }
  266.  
  267.     /* trim off the target list, since it isn't used again */
  268.     root->left = t;
  269.  
  270.     /*
  271.     **  Check out the target relation.
  272.     **    We first save the varno of the relation which is
  273.     **    getting the permit stuff.  Also, we check to see
  274.     **    that the relation mentioned is a base relation,
  275.     **    and not a view, since that tuple would never do
  276.     **    anything anyway.  Finally, we clear the Qt.qt_resvar
  277.     **    so that it does not get output to the tree catalog.
  278.     **    This would result in a 'syserr' when we tried to
  279.     **    read it.
  280.     */
  281.  
  282.     protup.proresvar = Qt.qt_resvar;
  283. #    ifdef xQTR3
  284.     if (Qt.qt_resvar < 0)
  285.         syserr("d_prot: Rv %d", Qt.qt_resvar);
  286. #    endif
  287.     if (bitset(S_VIEW, Qt.qt_rangev[Qt.qt_resvar].rngvdesc->reldum.relstat))
  288.         qmerror(NOTREALREL, -1, Qt.qt_resvar, 0);    /* is a view */
  289.  
  290.     /* clear the (unused) Qt.qt_qmode */
  291. #    ifdef xQTR3
  292.     if (Qt.qt_qmode != mdPROT)
  293.         syserr("d_prot: Qt.qt_qmode %d", Qt.qt_qmode);
  294. #    endif
  295.     Qt.qt_qmode = -1;
  296.  
  297.     /*
  298.     **  Check for PERMIT xx to ALL case.
  299.     **    The relstat bits will be adjusted as necessary
  300.     **    to reflect these special cases.
  301.     **
  302.     **    This is actually a little tricky, since we cannot
  303.     **    afford to turn off any permissions.  If we already
  304.     **    have some form of PERMIT xx to ALL access, we must
  305.     **    leave it.
  306.     */
  307.  
  308.     relstat = Qt.qt_rangev[Qt.qt_resvar].rngvdesc->reldum.relstat;
  309.     if (all_pro && (protup.proopset & PRO_RETR) != 0)
  310.     {
  311.         if (protup.proopset == -1)
  312.             relstat &= ~S_PROTALL;
  313.         else
  314.         {
  315.             relstat &= ~S_PROTRET;
  316.             if ((protup.proopset & ~(PRO_RETR|PRO_AGGR|PRO_TEST)) != 0)
  317.             {
  318.                 /* some special case: still insert prot tuple */
  319.                 all_pro = FALSE;
  320.             }
  321.         }
  322.     }
  323.     else
  324.         all_pro = FALSE;
  325.  
  326.     /* see if we are adding any tuples */
  327.     if (!all_pro)
  328.         relstat |= S_PROTUPS;
  329.     
  330.     /*
  331.     **  Change relstat field in relation catalog if changed
  332.     */
  333.  
  334.     if (relstat != Qt.qt_rangev[Qt.qt_resvar].rngvdesc->reldum.relstat)
  335.     {
  336.         opencatalog("relation", OR_WRITE);
  337.         setkey(&Reldes, &relkey, Qt.qt_rangev[Qt.qt_resvar].rngvdesc->reldum.relid, RELID);
  338.         setkey(&Reldes, &relkey, Qt.qt_rangev[Qt.qt_resvar].rngvdesc->reldum.relowner, RELOWNER);
  339.         i = getequal(&Reldes, &relkey, &reltup, &reltid);
  340.         if (i != 0)
  341.             syserr("d_prot: geteq %d", i);
  342.         reltup.relstat = relstat;
  343.         i = replace(&Reldes, &reltid, &reltup, FALSE);
  344.         if (i != 0)
  345.             syserr("d_prot: repl %d", i);
  346.         if (noclose(&Reldes) != 0)
  347.             syserr("d_prot: noclose(rel)");
  348.     }
  349.  
  350.     Qt.qt_resvar = -1;
  351.  
  352.     if (!all_pro)
  353.     {
  354.         /*
  355.         **  Output the created tuple to the protection catalog
  356.         **  after making other internal adjustments and deter-
  357.         **  mining a unique sequence number (with the protect
  358.         **  catalog locked).
  359.         */
  360.  
  361.         if (root->right->sym.type != QLEND)
  362.             protup.protree = puttree(root, protup.prorelid, protup.prorelown, mdPROT);
  363.         else
  364.             protup.protree = -1;
  365.  
  366.         /* compute unique permission id */
  367.         opencatalog("protect", OR_WRITE);
  368.         setrll(A_SLP, Prodes.reltid.ltid, M_EXCL);
  369.         setkey(&Prodes, &prokey, protup.prorelid, PRORELID);
  370.         setkey(&Prodes, &prokey, protup.prorelown, PRORELOWN);
  371.         for (ix = 2; ; ix++)
  372.         {
  373.             setkey(&Prodes, &prokey, &ix, PROPERMID);
  374.             i = getequal(&Prodes, &prokey, &proxtup, &protid);
  375.             if (i < 0)
  376.                 syserr("d_prot: geteq");
  377.             else if (i > 0)
  378.                 break;
  379.         }
  380.         protup.propermid = ix;
  381.  
  382.         /* do actual insert */
  383.         i = insert(&Prodes, &protid, &protup, FALSE);
  384.         if (i < 0)
  385.             syserr("d_prot: insert");
  386.         if (noclose(&Prodes) != 0)
  387.             syserr("d_prot: noclose(pro)");
  388.         
  389.         /* clear the lock */
  390.         unlrl(Prodes.reltid.ltid);
  391.     }
  392. }
  393. /*
  394. **  CVT_DOW -- convert day of week
  395. **
  396. **    Converts the day of the week from string form to a number.
  397. **
  398. **    Parameters:
  399. **        sdow -- dow in string form.
  400. **
  401. **    Returns:
  402. **        0 -> 6 -- the encoded day of the week.
  403. **        -1 -- error.
  404. **
  405. **    Side Effects:
  406. **        none
  407. **
  408. **    Defines:
  409. **        Dowlist -- a mapping from day of week to number.
  410. **        cvt_dow
  411. **
  412. **    Called By:
  413. **        d_prot
  414. */
  415.  
  416. struct downame
  417. {
  418.     char    *dow_name;
  419.     int    dow_num;
  420. };
  421.  
  422. struct downame    Dowlist[] =
  423. {
  424.     "sun",        0,
  425.     "sunday",    0,
  426.     "mon",        1,
  427.     "monday",    1,
  428.     "tue",        2,
  429.     "tues",        2,
  430.     "tuesday",    2,
  431.     "wed",        3,
  432.     "wednesday",    3,
  433.     "thu",        4,
  434.     "thurs",    4,
  435.     "thursday",    4,
  436.     "fri",        5,
  437.     "friday",    5,
  438.     "sat",        6,
  439.     "saturday",    6,
  440.     NULL
  441. };
  442.  
  443. cvt_dow(sdow)
  444. char    *sdow;
  445. {
  446.     register struct downame    *d;
  447.     register char        *s;
  448.  
  449.     s = sdow;
  450.  
  451.     for (d = Dowlist; d->dow_name != NULL; d++)
  452.         if (sequal(d->dow_name, s))
  453.             return (d->dow_num);
  454.     return (-1);
  455. }
  456. /*
  457. **  ISTTYNAME -- "is a legal terminal name" predicate
  458. **
  459. **    Returns TRUE if the argument is a legal terminal name,
  460. **    otherwise FALSE.
  461. **
  462. **    It may make sense to have this routine check if the given
  463. **    file name really exists.
  464. **
  465. **    WARNING:
  466. **        This routine may be installation-dependent!
  467. **
  468. **    Parameters:
  469. **        n -- the name to check.
  470. **
  471. **    Returns:
  472. **        TRUE -- n is a legal tty name at this installation.
  473. **        FALSE -- otherwise.
  474. **
  475. **    Side Effects:
  476. **        none
  477. **
  478. **    History:
  479. **        8/1/79 (eric) -- written.
  480. */
  481.  
  482.  
  483. isttyname(n)
  484. register char    *n;
  485. {
  486.     return (sequal(n, "console") || bequal(n, "tty", 3));
  487. }
  488.