1: # include "../ingres.h" 2: # include "../aux.h" 3: # include "../unix.h" 4: # include "../catalog.h" 5: # include "../access.h" 6: # include "../tree.h" 7: # include "../symbol.h" 8: # include "../lock.h" 9: # include "qrymod.h" 10: 11: 12: 13: /* 14: ** D_PROT -- define protection constraint 15: ** 16: ** A protection constraint as partially defined by the last tree 17: ** defined by d_tree is defined. 18: ** 19: ** The stuff that comes through the pipe as parameters is complex. 20: ** It comes as a sequence of strings: 21: ** # The operation set, already encoded in the parser into a 22: ** bit map. If the PRO_RETR permission is set, the PRO_TEST 23: ** and PRO_AGGR permissions will also be set. 24: ** # The relation name. 25: ** # The relation owner. 26: ** # The user name. This must be a user name as specified in 27: ** the 'users' file, or the keyword 'all', meaning all users. 28: ** # The terminal id. Must be a string of the form 'ttyx' or 29: ** the keyword 'all'. 30: ** # The starting time of day, as minutes-since-midnight. 31: ** # The ending time of day. 32: ** # The starting day-of-week, with 0 = Sunday. 33: ** # The ending dow. 34: ** 35: ** The domain reference set is build automatically from the 36: ** target list of the tree. Thus, the target list must exist, 37: ** but it is not inserted into the tree. The target list must 38: ** be a flat sequence of RESDOM nodes with VAR nodes hanging 39: ** of the rhs; also, the VAR nodes must all be for Resultvar. 40: ** If there is no target list on the tree, the set of all var- 41: ** iables is assumed. 42: ** 43: ** The relstat field in the relation relation is updated to 44: ** reflect any changes. 45: ** 46: ** It only makes sense for the DBA to execute this command. 47: ** 48: ** If there is one of the special cases 49: ** permit all to all 50: ** permit retrieve to all 51: ** it is caught, and the effect is achieved by diddling 52: ** relstat bits instead of inserting into the protect catalog. 53: ** 54: ** Parameters: 55: ** none 56: ** 57: ** Returns: 58: ** none 59: ** 60: ** Side Effects: 61: ** Activity in 'protect' and 'relation' catalogs. 62: ** 63: ** Requires: 64: ** Prodes, Reldes -- descriptors. 65: ** opencatalog -- to open these relations. 66: ** puttree -- to output the tree to the 'tree' 67: ** relation. 68: ** insert -- to output the tuple to the 'protect' 69: ** relation. 70: ** noclose -- to flush the 'protect' relation. 71: ** Rangev, Qmode, Resultvar -- for various parameter 72: ** validation. 73: ** Treeroot -- a pointer to the protection tree. 74: ** 75: ** Called By: 76: ** define 77: ** 78: ** Trace Flags: 79: ** 59 80: ** 81: ** Diagnostics: 82: ** 3590 -- bad terminal id. 83: ** 3591 -- bad user name. 84: ** 3592 -- you do not own one of the relations involved. 85: ** 3593 -- attempt to define a protection constraint 86: ** on a view. 87: ** 3594 -- you are not the dba. 88: ** 89: ** Syserrs: 90: ** On inconsistancies between pipe info and system 91: ** catalogs. 92: ** 93: ** History: 94: ** 2/19/79 (eric) -- split from define.c. 95: */ 96: 97: extern struct admin Admin; 98: extern struct descriptor Prodes; 99: extern struct descriptor Reldes; 100: extern QTREE *Treeroot; 101: 102: d_prot() 103: { 104: struct protect protup; 105: struct tup_id protid; 106: struct protect prokey; 107: struct protect proxtup; 108: register int i; 109: auto int ix; 110: int treeid; 111: register QTREE *t; 112: register char *p; 113: struct relation reltup; 114: struct relation relkey; 115: struct tup_id reltid; 116: int relstat; 117: int all_pro; 118: 119: /* 120: ** Check for valid tree: 121: ** There must be a tree defined, and all variables 122: ** referenced must be owned by the current user; this 123: ** is because you could otherwise get at data by 124: ** mentioning it in a permit statement; see protect.c 125: ** for a better explanation of this. 126: */ 127: 128: if (Treeroot == NULL) 129: syserr("d_prot: NULL Treeroot"); 130: for (i = 0; i < MAXVAR + 1; i++) 131: { 132: if (!Rangev[i].rused) 133: continue; 134: if (!bequal(Rangev[i].rowner, Usercode, 2)) 135: ferror(3592, -1, i, 0); 136: } 137: 138: /* test for dba */ 139: if (!bequal(Usercode, Admin.adhdr.adowner, 2)) 140: ferror(3595, -1, Resultvar, 0); 141: 142: clr_tuple(&Prodes, &protup); 143: 144: all_pro = fillprotup(&protup); 145: 146: /* get domain reference set from target list */ 147: /* (also, find the TREE node) */ 148: t = Treeroot->left; 149: if (t->sym.type == TREE) 150: { 151: for (i = 0; i < 8; i++) 152: protup.prodomset[i] = -1; 153: } 154: else 155: { 156: for (i = 0; i < 8; i++) 157: protup.prodomset[i] = 0; 158: for (; t->sym.type != TREE; t = t->left) 159: { 160: if (t->right->sym.type != VAR || 161: t->sym.type != RESDOM || 162: ((struct qt_var *)t->right)->varno != Resultvar) 163: syserr("d_prot: garbage tree"); 164: lsetbit(((struct qt_var *)t->right)->attno, protup.prodomset); 165: } 166: all_pro = FALSE; 167: } 168: 169: /* trim off the target list, since it isn't used again */ 170: Treeroot->left = t; 171: 172: /* 173: ** Check out the target relation. 174: ** We first save the varno of the relation which is 175: ** getting the permit stuff. Also, we check to see 176: ** that the relation mentioned is a base relation, 177: ** and not a view, since that tuple would never do 178: ** anything anyway. Finally, we clear the Resultvar 179: ** so that it does not get output to the tree catalog. 180: ** This would result in a 'syserr' when we tried to 181: ** read it. 182: */ 183: 184: protup.proresvar = Resultvar; 185: # ifdef xQTR3 186: if (Resultvar < 0) 187: syserr("d_prot: Rv %d", Resultvar); 188: # endif 189: if ((Rangev[Resultvar].rstat & S_VIEW) != 0) 190: ferror(3593, -1, Resultvar, 0); /* is a view */ 191: 192: /* clear the (unused) Qmode */ 193: # ifdef xQTR3 194: if (Qmode != mdDEFINE) 195: syserr("d_prot: Qmode %d", Qmode); 196: # endif 197: Qmode = -1; 198: 199: /* 200: ** Check for PERMIT xx to ALL case. 201: ** The relstat bits will be adjusted as necessary 202: ** to reflect these special cases. 203: ** 204: ** This is actually a little tricky, since we cannot 205: ** afford to turn off any permissions. If we already 206: ** have some form of PERMIT xx to ALL access, we must 207: ** leave it. 208: */ 209: 210: relstat = Rangev[Resultvar].rstat; 211: if (all_pro && (protup.proopset & PRO_RETR) != 0) 212: { 213: if (protup.proopset == -1) 214: relstat &= ~S_PROTALL; 215: else 216: { 217: relstat &= ~S_PROTRET; 218: if ((protup.proopset & ~(PRO_RETR|PRO_AGGR|PRO_TEST)) != 0) 219: { 220: /* some special case: still insert prot tuple */ 221: all_pro = FALSE; 222: } 223: } 224: } 225: else 226: all_pro = FALSE; /* insert tuple if not special case */ 227: 228: /* see if we are adding any tuples */ 229: if (!all_pro) 230: relstat |= S_PROTUPS; 231: 232: /* 233: ** Change relstat field in relation catalog 234: */ 235: 236: opencatalog("relation", 2); 237: setkey(&Reldes, &relkey, Rangev[Resultvar].relid, RELID); 238: setkey(&Reldes, &relkey, Rangev[Resultvar].rowner, RELOWNER); 239: i = getequal(&Reldes, &relkey, &reltup, &reltid); 240: if (i != 0) 241: syserr("d_prot: geteq %d", i); 242: reltup.relstat = relstat; 243: i = replace(&Reldes, &reltid, &reltup, FALSE); 244: if (i != 0 && i != 1) 245: syserr("d_prot: repl %d", i); 246: if (noclose(&Reldes) != 0) 247: syserr("d_prot: noclose(rel)"); 248: 249: Resultvar = -1; 250: 251: if (!all_pro) 252: { 253: /* 254: ** Output the created tuple to the protection catalog 255: ** after making other internal adjustments and deter- 256: ** mining a unique sequence number (with the protect 257: ** catalog locked). 258: */ 259: 260: if (Treeroot->right->sym.type != QLEND) 261: protup.protree = puttree(Treeroot, protup.prorelid, protup.prorelown, mdPROT); 262: else 263: protup.protree = -1; 264: 265: /* compute unique permission id */ 266: opencatalog("protect", 2); 267: setrll(A_SLP, Prodes.reltid, M_EXCL); 268: setkey(&Prodes, &prokey, protup.prorelid, PRORELID); 269: setkey(&Prodes, &prokey, protup.prorelown, PRORELOWN); 270: for (ix = 2; ; ix++) 271: { 272: setkey(&Prodes, &prokey, &ix, PROPERMID); 273: i = getequal(&Prodes, &prokey, &proxtup, &protid); 274: if (i < 0) 275: syserr("d_prot: geteq"); 276: else if (i > 0) 277: break; 278: } 279: protup.propermid = ix; 280: 281: /* do actual insert */ 282: i = insert(&Prodes, &protid, &protup, FALSE); 283: if (i < 0) 284: syserr("d_prot: insert"); 285: if (noclose(&Prodes) != 0) 286: syserr("d_prot: noclose(pro)"); 287: 288: /* clear the lock */ 289: unlrl(Prodes.reltid); 290: } 291: Treeroot = NULL; 292: } 293: 294: 295: 296: 297: 298: /* 299: ** CVT_DOW -- convert day of week 300: ** 301: ** Converts the day of the week from string form to a number. 302: ** 303: ** Parameters: 304: ** sdow -- dow in string form. 305: ** 306: ** Returns: 307: ** 0 -> 6 -- the encoded day of the week. 308: ** -1 -- error. 309: ** 310: ** Side Effects: 311: ** none 312: ** 313: ** Defines: 314: ** Dowlist -- a mapping from day of week to number. 315: ** cvt_dow 316: ** 317: ** Called By: 318: ** d_prot 319: */ 320: 321: struct downame 322: { 323: char *dow_name; 324: int dow_num; 325: }; 326: 327: struct downame Dowlist[] = 328: { 329: "sun", 0, 330: "sunday", 0, 331: "mon", 1, 332: "monday", 1, 333: "tue", 2, 334: "tues", 2, 335: "tuesday", 2, 336: "wed", 3, 337: "wednesday", 3, 338: "thu", 4, 339: "thurs", 4, 340: "thursday", 4, 341: "fri", 5, 342: "friday", 5, 343: "sat", 6, 344: "saturday", 6, 345: NULL 346: }; 347: 348: cvt_dow(sdow) 349: char *sdow; 350: { 351: register struct downame *d; 352: register char *s; 353: 354: s = sdow; 355: 356: for (d = Dowlist; d->dow_name != NULL; d++) 357: if (sequal(d->dow_name, s)) 358: return (d->dow_num); 359: return (-1); 360: }