Commit | Line | Data |
---|---|---|
c2c2eae0 KB |
1 | /* |
2 | * Copyright (c) 1987 Regents of the University of California. | |
ea9afd82 KB |
3 | * All rights reserved. |
4 | * | |
f15db449 | 5 | * %sccs.include.redist.c% |
c2c2eae0 KB |
6 | */ |
7 | ||
8 | #ifndef lint | |
9 | char copyright[] = | |
10 | "@(#) Copyright (c) 1987 Regents of the University of California.\n\ | |
11 | All rights reserved.\n"; | |
ea9afd82 | 12 | #endif /* not lint */ |
c2c2eae0 KB |
13 | |
14 | #ifndef lint | |
f15db449 | 15 | static char sccsid[] = "@(#)man.c 5.21 (Berkeley) %G%"; |
ea9afd82 | 16 | #endif /* not lint */ |
c2c2eae0 KB |
17 | |
18 | #include <sys/param.h> | |
19 | #include <sys/file.h> | |
0076013a | 20 | #include <errno.h> |
c2c2eae0 | 21 | #include <ctype.h> |
0076013a | 22 | #include <string.h> |
011519cd | 23 | #include <stdlib.h> |
ade4c407 | 24 | #include "pathnames.h" |
4610900a | 25 | |
0076013a | 26 | extern int errno; |
07b262aa | 27 | |
0076013a | 28 | int f_all, f_cat, f_where; |
011519cd | 29 | char *command, *machine, *p_augment, *p_path, *pager, *progname; |
c2c2eae0 KB |
30 | |
31 | main(argc, argv) | |
bb1b89c7 KB |
32 | int argc; |
33 | register char **argv; | |
c2c2eae0 | 34 | { |
07b262aa KB |
35 | extern char *optarg; |
36 | extern int optind; | |
011519cd KB |
37 | int ch, res; |
38 | char *section[2], *check_pager(), *getpath(); | |
c2c2eae0 | 39 | |
0076013a KB |
40 | progname = "man"; |
41 | while ((ch = getopt(argc, argv, "-acfkM:m:P:w")) != EOF) | |
07b262aa | 42 | switch((char)ch) { |
0076013a KB |
43 | case 'a': |
44 | f_all = 1; | |
45 | break; | |
46 | case 'c': | |
47 | case '-': /* deprecated */ | |
48 | f_cat = 1; | |
49 | break; | |
50 | case 'm': | |
51 | p_augment = optarg; | |
c2c2eae0 KB |
52 | break; |
53 | case 'M': | |
54 | case 'P': /* backward compatibility */ | |
0076013a | 55 | p_path = optarg; |
07b262aa | 56 | break; |
011519cd KB |
57 | /* |
58 | * "man -f" and "man -k" are backward compatible, undocumented | |
59 | * ways of calling whatis(1) and apropos(1). | |
60 | */ | |
c2c2eae0 | 61 | case 'f': |
07b262aa | 62 | jump(argv, "-f", "whatis"); |
0076013a | 63 | /* NOTREACHED */ |
c2c2eae0 | 64 | case 'k': |
07b262aa | 65 | jump(argv, "-k", "apropos"); |
0076013a | 66 | /* NOTREACHED */ |
da0e94fc | 67 | case 'w': |
0076013a | 68 | f_all = f_where = 1; |
da0e94fc | 69 | break; |
c2c2eae0 KB |
70 | case '?': |
71 | default: | |
07b262aa | 72 | usage(); |
c2c2eae0 | 73 | } |
07b262aa | 74 | argv += optind; |
bb1b89c7 | 75 | |
07b262aa KB |
76 | if (!*argv) |
77 | usage(); | |
c2c2eae0 | 78 | |
0076013a | 79 | if (!f_cat) |
c2c2eae0 | 80 | if (!isatty(1)) |
0076013a KB |
81 | f_cat = 1; |
82 | else if (pager = getenv("PAGER")) | |
83 | pager = check_pager(pager); | |
81cd4ba7 | 84 | else |
ade4c407 | 85 | pager = _PATH_PAGER; |
0076013a | 86 | |
c2c2eae0 KB |
87 | if (!(machine = getenv("MACHINE"))) |
88 | machine = MACHINE; | |
0076013a | 89 | |
011519cd KB |
90 | /* see if checking in a specific section */ |
91 | if (argc > 1 && getsection(*argv)) { | |
92 | section[0] = *argv++; | |
93 | section[1] = (char *)NULL; | |
94 | } else { | |
95 | section[0] = "_default"; | |
96 | section[1] = (char *)NULL; | |
97 | } | |
98 | ||
99 | if (!p_path && !(p_path = getenv("MANPATH")) && | |
100 | !(p_path = getpath(section)) && !p_augment) { | |
101 | (void)fprintf(stderr, | |
102 | "man: no place to search for those manual pages.\n"); | |
103 | exit(1); | |
104 | } | |
0076013a | 105 | |
011519cd KB |
106 | for (; *argv; ++argv) { |
107 | if (p_augment) | |
108 | res = manual(p_augment, *argv); | |
109 | res = manual(p_path, *argv); | |
110 | if (res || f_where) | |
111 | continue; | |
112 | (void)fprintf(stderr, | |
113 | "man: no entry for %s in the manual.\n", *argv); | |
114 | exit(1); | |
115 | } | |
0076013a | 116 | |
b5e4dc7e | 117 | /* use system(3) in case someone's pager is "pager arg1 arg2" */ |
c56621e7 KB |
118 | if (command) |
119 | (void)system(command); | |
bb1b89c7 KB |
120 | exit(0); |
121 | } | |
122 | ||
8f946e8d KB |
123 | /* |
124 | * manual -- | |
0076013a KB |
125 | * given a path, a directory list and a file name, find a file |
126 | * that matches; check ${directory}/${dir}/{file name} and | |
c56621e7 | 127 | * ${directory}/${dir}/${machine}/${file name}. |
8f946e8d | 128 | */ |
011519cd | 129 | manual(path, name) |
0076013a | 130 | char *path, *name; |
c2c2eae0 | 131 | { |
c56621e7 | 132 | register int res; |
011519cd | 133 | register char *end; |
0076013a | 134 | char fname[MAXPATHLEN + 1]; |
c2c2eae0 | 135 | |
0076013a | 136 | for (res = 0;; path = end + 1) { |
011519cd KB |
137 | if (!*path) /* foo: */ |
138 | break; | |
139 | if (end = index(path, ':')) { | |
140 | if (end == path + 1) /* foo::bar */ | |
141 | continue; | |
c2c2eae0 | 142 | *end = '\0'; |
c56621e7 | 143 | } |
011519cd KB |
144 | (void)sprintf(fname, "%s/%s.0", path, name); |
145 | if (access(fname, R_OK)) { | |
146 | (void)sprintf(fname, "%s/%s/%s.0", path, machine, name); | |
147 | if (access(fname, R_OK)) | |
148 | continue; | |
149 | } | |
150 | ||
151 | if (f_where) | |
152 | (void)printf("man: found in %s.\n", fname); | |
153 | else if (f_cat) | |
154 | cat(fname); | |
155 | else | |
156 | add(fname); | |
157 | if (!f_all) | |
158 | return(1); | |
159 | res = 1; | |
c2c2eae0 | 160 | if (!end) |
011519cd | 161 | break; |
fe684fa4 | 162 | *end = ':'; |
c2c2eae0 | 163 | } |
011519cd | 164 | return(res); |
c2c2eae0 KB |
165 | } |
166 | ||
8f946e8d | 167 | /* |
c56621e7 KB |
168 | * cat -- |
169 | * cat out the file | |
8f946e8d | 170 | */ |
c56621e7 KB |
171 | cat(fname) |
172 | char *fname; | |
c2c2eae0 | 173 | { |
c56621e7 KB |
174 | register int fd, n; |
175 | char buf[BUFSIZ]; | |
c2c2eae0 | 176 | |
c56621e7 | 177 | if (!(fd = open(fname, O_RDONLY, 0))) { |
0076013a | 178 | (void)fprintf(stderr, "man: %s: %s\n", fname, strerror(errno)); |
c56621e7 | 179 | exit(1); |
c2c2eae0 | 180 | } |
c56621e7 KB |
181 | while ((n = read(fd, buf, sizeof(buf))) > 0) |
182 | if (write(1, buf, n) != n) { | |
0076013a KB |
183 | (void)fprintf(stderr, |
184 | "man: write: %s\n", strerror(errno)); | |
c56621e7 KB |
185 | exit(1); |
186 | } | |
187 | if (n == -1) { | |
0076013a | 188 | (void)fprintf(stderr, "man: read: %s\n", strerror(errno)); |
c56621e7 KB |
189 | exit(1); |
190 | } | |
191 | (void)close(fd); | |
c2c2eae0 KB |
192 | } |
193 | ||
8f946e8d | 194 | /* |
c56621e7 KB |
195 | * add -- |
196 | * add a file name to the list for future paging | |
8f946e8d | 197 | */ |
c56621e7 | 198 | add(fname) |
bb1b89c7 | 199 | char *fname; |
c2c2eae0 | 200 | { |
c56621e7 KB |
201 | static u_int buflen; |
202 | static int len; | |
203 | static char *cp; | |
204 | int flen; | |
c2c2eae0 | 205 | |
c56621e7 | 206 | if (!command) { |
0076013a KB |
207 | if (!(command = malloc(buflen = 1024))) |
208 | enomem(); | |
c56621e7 KB |
209 | len = strlen(strcpy(command, pager)); |
210 | cp = command + len; | |
211 | } | |
212 | flen = strlen(fname); | |
213 | if (len + flen + 2 > buflen) { /* +2 == space, EOS */ | |
0076013a KB |
214 | if (!(command = realloc(command, buflen += 1024))) |
215 | enomem(); | |
c56621e7 | 216 | cp = command + len; |
c2c2eae0 | 217 | } |
c56621e7 KB |
218 | *cp++ = ' '; |
219 | len += flen + 1; /* +1 = space */ | |
220 | (void)strcpy(cp, fname); | |
221 | cp += flen; | |
c2c2eae0 KB |
222 | } |
223 | ||
0076013a KB |
224 | /* |
225 | * check_pager -- | |
226 | * check the user supplied page information | |
227 | */ | |
228 | char * | |
229 | check_pager(name) | |
230 | char *name; | |
231 | { | |
232 | register char *p; | |
011519cd | 233 | char *save; |
0076013a KB |
234 | |
235 | /* | |
236 | * if the user uses "more", we make it "more -s"; watch out for | |
237 | * PAGER = "mypager /usr/ucb/more" | |
238 | */ | |
239 | for (p = name; *p && !isspace(*p); ++p); | |
240 | for (; p > name && *p != '/'; --p); | |
241 | if (p != name) | |
242 | ++p; | |
243 | ||
244 | /* make sure it's "more", not "morex" */ | |
245 | if (!strncmp(p, "more", 4) && (!p[4] || isspace(p[4]))){ | |
246 | save = name; | |
247 | /* allocate space to add the "-s" */ | |
248 | if (!(name = | |
249 | malloc((u_int)(strlen(save) + sizeof("-s") + 1)))) | |
250 | enomem(); | |
251 | (void)sprintf(name, "%s %s", save, "-s"); | |
bb1b89c7 | 252 | } |
0076013a | 253 | return(name); |
c2c2eae0 | 254 | } |
07b262aa KB |
255 | |
256 | /* | |
257 | * jump -- | |
258 | * strip out flag argument and jump | |
259 | */ | |
07b262aa KB |
260 | jump(argv, flag, name) |
261 | char **argv, *name; | |
262 | register char *flag; | |
263 | { | |
264 | register char **arg; | |
265 | ||
266 | argv[0] = name; | |
267 | for (arg = argv + 1; *arg; ++arg) | |
268 | if (!strcmp(*arg, flag)) | |
269 | break; | |
270 | for (; *arg; ++arg) | |
271 | arg[0] = arg[1]; | |
272 | execvp(name, argv); | |
011519cd | 273 | (void)fprintf(stderr, "%s: Command not found.\n", name); |
07b262aa KB |
274 | exit(1); |
275 | } | |
276 | ||
277 | /* | |
278 | * usage -- | |
0076013a | 279 | * print usage message and die |
07b262aa | 280 | */ |
07b262aa KB |
281 | usage() |
282 | { | |
0076013a KB |
283 | (void)fprintf(stderr, |
284 | "usage: man [-ac] [-M path] [-m path] [section] title ...\n"); | |
07b262aa KB |
285 | exit(1); |
286 | } |