]>
Commit | Line | Data |
---|---|---|
726f6388 JA |
1 | This file is help.def, from which is created help.c. |
2 | It implements the builtin "help" in Bash. | |
3 | ||
3185942a | 4 | Copyright (C) 1987-2009 Free Software Foundation, Inc. |
726f6388 JA |
5 | |
6 | This file is part of GNU Bash, the Bourne Again SHell. | |
7 | ||
3185942a JA |
8 | Bash is free software: you can redistribute it and/or modify |
9 | it under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation, either version 3 of the License, or | |
11 | (at your option) any later version. | |
726f6388 | 12 | |
3185942a JA |
13 | Bash is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
726f6388 | 17 | |
3185942a JA |
18 | You should have received a copy of the GNU General Public License |
19 | along with Bash. If not, see <http://www.gnu.org/licenses/>. | |
726f6388 JA |
20 | |
21 | $PRODUCES help.c | |
22 | ||
23 | $BUILTIN help | |
24 | $FUNCTION help_builtin | |
ccc6cda3 | 25 | $DEPENDS_ON HELP_BUILTIN |
0001803f | 26 | $SHORT_DOC help [-dms] [pattern ...] |
3185942a JA |
27 | Display information about builtin commands. |
28 | ||
29 | Displays brief summaries of builtin commands. If PATTERN is | |
726f6388 | 30 | specified, gives detailed help on all commands matching PATTERN, |
3185942a JA |
31 | otherwise the list of help topics is printed. |
32 | ||
33 | Options: | |
34 | -d output short description for each topic | |
35 | -m display usage in pseudo-manpage format | |
36 | -s output only a short usage synopsis for each topic matching | |
37 | PATTERN | |
38 | ||
39 | Arguments: | |
40 | PATTERN Pattern specifiying a help topic | |
41 | ||
42 | Exit Status: | |
43 | Returns success unless PATTERN is not found or an invalid option is given. | |
726f6388 JA |
44 | $END |
45 | ||
ccc6cda3 JA |
46 | #include <config.h> |
47 | ||
48 | #if defined (HELP_BUILTIN) | |
726f6388 | 49 | #include <stdio.h> |
ccc6cda3 JA |
50 | |
51 | #if defined (HAVE_UNISTD_H) | |
cce855bc JA |
52 | # ifdef _MINIX |
53 | # include <sys/types.h> | |
54 | # endif | |
ccc6cda3 JA |
55 | # include <unistd.h> |
56 | #endif | |
57 | ||
7117c2d2 JA |
58 | #include <errno.h> |
59 | ||
60 | #include <filecntl.h> | |
61 | ||
b80f6443 JA |
62 | #include "../bashintl.h" |
63 | ||
726f6388 JA |
64 | #include "../shell.h" |
65 | #include "../builtins.h" | |
cce855bc | 66 | #include "../pathexp.h" |
f73dda09 | 67 | #include "common.h" |
ccc6cda3 JA |
68 | #include "bashgetopt.h" |
69 | ||
f73dda09 | 70 | #include <glob/strmatch.h> |
ccc6cda3 | 71 | #include <glob/glob.h> |
726f6388 | 72 | |
7117c2d2 JA |
73 | #ifndef errno |
74 | extern int errno; | |
75 | #endif | |
76 | ||
3185942a JA |
77 | extern const char * const bash_copyright; |
78 | extern const char * const bash_license; | |
79 | ||
7117c2d2 | 80 | static void show_builtin_command_help __P((void)); |
3185942a JA |
81 | static int open_helpfile __P((char *)); |
82 | static void show_desc __P((char *, int)); | |
83 | static void show_manpage __P((char *, int)); | |
7117c2d2 | 84 | static void show_longdoc __P((int)); |
726f6388 JA |
85 | |
86 | /* Print out a list of the known functions in the shell, and what they do. | |
87 | If LIST is supplied, print out the list which matches for each pattern | |
88 | specified. */ | |
ccc6cda3 | 89 | int |
726f6388 JA |
90 | help_builtin (list) |
91 | WORD_LIST *list; | |
92 | { | |
7117c2d2 | 93 | register int i; |
ccc6cda3 | 94 | char *pattern, *name; |
3185942a | 95 | int plen, match_found, sflag, dflag, mflag; |
726f6388 | 96 | |
3185942a | 97 | dflag = sflag = mflag = 0; |
ccc6cda3 | 98 | reset_internal_getopt (); |
3185942a | 99 | while ((i = internal_getopt (list, "dms")) != -1) |
ccc6cda3 JA |
100 | { |
101 | switch (i) | |
726f6388 | 102 | { |
3185942a JA |
103 | case 'd': |
104 | dflag = 1; | |
105 | break; | |
106 | case 'm': | |
107 | mflag = 1; | |
108 | break; | |
bb70624e JA |
109 | case 's': |
110 | sflag = 1; | |
111 | break; | |
ccc6cda3 JA |
112 | default: |
113 | builtin_usage (); | |
114 | return (EX_USAGE); | |
726f6388 | 115 | } |
726f6388 | 116 | } |
ccc6cda3 | 117 | list = loptend; |
726f6388 | 118 | |
d166f048 JA |
119 | if (list == 0) |
120 | { | |
121 | show_shell_version (0); | |
122 | show_builtin_command_help (); | |
123 | return (EXECUTION_SUCCESS); | |
124 | } | |
125 | ||
ccc6cda3 | 126 | /* We should consider making `help bash' do something. */ |
726f6388 | 127 | |
ccc6cda3 JA |
128 | if (glob_pattern_p (list->word->word)) |
129 | { | |
3185942a | 130 | printf (ngettext ("Shell commands matching keyword `", "Shell commands matching keywords `", (list->next ? 2 : 1))); |
ccc6cda3 JA |
131 | print_word_list (list, ", "); |
132 | printf ("'\n\n"); | |
133 | } | |
726f6388 | 134 | |
ccc6cda3 JA |
135 | for (match_found = 0, pattern = ""; list; list = list->next) |
136 | { | |
137 | pattern = list->word->word; | |
138 | plen = strlen (pattern); | |
726f6388 | 139 | |
ccc6cda3 JA |
140 | for (i = 0; name = shell_builtins[i].name; i++) |
141 | { | |
142 | QUIT; | |
143 | if ((strncmp (pattern, name, plen) == 0) || | |
f73dda09 | 144 | (strmatch (pattern, name, FNMATCH_EXTFLAG) != FNM_NOMATCH)) |
726f6388 | 145 | { |
3185942a JA |
146 | match_found++; |
147 | if (dflag) | |
148 | { | |
149 | show_desc (name, i); | |
150 | continue; | |
151 | } | |
152 | else if (mflag) | |
153 | { | |
154 | show_manpage (name, i); | |
155 | continue; | |
156 | } | |
157 | ||
495aee44 | 158 | printf ("%s: %s\n", name, _(shell_builtins[i].short_doc)); |
726f6388 | 159 | |
bb70624e | 160 | if (sflag == 0) |
7117c2d2 | 161 | show_longdoc (i); |
726f6388 | 162 | } |
726f6388 | 163 | } |
ccc6cda3 | 164 | } |
726f6388 | 165 | |
ccc6cda3 JA |
166 | if (match_found == 0) |
167 | { | |
b80f6443 | 168 | builtin_error (_("no help topics match `%s'. Try `help help' or `man -k %s' or `info %s'."), pattern, pattern, pattern); |
ccc6cda3 | 169 | return (EXECUTION_FAILURE); |
726f6388 | 170 | } |
ccc6cda3 | 171 | |
726f6388 JA |
172 | fflush (stdout); |
173 | return (EXECUTION_SUCCESS); | |
174 | } | |
ccc6cda3 | 175 | |
3185942a JA |
176 | static int |
177 | open_helpfile (name) | |
178 | char *name; | |
179 | { | |
180 | int fd; | |
181 | ||
182 | fd = open (name, O_RDONLY); | |
183 | if (fd == -1) | |
184 | { | |
185 | builtin_error (_("%s: cannot open: %s"), name, strerror (errno)); | |
186 | return -1; | |
187 | } | |
188 | return fd; | |
189 | } | |
190 | ||
7117c2d2 JA |
191 | /* By convention, enforced by mkbuiltins.c, if separate help files are being |
192 | used, the long_doc array contains one string -- the full pathname of the | |
193 | help file for this builtin. */ | |
194 | static void | |
195 | show_longdoc (i) | |
196 | int i; | |
197 | { | |
198 | register int j; | |
199 | char * const *doc; | |
200 | int fd; | |
201 | ||
202 | doc = shell_builtins[i].long_doc; | |
203 | ||
204 | if (doc && doc[0] && *doc[0] == '/' && doc[1] == (char *)NULL) | |
205 | { | |
3185942a JA |
206 | fd = open_helpfile (doc[0]); |
207 | if (fd < 0) | |
208 | return; | |
7117c2d2 JA |
209 | zcatfd (fd, 1, doc[0]); |
210 | close (fd); | |
211 | } | |
212 | else | |
213 | for (j = 0; doc[j]; j++) | |
95732b49 | 214 | printf ("%*s%s\n", BASE_INDENT, " ", _(doc[j])); |
7117c2d2 JA |
215 | } |
216 | ||
3185942a JA |
217 | static void |
218 | show_desc (name, i) | |
219 | char *name; | |
220 | int i; | |
221 | { | |
222 | register int j; | |
223 | char **doc, *line; | |
224 | int fd, usefile; | |
225 | ||
226 | doc = (char **)shell_builtins[i].long_doc; | |
227 | ||
228 | usefile = (doc && doc[0] && *doc[0] == '/' && doc[1] == (char *)NULL); | |
229 | if (usefile) | |
230 | { | |
231 | fd = open_helpfile (doc[0]); | |
232 | if (fd < 0) | |
233 | return; | |
234 | zmapfd (fd, &line, doc[0]); | |
235 | close (fd); | |
236 | } | |
237 | else | |
238 | line = doc ? doc[0] : (char *)NULL; | |
239 | ||
240 | printf ("%s - ", name); | |
241 | for (j = 0; line && line[j]; j++) | |
242 | { | |
243 | putchar (line[j]); | |
244 | if (line[j] == '\n') | |
245 | break; | |
246 | } | |
247 | ||
248 | fflush (stdout); | |
249 | ||
250 | if (usefile) | |
251 | free (line); | |
252 | } | |
253 | ||
254 | /* Print builtin help in pseudo-manpage format. */ | |
255 | static void | |
256 | show_manpage (name, i) | |
257 | char *name; | |
258 | int i; | |
259 | { | |
260 | register int j; | |
261 | char **doc, *line; | |
262 | int fd, usefile; | |
263 | ||
264 | doc = (char **)shell_builtins[i].long_doc; | |
265 | ||
266 | usefile = (doc && doc[0] && *doc[0] == '/' && doc[1] == (char *)NULL); | |
267 | if (usefile) | |
268 | { | |
269 | fd = open_helpfile (doc[0]); | |
270 | if (fd < 0) | |
271 | return; | |
272 | zmapfd (fd, &line, doc[0]); | |
273 | close (fd); | |
274 | } | |
275 | else | |
276 | line = doc ? _(doc[0]) : (char *)NULL; | |
277 | ||
278 | /* NAME */ | |
279 | printf ("NAME\n"); | |
280 | printf ("%*s%s - ", BASE_INDENT, " ", name); | |
281 | for (j = 0; line && line[j]; j++) | |
282 | { | |
283 | putchar (line[j]); | |
284 | if (line[j] == '\n') | |
285 | break; | |
286 | } | |
287 | printf ("\n"); | |
288 | ||
289 | /* SYNOPSIS */ | |
290 | printf ("SYNOPSIS\n"); | |
495aee44 | 291 | printf ("%*s%s\n\n", BASE_INDENT, " ", _(shell_builtins[i].short_doc)); |
3185942a JA |
292 | |
293 | /* DESCRIPTION */ | |
294 | printf ("DESCRIPTION\n"); | |
295 | if (usefile == 0) | |
296 | { | |
297 | for (j = 0; doc[j]; j++) | |
298 | printf ("%*s%s\n", BASE_INDENT, " ", _(doc[j])); | |
299 | } | |
300 | else | |
301 | { | |
302 | for (j = 0; line && line[j]; j++) | |
303 | { | |
304 | putchar (line[j]); | |
305 | if (line[j] == '\n') | |
306 | printf ("%*s", BASE_INDENT, " "); | |
307 | } | |
308 | } | |
309 | putchar ('\n'); | |
310 | ||
311 | /* SEE ALSO */ | |
312 | printf ("SEE ALSO\n"); | |
313 | printf ("%*sbash(1)\n\n", BASE_INDENT, " "); | |
314 | ||
315 | /* IMPLEMENTATION */ | |
316 | printf ("IMPLEMENTATION\n"); | |
317 | printf ("%*s", BASE_INDENT, " "); | |
318 | show_shell_version (0); | |
319 | printf ("%*s", BASE_INDENT, " "); | |
320 | printf ("%s\n", _(bash_copyright)); | |
321 | printf ("%*s", BASE_INDENT, " "); | |
322 | printf ("%s\n", _(bash_license)); | |
323 | ||
324 | fflush (stdout); | |
325 | if (usefile) | |
326 | free (line); | |
327 | } | |
328 | ||
ccc6cda3 JA |
329 | static void |
330 | show_builtin_command_help () | |
331 | { | |
332 | int i, j; | |
3185942a JA |
333 | int height, width; |
334 | char *t, blurb[128]; | |
ccc6cda3 JA |
335 | |
336 | printf ( | |
b80f6443 | 337 | _("These shell commands are defined internally. Type `help' to see this list.\n\ |
ccc6cda3 JA |
338 | Type `help name' to find out more about the function `name'.\n\ |
339 | Use `info bash' to find out more about the shell in general.\n\ | |
7117c2d2 | 340 | Use `man -k' or `info' to find out more about commands not in this list.\n\ |
ccc6cda3 JA |
341 | \n\ |
342 | A star (*) next to a name means that the command is disabled.\n\ | |
b80f6443 | 343 | \n")); |
ccc6cda3 | 344 | |
3185942a JA |
345 | t = get_string_value ("COLUMNS"); |
346 | width = (t && *t) ? atoi (t) : 80; | |
347 | if (width <= 0) | |
348 | width = 80; | |
349 | ||
350 | width /= 2; | |
351 | if (width > sizeof (blurb)) | |
352 | width = sizeof (blurb); | |
0001803f CR |
353 | if (width <= 3) |
354 | width = 40; | |
3185942a JA |
355 | height = (num_shell_builtins + 1) / 2; /* number of rows */ |
356 | ||
357 | for (i = 0; i < height; i++) | |
ccc6cda3 JA |
358 | { |
359 | QUIT; | |
3185942a JA |
360 | |
361 | /* first column */ | |
ccc6cda3 | 362 | blurb[0] = (shell_builtins[i].flags & BUILTIN_ENABLED) ? ' ' : '*'; |
495aee44 | 363 | strncpy (blurb + 1, _(shell_builtins[i].short_doc), width - 2); |
3185942a JA |
364 | blurb[width - 2] = '>'; /* indicate truncation */ |
365 | blurb[width - 1] = '\0'; | |
ccc6cda3 | 366 | printf ("%s", blurb); |
3185942a JA |
367 | if (((i << 1) >= num_shell_builtins) || (i+height >= num_shell_builtins)) |
368 | { | |
369 | printf ("\n"); | |
370 | break; | |
371 | } | |
372 | ||
373 | /* two spaces */ | |
374 | for (j = strlen (blurb); j < width; j++) | |
375 | putc (' ', stdout); | |
ccc6cda3 | 376 | |
3185942a JA |
377 | /* second column */ |
378 | blurb[0] = (shell_builtins[i+height].flags & BUILTIN_ENABLED) ? ' ' : '*'; | |
495aee44 | 379 | strncpy (blurb + 1, _(shell_builtins[i+height].short_doc), width - 3); |
3185942a JA |
380 | blurb[width - 3] = '>'; /* indicate truncation */ |
381 | blurb[width - 2] = '\0'; | |
382 | printf ("%s\n", blurb); | |
ccc6cda3 | 383 | } |
ccc6cda3 JA |
384 | } |
385 | #endif /* HELP_BUILTIN */ |