1: # include <pv.h> 2: # include <ingres.h> 3: # include <aux.h> 4: # include <catalog.h> 5: # include <access.h> 6: # include <func.h> 7: # include <signal.h> 8: # include <sccs.h> 9: # include <errors.h> 10: 11: SCCSID(@(#)help.c 8.5 2/8/85) 12: 13: extern short tTdbu[100]; 14: extern int help(); 15: extern int null_fn(); 16: 17: struct fn_def HelpFn = 18: { 19: "HELP", 20: help, 21: null_fn, /* initialization function */ 22: null_fn, 23: NULL, 24: 0, 25: tTdbu, 26: 100, 27: 'Z', 28: 0 29: }; 30: 31: 32: /* 33: ** HELP - Provide Information to User 34: ** 35: ** Arguments: 36: ** pv[i] - code 37: ** RELINFO - print relation information 38: ** MANSEC - print manual section 39: ** DELIMLIST - print delim information 40: ** RELIST - print relation list 41: ** ALLRELINFO - print relation info for all accessible 42: ** relations 43: ** 44: ** pv[i+1] - name of entity for modes 0 or 1 45: ** 46: ** Trace Flags: 47: ** 44 48: */ 49: 50: help(parmc, parmv) 51: int parmc; 52: PARM parmv[]; 53: { 54: DESC des; 55: int mode; 56: register PARM *pv; 57: register int ret; 58: int i; 59: 60: # ifdef xZTR1 61: if (tTf(44, -1)) 62: { 63: printf(">>help\n"); 64: if (tTf(44, 0)) 65: prvect(parmc, parmv); 66: } 67: # endif 68: 69: ret = 0; 70: pv = parmv; 71: getuser(-1); /* init getuser for modes RELINFO & MANSEC */ 72: while (pv->pv_type != PV_EOF) 73: { 74: mode = (pv++)->pv_val.pv_int; 75: if (mode < RELIST && pv->pv_type == PV_EOF) 76: syserr("help: mode %d no val", mode); 77: 78: # ifdef xZTR1 79: if (tTf(44, -1)) 80: { 81: printf("help %d", mode); 82: if (mode != RELIST) 83: printf(" %s", pv->pv_val.pv_str); 84: putchar('\n'); 85: } 86: # endif 87: switch (mode) 88: { 89: 90: case RELINFO: /* help relation */ 91: if (!openr(&des, OR_RELTID, pv->pv_val.pv_str)) 92: { 93: rel_fmt(&des); 94: pv->pv_val.pv_str = NULL; 95: } 96: pv++; 97: break; 98: 99: case MANSEC: /* help manual section */ 100: if (man(pv->pv_val.pv_str)) 101: pv->pv_val.pv_str = NULL; 102: pv++; 103: break; 104: 105: case DELLIST: /* help delim */ 106: if (!openr(&des, OR_READ, "rdelim")) 107: { 108: if ((i = helpdelim(pv->pv_val.pv_str,&des)) == -1) 109: return(error(RDELIMERR, pv->pv_val.pv_str, 0)); 110: closer(&des); 111: pv->pv_val.pv_str = NULL; 112: } 113: pv++; 114: break; 115: 116: case RELIST: 117: case ALLRELINFO: 118: relpr(mode); 119: break; 120: 121: case ALLDELLIST: 122: if (!openr(&des, OR_READ, "rdelim")) 123: { 124: if ((i = alldelims(&des)) == -1) 125: return(error(RDELIMERR, pv->pv_val.pv_str, 0)); 126: closer(&des); 127: pv->pv_val.pv_str = NULL; 128: } 129: pv++; 130: break; 131: 132: default: 133: syserr("HELP: mode %d", mode); 134: } 135: } 136: getuser(0); /* close getuser in case mode RELINFO or MANSEC */ 137: 138: /* now rescan for error messages */ 139: pv = parmv; 140: while (pv->pv_type != PV_EOF) 141: { 142: mode = (pv++)->pv_val.pv_int; 143: 144: if (mode < RELIST) 145: { 146: if (pv->pv_val.pv_str != NULL) 147: ret = nferror(NORELEXIST + mode, pv->pv_val.pv_str, 0); 148: pv++; 149: } 150: } 151: return (ret); 152: } 153: 154: 155: /* 156: ** Nroff Manual Section 157: ** 158: ** The manual section given by 'name' is nroff'ed. Returns one 159: ** on success, zero if the manual section is not found. 160: ** 161: ** Uses trace flag 11 162: */ 163: 164: int 165: man(name) 166: char *name; 167: { 168: char manual[100]; 169: register int i; 170: int stat; 171: char name_nr[18]; 172: register char *naa; 173: extern char *ztack(); 174: 175: if (length(name) > 14) 176: return (0); 177: 178: /* a null manual name gives table of contents */ 179: if (name[0] == 0) 180: smove("../toc.nr", name_nr); 181: else 182: concat(name, ".nr", name_nr); 183: 184: concat(ztack(Pathname, "/doc/quel/"), name_nr, manual); 185: if ((i = open(manual, O_RDONLY)) < 0) 186: { 187: /* try a unix command instead */ 188: concat(ztack(Pathname, "/doc/unix/"), name_nr, manual); 189: if ((i = open(manual, O_RDONLY)) < 0) 190: return (0); 191: } 192: if (close(i)) 193: syserr("cannot close %s", manual); 194: ruboff(0); /* wait for child's death if rubout occures */ 195: i = fork(); 196: if (i == 0) 197: { 198: signal(SIGINT, SIG_DFL); /* die on rubout */ 199: setuid(getuid()); 200: # ifndef xB_UNIX 201: setgid(getgid()); 202: # endif 203: naa = ztack(Pathname, "/doc/iaa"); 204: execl("/bin/nroff", "nroff", naa, manual, 0); 205: execl("/usr/bin/nroff", "nroff", naa, manual, 0); 206: syserr("help: exec: nroff"); 207: } 208: /* wait for nroff if fork succeeded */ 209: if (i > 0) 210: fullwait(i, "help: nroff"); 211: rubon(); 212: return (1); 213: } 214: 215: 216: /* 217: ** PRINT DATABASE INFORMATION 218: ** 219: ** Prints a list of all the relations in the database, together 220: ** with their owner. 221: ** 222: ** Uses trace flag 12 223: */ 224: 225: relpr(mode) 226: int mode; 227: { 228: extern DESC Reldes; 229: register DESC *d; 230: register int i; 231: register char *cp; 232: struct tup_id limtid, tid; 233: char buf[MAXLINE + 1]; 234: char lastuser[2]; 235: struct relation rel; 236: 237: opencatalog("relation", OR_READ); 238: d = &Reldes; 239: if (i = find(d, NOKEY, &tid, &limtid)) 240: syserr("help: relpr: find %d", i); 241: 242: lastuser[0] = '\0'; 243: 244: if (mode == RELIST) 245: printf("\n relation name relation owner\n\n"); 246: 247: while ((i = get(d, &tid, &limtid, &rel, 1)) == 0) 248: { 249: if (mode == RELIST) 250: { 251: if (!bequal(lastuser, rel.relowner, 2)) 252: { 253: if (getuser(rel.relowner, buf)) 254: { 255: /* cant find user code */ 256: bmove(" ", buf, 2); 257: cp = &buf[2]; 258: bmove(rel.relowner, cp, 2); 259: cp = &cp[2]; 260: *cp = '\0'; 261: } 262: else 263: { 264: for (cp = buf; *cp != ':'; cp++) 265: ; 266: *cp = '\0'; 267: } 268: bmove(rel.relowner, lastuser, 2); 269: } 270: printf(" %.12s %s\n", rel.relid, buf); 271: } 272: else 273: { 274: if ((rel.relstat & S_CATALOG) || bequal("_SYS", rel.relid, 4)) 275: continue; 276: if (bequal(Usercode, rel.relowner, UCODE_SZ) || bequal(Admin.adhdr.adowner, rel.relowner, 2)) 277: rel_fmt(&rel); 278: } 279: } 280: 281: if (i < 0) 282: syserr("help: relpr: get %d", i); 283: if (mode == RELIST) 284: printf("\n"); 285: return (0); 286: } 287: 288: 289: 290: /* 291: ** Print Relation Information 292: ** 293: ** Prints detailed information regarding the relation. 294: ** 295: ** Uses trace flag 13 296: */ 297: 298: rel_fmt(r) 299: register struct relation *r; 300: { 301: struct tup_id limtid, tid; 302: char buf[MAXLINE + 1]; 303: struct attribute att; 304: struct index indkey, ind; 305: register int i; 306: int j; 307: extern DESC Attdes, Inddes; 308: char *trim_relname(); 309: 310: printf("\nRelation:\t\t%s\n", trim_relname(r->relid)); 311: i = getuser(r->relowner, buf); 312: if (i) 313: { 314: smove("(xx)", buf); 315: bmove(r->relowner, &buf[1], 2); 316: } 317: else 318: { 319: for (i = 0; buf[i] != ':'; i++) 320: continue; 321: buf[i] = 0; 322: } 323: printf("Owner:\t\t\t%s\n", buf); 324: printf("Tuple width:\t\t%d\n", r->relwid); 325: if (r->relsave != 0) 326: { 327: printf("Saved until:\t\t%s", ctime(&r->relsave)); 328: } 329: if ((r->relstat & S_VIEW) == 0) 330: { 331: printf("Number of tuples:\t%ld\n", r->reltups); 332: printf("Storage structure:\t"); 333: i = r->relspec; 334: if (i < 0) 335: { 336: printf("compressed "); 337: i = -i; 338: } 339: switch (i) 340: { 341: 342: case M_HEAP: 343: printf("paged heap\n"); 344: break; 345: 346: case M_ISAM: 347: printf("ISAM file\n"); 348: break; 349: 350: case M_HASH: 351: printf("random hash\n"); 352: break; 353: 354: default: 355: printf("unknown structure %d\n", i); 356: break; 357: 358: } 359: } 360: 361: printf("Relation type:\t\t"); 362: if (r->relstat & S_CATALOG) 363: printf("system catalog\n"); 364: else if (r->relstat & S_VIEW) 365: printf("view\n"); 366: else 367: if (r->reldim > 0) 368: printf("ordered relation\n"); 369: else if (r->relindxd < 0) 370: { 371: printf("secondary index on "); 372: opencatalog("indexes", OR_READ); 373: setkey(&Inddes, &indkey, r->relowner, IOWNERP); 374: setkey(&Inddes, &indkey, r->relid, IRELIDI); 375: if (!getequal(&Inddes, &indkey, &ind, &tid)) 376: printf("%s\n", trim_relname(ind.irelidp)); 377: else 378: printf("unknown relation\n"); 379: } 380: else 381: { 382: if (r->relstat & S_DISTRIBUTED) 383: printf("distributed "); 384: printf("user relation\n"); 385: } 386: if (r->relindxd > 0) 387: { 388: printf("Secondary Indices:\t"); 389: opencatalog("indexes", OR_READ); 390: setkey(&Inddes, &indkey, r->relid, IRELIDP); 391: setkey(&Inddes, &indkey, r->relowner, IOWNERP); 392: if (i = find(&Inddes, EXACTKEY, &tid, &limtid, &indkey)) 393: syserr("help: find %d indexes", i); 394: j = FALSE; 395: while ((i = get(&Inddes, &tid, &limtid, &ind, 1)) == 0) 396: { 397: if (!bequal(&indkey, &ind, MAXNAME + 2)) 398: continue; 399: if (j) 400: printf(", "); 401: j =TRUE; 402: printf("%s", trim_relname(ind.irelidi)); 403: } 404: if (i < 0) 405: syserr("help:get indexes %d", i); 406: if (!j) 407: printf("unknown"); 408: } 409: printf("\n"); 410: 411: opencatalog("attribute", OR_READ); 412: printf("\n attribute name type length keyno.\n\n"); 413: seq_init(&Attdes, r); 414: while (seq_attributes(&Attdes, r, &att)) 415: { 416: printf(" %.12s %c%8d", 417: att.attname, att.attfrmt, att.attfrml & I1MASK); 418: if (att.attxtra) 419: printf("%7d", att.attxtra); 420: printf("\n"); 421: } 422: 423: printf("\n"); 424: return (0); 425: } 426: 427: /* 428: ** HELPDELIM - print all delims presently defined. 429: ** 430: ** Parameters: 431: ** group - the group of delims to print 432: ** 433: ** Returns: 434: ** 0 - if successful 435: ** -1 - if relation not found 436: */ 437: helpdelim(group,des) 438: char *group; 439: DESC *des; 440: { 441: DELIM_TUP tuple; 442: TID lotid,hitid; 443: int notfound = 1; 444: char delim[12]; 445: int start = 0; 446: int begin = 1; 447: char dstring[1024]; 448: char *dptr; 449: int found=0; 450: 451: if (find(des,LRANGEKEY, &lotid, &hitid, group) < 0) 452: return(-1); 453: find(des,HRANGEKEY, &lotid, &hitid, group); 454: printf("\n \t>>>> %s <<<<\n", group); 455: 456: while (!get(des, &lotid, &hitid, &tuple, 1)) 457: { 458: 459: if (strcmp(tuple.group, group)) 460: continue; 461: 462: if (strcmp(tuple.delim, delim)) 463: start = 1; 464: 465: if (start) 466: { 467: found = 1; 468: if (begin) 469: begin = 0; 470: else 471: print_delim(dstring); 472: 473: /*start a new string*/ 474: strcpy(delim, tuple.delim); 475: start = 0; 476: *dstring = NULL; 477: strcat(dstring, tuple.delim); 478: strcat(dstring, ": "); 479: convert_bitmap(dstring, &tuple); 480: } 481: else 482: { 483: /*add to old string*/ 484: convert_bitmap(dstring, &tuple); 485: } 486: } 487: if (!found) 488: printf("group %s does not exist\n", group); 489: else 490: print_delim(dstring); 491: return(0); 492: } 493: 494: /* 495: ** CONVERT_BITMAP - convert a bitmap back to a BNF expression 496: ** 497: ** Parameters: 498: ** dstring - string to stuff the BNF expression info 499: ** tuple - tuple containing the bitmap 500: ** 501: */ 502: convert_bitmap(dstring, tuple) 503: char *dstring; 504: DELIM_TUP *tuple; 505: { 506: int i,j; 507: char *pntr; 508: 509: pntr = dstring + strlen(dstring); 510: *pntr++ = (tuple->type == ONE ? LBRACKET : LBRACE); 511: i = 0; 512: while (i < 128 ) 513: { 514: if (test(tuple->bitmap, i)) 515: { 516: *pntr++ = i; 517: j = ++i; 518: while ((j < 128) && test(tuple->bitmap, j)) 519: j++; 520: if ( (j - i) >= 5) 521: { 522: j--; 523: *pntr++ = '-'; 524: *pntr++ = j; 525: i = j + 1; 526: } 527: } 528: else 529: i++; 530: } 531: *pntr++ = (tuple->type == ONE ? RBRACKET : RBRACE); 532: *pntr = NULL; 533: } 534: 535: /* 536: ** PRINT_DELIM - print one delim of the rdelim relation 537: ** 538: ** Parameters: 539: ** 540: */ 541: print_delim(delim) 542: char *delim; 543: { 544: printf("%s\n", delim); 545: } 546: 547: /* 548: ** ALLDELIMS - print all the delims currently defined 549: ** 550: */ 551: alldelims(des) 552: DESC *des; 553: { 554: DELIM_TUP tuple; 555: int start=1; 556: char group[12]; 557: TID lotid; 558: TID hitid; 559: 560: printf("Delimitor groups:\n"); 561: if (find(des,LRANGEKEY, &lotid, &hitid, group) < 0) 562: return(-1); 563: find(des,HRANGEKEY, &lotid, &hitid, group); 564: 565: while (!get(des, &lotid, &hitid, &tuple, 1)) 566: { 567: 568: if (strcmp(tuple.group, group)) 569: start = 1; 570: 571: if (start) 572: { 573: strcpy(group, tuple.group); 574: printf("\t\t %s\n", group); 575: /*helpdelim(group, des); */ 576: start = 0; 577: } 578: } 579: }