|
|
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.