|
|
1.1 ! root 1: /* ! 2: * Command to give help on various command's usages. ! 3: * Also, this command allows user-specific information ! 4: * to be kept. ! 5: */ ! 6: ! 7: #include <stdio.h> ! 8: #include <sys/stat.h> ! 9: ! 10: #define NLINE 512 /* Longest helpfile line */ ! 11: #define HELPSEP '@' ! 12: ! 13: uchar doc[50]; ! 14: uchar buf[BUFSIZ]; ! 15: uchar *list[2]; ! 16: ! 17: uchar helpline[NLINE]; ! 18: uchar helpfile[] = "/etc/helpfile"; ! 19: FILE *shf; /* System helpfile */ ! 20: FILE *uhf; /* User helpfile */ ! 21: ! 22: /* ! 23: * Structure to speed lookup time. ! 24: */ ! 25: struct look { ! 26: long l_seek; ! 27: uchar *l_name; ! 28: }; ! 29: ! 30: struct look *lread(); ! 31: ! 32: uchar helpuse[] = "\ ! 33: The 'help' command prints a brief description of the usage of a command.\n\ ! 34: For example, to get information about the 'who' command, type:\n\ ! 35: help who\n\ ! 36: The 'man' command provides more detailed descriptions of commands.\n\ ! 37: \n\ ! 38: "; ! 39: ! 40: uchar noinf[] = "No information on %s\n"; ! 41: uchar *getenv(); ! 42: ! 43: main(argc, argv) ! 44: uuchar *argv[]; ! 45: { ! 46: register uchar **ap; ! 47: register int estat = 0; ! 48: uchar *fn; ! 49: ! 50: shf = fopen(helpfile, "r"); ! 51: if ((fn = getenv("HELP")) != NULL) ! 52: uhf = fopen(fn, "r"); ! 53: setbuf(stdout, buf); ! 54: ap = argv+1; ! 55: if (argc < 2) { ! 56: fprintf(stderr, helpuse); ! 57: ap = list; ! 58: if ((*ap = getenv("LASTERROR")) == NULL) ! 59: exit(0); ! 60: } ! 61: while (*ap != NULL) { ! 62: if (help(*ap)) { ! 63: printf(noinf, *ap); ! 64: estat |= 1; ! 65: } ! 66: if (*++ap != NULL) ! 67: putchar('\n'); ! 68: fflush(stdout); ! 69: } ! 70: exit(estat); ! 71: } ! 72: ! 73: /* ! 74: * This routine looks for information ! 75: * in the on-line documentation for ! 76: * the specified command. ! 77: * The information is bracketed by `.HS' ! 78: * and `.HE'. ! 79: * If nothing is found, search the other two places. ! 80: */ ! 81: help(command) ! 82: uchar *command; ! 83: { ! 84: register int bad = 1; ! 85: register FILE *hf; ! 86: ! 87: sprintf(doc, "/usr/man/cmd/%s", command); ! 88: if ((hf = fopen(doc, "r")) == NULL) { ! 89: strcat(doc, "m"); ! 90: if ((hf = fopen(doc, "r")) == NULL) ! 91: goto other; ! 92: } ! 93: for (;;) { ! 94: if (fgets(helpline, NLINE, hf) == NULL) ! 95: break; ! 96: if (strcmp(helpline, ".HS\n") == 0) { ! 97: bad = 0; ! 98: break; ! 99: } ! 100: } ! 101: if (!bad) ! 102: while (fgets(helpline, NLINE, hf) != NULL ! 103: && strcmp(helpline, ".HE\n") != 0) ! 104: fputs(helpline, stdout); ! 105: fclose(hf); ! 106: other: ! 107: if (bad) ! 108: if (bad = lookup(command, shf, "/etc/helpindex")) ! 109: bad = lookup(command, uhf, NULL); ! 110: return (bad); ! 111: } ! 112: ! 113: /* ! 114: * Lookup a command in the given file. ! 115: * The format is to look for # lines. ! 116: * The index-file is provided to speed up ! 117: * the lookup in situations where there is a very ! 118: * large system help file. ! 119: */ ! 120: lookup(com, fp, ind) ! 121: register uchar *com; ! 122: FILE *fp; ! 123: uchar *ind; ! 124: { ! 125: if (fp == NULL) ! 126: return (1); ! 127: if (fastlook(com, fp, ind)) ! 128: return (1); ! 129: while (fgets(helpline, NLINE, fp) != NULL) ! 130: if (helpline[0] == HELPSEP) { ! 131: helpline[strlen(helpline)-1] = '\0'; ! 132: if (strcmp(com, helpline+1) == 0) { ! 133: while (fgets(helpline, NLINE, fp) != NULL) { ! 134: if (helpline[0] == HELPSEP) ! 135: break; ! 136: fputs(helpline, stdout); ! 137: } ! 138: return (0); ! 139: } ! 140: } ! 141: return (1); ! 142: } ! 143: ! 144: /* ! 145: * Possibly seek the helpfile to the right place ! 146: * based on an index file. ! 147: * Return non-zero only when it is impossible to ! 148: * find it. ! 149: * If the index file is out of date, re-build it. ! 150: */ ! 151: fastlook(com, fp, ind) ! 152: uchar *com; ! 153: FILE *fp; ! 154: uchar *ind; ! 155: { ! 156: register uchar *cp, *ep; ! 157: register struct look *lp; ! 158: struct look look; ! 159: FILE *ifp; ! 160: long seek = 0; ! 161: int found = 0; ! 162: static struct stat sb; ! 163: long htime; ! 164: ! 165: fstat(fileno(fp), &sb); ! 166: htime = sb.st_mtime; ! 167: if (stat(ind, &sb) < 0) ! 168: goto rebuild; ! 169: if (htime < sb.st_mtime) { ! 170: if ((ifp = fopen(ind, "r")) == NULL) ! 171: goto rebuild; ! 172: while ((lp = lread(ifp)) != NULL) ! 173: if (strcmp(com, lp->l_name) == 0) { ! 174: seek = lp->l_seek; ! 175: found++; ! 176: break; ! 177: } ! 178: fclose(ifp); ! 179: if (found) { ! 180: fseek(fp, seek, 0); ! 181: return (0); ! 182: } ! 183: return (1); ! 184: } ! 185: ! 186: rebuild: ! 187: /* ! 188: * Re-build the index file. ! 189: */ ! 190: if ((ifp = fopen(ind, "w")) == NULL) ! 191: return (0); ! 192: for (;;) { ! 193: look.l_seek = ftell(fp); ! 194: if (fgets(helpline, NLINE, fp) == NULL) ! 195: break; ! 196: cp = helpline; ! 197: if (*cp++ != HELPSEP) ! 198: continue; ! 199: while (*cp==' ' && *cp=='\t') ! 200: cp++; ! 201: ep = cp; ! 202: while (*ep!='\n' && *ep!='\0' && *ep!=' ' && *ep!='\t') ! 203: ep++; ! 204: *ep = '\0'; ! 205: look.l_name = cp; ! 206: if (strcmp(com, cp) == 0) { ! 207: seek = look.l_seek; ! 208: found++; ! 209: } ! 210: lwrite(&look, ifp); ! 211: } ! 212: fclose(ifp); ! 213: if (found) { ! 214: fseek(fp, seek, 0); ! 215: return (0); ! 216: } ! 217: return (1); ! 218: } ! 219: ! 220: /* ! 221: * Read in a look structure. Return NULL ! 222: * on end of file or error. ! 223: */ ! 224: struct look * ! 225: lread(fp) ! 226: register FILE *fp; ! 227: { ! 228: register uchar *cp; ! 229: register int c; ! 230: static struct look look; ! 231: static uchar name[50]; ! 232: ! 233: look.l_name = name; ! 234: if (fread(&look.l_seek, sizeof look.l_seek, 1, fp) != 1) ! 235: return (NULL); ! 236: for (cp = name; cp<&name[49]; cp++) { ! 237: if ((c = getc(fp)) == EOF) ! 238: return (NULL); ! 239: *cp = c; ! 240: if (c == '\0') ! 241: break; ! 242: } ! 243: return (&look); ! 244: } ! 245: ! 246: /* ! 247: * Write out a structure to the ! 248: * given file pointer. ! 249: */ ! 250: lwrite(lp, fp) ! 251: register struct look *lp; ! 252: FILE *fp; ! 253: { ! 254: register uchar *cp; ! 255: ! 256: fwrite(&lp->l_seek, 1, sizeof lp->l_seek, fp); ! 257: cp = lp->l_name; do { ! 258: putc(*cp, fp); ! 259: } while (*cp++ != '\0'); ! 260: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.