]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/help.def
Bash-4.3 patch 46
[thirdparty/bash.git] / builtins / help.def
CommitLineData
726f6388
JA
1This file is help.def, from which is created help.c.
2It implements the builtin "help" in Bash.
3
ac50fbac 4Copyright (C) 1987-2013 Free Software Foundation, Inc.
726f6388
JA
5
6This file is part of GNU Bash, the Bourne Again SHell.
7
3185942a
JA
8Bash is free software: you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation, either version 3 of the License, or
11(at your option) any later version.
726f6388 12
3185942a
JA
13Bash is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
726f6388 17
3185942a
JA
18You should have received a copy of the GNU General Public License
19along 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
27Display information about builtin commands.
28
29Displays brief summaries of builtin commands. If PATTERN is
726f6388 30specified, gives detailed help on all commands matching PATTERN,
3185942a
JA
31otherwise the list of help topics is printed.
32
33Options:
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
39Arguments:
40 PATTERN Pattern specifiying a help topic
41
42Exit Status:
43Returns 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
74extern int errno;
75#endif
76
3185942a
JA
77extern const char * const bash_copyright;
78extern const char * const bash_license;
79
7117c2d2 80static void show_builtin_command_help __P((void));
3185942a
JA
81static int open_helpfile __P((char *));
82static void show_desc __P((char *, int));
83static void show_manpage __P((char *, int));
7117c2d2 84static 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 89int
726f6388
JA
90help_builtin (list)
91 WORD_LIST *list;
92{
7117c2d2 93 register int i;
ccc6cda3 94 char *pattern, *name;
ac50fbac 95 int plen, match_found, sflag, dflag, mflag, m, pass, this_found;
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
ac50fbac 140 for (pass = 1, this_found = 0; pass < 3; pass++)
ccc6cda3 141 {
ac50fbac 142 for (i = 0; name = shell_builtins[i].name; i++)
726f6388 143 {
ac50fbac
CR
144 QUIT;
145
146 /* First pass: look for exact string or pattern matches.
147 Second pass: look for prefix matches like bash-4.2 */
148 if (pass == 1)
149 m = (strcmp (pattern, name) == 0) ||
150 (strmatch (pattern, name, FNMATCH_EXTFLAG) != FNM_NOMATCH);
151 else
152 m = strncmp (pattern, name, plen) == 0;
153
154 if (m)
155 {
156 this_found = 1;
157 match_found++;
158 if (dflag)
159 {
160 show_desc (name, i);
161 continue;
162 }
163 else if (mflag)
164 {
165 show_manpage (name, i);
166 continue;
167 }
168
169 printf ("%s: %s\n", name, _(shell_builtins[i].short_doc));
170
171 if (sflag == 0)
172 show_longdoc (i);
173 }
726f6388 174 }
ac50fbac
CR
175 if (pass == 1 && this_found == 1)
176 break;
726f6388 177 }
ccc6cda3 178 }
726f6388 179
ccc6cda3
JA
180 if (match_found == 0)
181 {
b80f6443 182 builtin_error (_("no help topics match `%s'. Try `help help' or `man -k %s' or `info %s'."), pattern, pattern, pattern);
ccc6cda3 183 return (EXECUTION_FAILURE);
726f6388 184 }
ccc6cda3 185
726f6388
JA
186 fflush (stdout);
187 return (EXECUTION_SUCCESS);
188}
ccc6cda3 189
3185942a
JA
190static int
191open_helpfile (name)
192 char *name;
193{
194 int fd;
195
196 fd = open (name, O_RDONLY);
197 if (fd == -1)
198 {
199 builtin_error (_("%s: cannot open: %s"), name, strerror (errno));
200 return -1;
201 }
202 return fd;
203}
204
7117c2d2
JA
205/* By convention, enforced by mkbuiltins.c, if separate help files are being
206 used, the long_doc array contains one string -- the full pathname of the
207 help file for this builtin. */
208static void
209show_longdoc (i)
210 int i;
211{
212 register int j;
213 char * const *doc;
214 int fd;
215
216 doc = shell_builtins[i].long_doc;
217
218 if (doc && doc[0] && *doc[0] == '/' && doc[1] == (char *)NULL)
219 {
3185942a
JA
220 fd = open_helpfile (doc[0]);
221 if (fd < 0)
222 return;
7117c2d2
JA
223 zcatfd (fd, 1, doc[0]);
224 close (fd);
225 }
ac50fbac 226 else if (doc)
7117c2d2 227 for (j = 0; doc[j]; j++)
95732b49 228 printf ("%*s%s\n", BASE_INDENT, " ", _(doc[j]));
7117c2d2
JA
229}
230
3185942a
JA
231static void
232show_desc (name, i)
233 char *name;
234 int i;
235{
236 register int j;
237 char **doc, *line;
238 int fd, usefile;
239
240 doc = (char **)shell_builtins[i].long_doc;
241
242 usefile = (doc && doc[0] && *doc[0] == '/' && doc[1] == (char *)NULL);
243 if (usefile)
244 {
245 fd = open_helpfile (doc[0]);
246 if (fd < 0)
247 return;
248 zmapfd (fd, &line, doc[0]);
249 close (fd);
250 }
251 else
252 line = doc ? doc[0] : (char *)NULL;
253
254 printf ("%s - ", name);
255 for (j = 0; line && line[j]; j++)
256 {
257 putchar (line[j]);
258 if (line[j] == '\n')
259 break;
260 }
261
262 fflush (stdout);
263
264 if (usefile)
265 free (line);
266}
267
268/* Print builtin help in pseudo-manpage format. */
269static void
270show_manpage (name, i)
271 char *name;
272 int i;
273{
274 register int j;
275 char **doc, *line;
276 int fd, usefile;
277
278 doc = (char **)shell_builtins[i].long_doc;
279
280 usefile = (doc && doc[0] && *doc[0] == '/' && doc[1] == (char *)NULL);
281 if (usefile)
282 {
283 fd = open_helpfile (doc[0]);
284 if (fd < 0)
285 return;
286 zmapfd (fd, &line, doc[0]);
287 close (fd);
288 }
289 else
290 line = doc ? _(doc[0]) : (char *)NULL;
291
292 /* NAME */
293 printf ("NAME\n");
294 printf ("%*s%s - ", BASE_INDENT, " ", name);
295 for (j = 0; line && line[j]; j++)
296 {
297 putchar (line[j]);
298 if (line[j] == '\n')
299 break;
300 }
301 printf ("\n");
302
303 /* SYNOPSIS */
304 printf ("SYNOPSIS\n");
495aee44 305 printf ("%*s%s\n\n", BASE_INDENT, " ", _(shell_builtins[i].short_doc));
3185942a
JA
306
307 /* DESCRIPTION */
308 printf ("DESCRIPTION\n");
309 if (usefile == 0)
310 {
311 for (j = 0; doc[j]; j++)
312 printf ("%*s%s\n", BASE_INDENT, " ", _(doc[j]));
313 }
314 else
315 {
316 for (j = 0; line && line[j]; j++)
317 {
318 putchar (line[j]);
319 if (line[j] == '\n')
320 printf ("%*s", BASE_INDENT, " ");
321 }
322 }
323 putchar ('\n');
324
325 /* SEE ALSO */
326 printf ("SEE ALSO\n");
327 printf ("%*sbash(1)\n\n", BASE_INDENT, " ");
328
329 /* IMPLEMENTATION */
330 printf ("IMPLEMENTATION\n");
331 printf ("%*s", BASE_INDENT, " ");
332 show_shell_version (0);
333 printf ("%*s", BASE_INDENT, " ");
334 printf ("%s\n", _(bash_copyright));
335 printf ("%*s", BASE_INDENT, " ");
336 printf ("%s\n", _(bash_license));
337
338 fflush (stdout);
339 if (usefile)
340 free (line);
341}
342
ac50fbac
CR
343static void
344dispcolumn (i, buf, bufsize, width, height)
345 int i;
346 char *buf;
347 size_t bufsize;
348 int width, height;
349{
350 int j;
351 int displen;
352 char *helpdoc;
353
354 /* first column */
355 helpdoc = _(shell_builtins[i].short_doc);
356
357 buf[0] = (shell_builtins[i].flags & BUILTIN_ENABLED) ? ' ' : '*';
358 strncpy (buf + 1, helpdoc, width - 2);
359 buf[width - 2] = '>'; /* indicate truncation */
360 buf[width - 1] = '\0';
361 printf ("%s", buf);
362 if (((i << 1) >= num_shell_builtins) || (i+height >= num_shell_builtins))
363 {
364 printf ("\n");
365 return;
366 }
367
368 displen = strlen (buf);
369 /* two spaces */
370 for (j = displen; j < width; j++)
371 putc (' ', stdout);
372
373 /* second column */
374 helpdoc = _(shell_builtins[i+height].short_doc);
375
376 buf[0] = (shell_builtins[i+height].flags & BUILTIN_ENABLED) ? ' ' : '*';
377 strncpy (buf + 1, helpdoc, width - 3);
378 buf[width - 3] = '>'; /* indicate truncation */
379 buf[width - 2] = '\0';
380
381 printf ("%s\n", buf);
382}
383
384#if defined (HANDLE_MULTIBYTE)
385static void
386wdispcolumn (i, buf, bufsize, width, height)
387 int i;
388 char *buf;
389 size_t bufsize;
390 int width, height;
391{
392 int j;
393 int displen;
394 char *helpdoc;
395 wchar_t *wcstr;
396 size_t slen, n;
397 int wclen;
398
399 /* first column */
400 helpdoc = _(shell_builtins[i].short_doc);
401
402 wcstr = 0;
403 slen = mbstowcs ((wchar_t *)0, helpdoc, 0);
404 if (slen == -1)
405 {
406 dispcolumn (i, buf, bufsize, width, height);
407 return;
408 }
409
410 /* No bigger than the passed max width */
411 if (slen >= width)
412 slen = width - 2;
413 wcstr = (wchar_t *)xmalloc (sizeof (wchar_t) * (width + 2));
414 n = mbstowcs (wcstr+1, helpdoc, slen + 1);
415 wcstr[n+1] = L'\0';
416
417 /* Turn tabs and newlines into spaces for column display, since wcwidth
418 returns -1 for them */
419 for (j = 1; j < n; j++)
420 if (wcstr[j] == L'\n' || wcstr[j] == L'\t')
421 wcstr[j] = L' ';
422
423 displen = wcsnwidth (wcstr+1, slen, width - 2) + 1; /* +1 for ' ' or '*' */
424
425 wcstr[0] = (shell_builtins[i].flags & BUILTIN_ENABLED) ? L' ' : L'*';
426
427 /* This assumes each wide char takes up one column position when displayed */
428 wcstr[width - 2] = L'>'; /* indicate truncation */
429 wcstr[width - 1] = L'\0';
430
431 printf ("%ls", wcstr);
432 if (((i << 1) >= num_shell_builtins) || (i+height >= num_shell_builtins))
433 {
434 printf ("\n");
435 return;
436 }
437
438 /* at least one space */
439 for (j = displen; j < width; j++)
440 putc (' ', stdout);
441
442 /* second column */
443 helpdoc = _(shell_builtins[i+height].short_doc);
444 slen = mbstowcs ((wchar_t *)0, helpdoc, 0);
445 if (slen == -1)
446 {
447 /* for now */
448 printf ("%c%s\n", (shell_builtins[i+height].flags & BUILTIN_ENABLED) ? ' ' : '*', helpdoc);
449 return;
450 }
451
452 /* Reuse wcstr since it is already width wide chars long */
453 if (slen >= width)
454 slen = width - 2;
455 n = mbstowcs (wcstr+1, helpdoc, slen + 1);
456 wcstr[n+1] = L'\0'; /* make sure null-terminated */
457
458 /* Turn tabs and newlines into spaces for column display */
459 for (j = 1; j < n; j++)
460 if (wcstr[j] == L'\n' || wcstr[j] == L'\t')
461 wcstr[j] = L' ';
462
463 displen = wcsnwidth (wcstr+1, slen, width - 2);
464
465 wcstr[0] = (shell_builtins[i+height].flags & BUILTIN_ENABLED) ? L' ' : L'*';
466
467 /* This assumes each wide char takes up one column position when displayed */
468 wcstr[width - 3] = L'>'; /* indicate truncation */
469 wcstr[width - 2] = L'\0';
470
471 printf ("%ls\n", wcstr);
472
473 free (wcstr);
474}
475#endif /* HANDLE_MULTIBYTE */
476
ccc6cda3
JA
477static void
478show_builtin_command_help ()
479{
480 int i, j;
3185942a
JA
481 int height, width;
482 char *t, blurb[128];
ccc6cda3
JA
483
484 printf (
b80f6443 485_("These shell commands are defined internally. Type `help' to see this list.\n\
ccc6cda3
JA
486Type `help name' to find out more about the function `name'.\n\
487Use `info bash' to find out more about the shell in general.\n\
7117c2d2 488Use `man -k' or `info' to find out more about commands not in this list.\n\
ccc6cda3
JA
489\n\
490A star (*) next to a name means that the command is disabled.\n\
b80f6443 491\n"));
ccc6cda3 492
3185942a
JA
493 t = get_string_value ("COLUMNS");
494 width = (t && *t) ? atoi (t) : 80;
495 if (width <= 0)
496 width = 80;
497
498 width /= 2;
499 if (width > sizeof (blurb))
500 width = sizeof (blurb);
0001803f
CR
501 if (width <= 3)
502 width = 40;
3185942a
JA
503 height = (num_shell_builtins + 1) / 2; /* number of rows */
504
505 for (i = 0; i < height; i++)
ccc6cda3
JA
506 {
507 QUIT;
3185942a 508
ac50fbac
CR
509#if defined (HANDLE_MULTIBYTE)
510 if (MB_CUR_MAX > 1)
511 wdispcolumn (i, blurb, sizeof (blurb), width, height);
512 else
513#endif
514 dispcolumn (i, blurb, sizeof (blurb), width, height);
ccc6cda3 515 }
ccc6cda3
JA
516}
517#endif /* HELP_BUILTIN */