]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/help.def
Bash-4.4 patch 4
[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
a0c0a00f 4Copyright (C) 1987-2015 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
a0c0a00f 37 PATTERN
3185942a
JA
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>
a0c0a00f 61#include <stddef.h>
7117c2d2 62
b80f6443
JA
63#include "../bashintl.h"
64
726f6388
JA
65#include "../shell.h"
66#include "../builtins.h"
cce855bc 67#include "../pathexp.h"
f73dda09 68#include "common.h"
ccc6cda3
JA
69#include "bashgetopt.h"
70
f73dda09 71#include <glob/strmatch.h>
ccc6cda3 72#include <glob/glob.h>
726f6388 73
7117c2d2
JA
74#ifndef errno
75extern int errno;
76#endif
77
3185942a
JA
78extern const char * const bash_copyright;
79extern const char * const bash_license;
80
a0c0a00f
CR
81extern char *this_command_name;
82extern struct builtin *current_builtin;
83
7117c2d2 84static void show_builtin_command_help __P((void));
3185942a
JA
85static int open_helpfile __P((char *));
86static void show_desc __P((char *, int));
87static void show_manpage __P((char *, int));
7117c2d2 88static void show_longdoc __P((int));
726f6388
JA
89
90/* Print out a list of the known functions in the shell, and what they do.
91 If LIST is supplied, print out the list which matches for each pattern
92 specified. */
ccc6cda3 93int
726f6388
JA
94help_builtin (list)
95 WORD_LIST *list;
96{
7117c2d2 97 register int i;
ccc6cda3 98 char *pattern, *name;
ac50fbac 99 int plen, match_found, sflag, dflag, mflag, m, pass, this_found;
726f6388 100
3185942a 101 dflag = sflag = mflag = 0;
ccc6cda3 102 reset_internal_getopt ();
3185942a 103 while ((i = internal_getopt (list, "dms")) != -1)
ccc6cda3
JA
104 {
105 switch (i)
726f6388 106 {
3185942a
JA
107 case 'd':
108 dflag = 1;
109 break;
110 case 'm':
111 mflag = 1;
112 break;
bb70624e
JA
113 case 's':
114 sflag = 1;
115 break;
a0c0a00f 116 CASE_HELPOPT;
ccc6cda3
JA
117 default:
118 builtin_usage ();
119 return (EX_USAGE);
726f6388 120 }
726f6388 121 }
ccc6cda3 122 list = loptend;
726f6388 123
d166f048
JA
124 if (list == 0)
125 {
126 show_shell_version (0);
127 show_builtin_command_help ();
128 return (EXECUTION_SUCCESS);
129 }
130
ccc6cda3 131 /* We should consider making `help bash' do something. */
726f6388 132
ccc6cda3
JA
133 if (glob_pattern_p (list->word->word))
134 {
3185942a 135 printf (ngettext ("Shell commands matching keyword `", "Shell commands matching keywords `", (list->next ? 2 : 1)));
ccc6cda3
JA
136 print_word_list (list, ", ");
137 printf ("'\n\n");
138 }
726f6388 139
ccc6cda3
JA
140 for (match_found = 0, pattern = ""; list; list = list->next)
141 {
142 pattern = list->word->word;
143 plen = strlen (pattern);
726f6388 144
ac50fbac 145 for (pass = 1, this_found = 0; pass < 3; pass++)
ccc6cda3 146 {
ac50fbac 147 for (i = 0; name = shell_builtins[i].name; i++)
726f6388 148 {
ac50fbac
CR
149 QUIT;
150
151 /* First pass: look for exact string or pattern matches.
152 Second pass: look for prefix matches like bash-4.2 */
153 if (pass == 1)
154 m = (strcmp (pattern, name) == 0) ||
155 (strmatch (pattern, name, FNMATCH_EXTFLAG) != FNM_NOMATCH);
156 else
157 m = strncmp (pattern, name, plen) == 0;
158
159 if (m)
160 {
161 this_found = 1;
162 match_found++;
163 if (dflag)
164 {
165 show_desc (name, i);
166 continue;
167 }
168 else if (mflag)
169 {
170 show_manpage (name, i);
171 continue;
172 }
173
174 printf ("%s: %s\n", name, _(shell_builtins[i].short_doc));
175
176 if (sflag == 0)
177 show_longdoc (i);
178 }
726f6388 179 }
ac50fbac
CR
180 if (pass == 1 && this_found == 1)
181 break;
726f6388 182 }
ccc6cda3 183 }
726f6388 184
ccc6cda3
JA
185 if (match_found == 0)
186 {
b80f6443 187 builtin_error (_("no help topics match `%s'. Try `help help' or `man -k %s' or `info %s'."), pattern, pattern, pattern);
ccc6cda3 188 return (EXECUTION_FAILURE);
726f6388 189 }
ccc6cda3 190
726f6388
JA
191 fflush (stdout);
192 return (EXECUTION_SUCCESS);
193}
ccc6cda3 194
a0c0a00f
CR
195void
196builtin_help ()
197{
198 int ind;
199 ptrdiff_t d;
200
201 current_builtin = builtin_address_internal (this_command_name, 0);
202 if (current_builtin == 0)
203 return;
204
205 d = current_builtin - shell_builtins;
206
207#if defined (__STDC__)
208 ind = (int)d;
209#else
210 ind = (int)d / sizeof (struct builtin);
211#endif
212
213 printf ("%s: %s\n", this_command_name, _(shell_builtins[ind].short_doc));
214 show_longdoc (ind);
215}
216
3185942a
JA
217static int
218open_helpfile (name)
219 char *name;
220{
221 int fd;
222
223 fd = open (name, O_RDONLY);
224 if (fd == -1)
225 {
226 builtin_error (_("%s: cannot open: %s"), name, strerror (errno));
227 return -1;
228 }
229 return fd;
230}
231
7117c2d2
JA
232/* By convention, enforced by mkbuiltins.c, if separate help files are being
233 used, the long_doc array contains one string -- the full pathname of the
234 help file for this builtin. */
235static void
236show_longdoc (i)
237 int i;
238{
239 register int j;
240 char * const *doc;
241 int fd;
242
243 doc = shell_builtins[i].long_doc;
244
245 if (doc && doc[0] && *doc[0] == '/' && doc[1] == (char *)NULL)
246 {
3185942a
JA
247 fd = open_helpfile (doc[0]);
248 if (fd < 0)
249 return;
7117c2d2
JA
250 zcatfd (fd, 1, doc[0]);
251 close (fd);
252 }
ac50fbac 253 else if (doc)
7117c2d2 254 for (j = 0; doc[j]; j++)
95732b49 255 printf ("%*s%s\n", BASE_INDENT, " ", _(doc[j]));
7117c2d2
JA
256}
257
3185942a
JA
258static void
259show_desc (name, i)
260 char *name;
261 int i;
262{
263 register int j;
264 char **doc, *line;
265 int fd, usefile;
266
267 doc = (char **)shell_builtins[i].long_doc;
268
269 usefile = (doc && doc[0] && *doc[0] == '/' && doc[1] == (char *)NULL);
270 if (usefile)
271 {
272 fd = open_helpfile (doc[0]);
273 if (fd < 0)
274 return;
275 zmapfd (fd, &line, doc[0]);
276 close (fd);
277 }
278 else
279 line = doc ? doc[0] : (char *)NULL;
280
281 printf ("%s - ", name);
282 for (j = 0; line && line[j]; j++)
283 {
284 putchar (line[j]);
285 if (line[j] == '\n')
286 break;
287 }
288
289 fflush (stdout);
290
291 if (usefile)
292 free (line);
293}
294
295/* Print builtin help in pseudo-manpage format. */
296static void
297show_manpage (name, i)
298 char *name;
299 int i;
300{
301 register int j;
302 char **doc, *line;
303 int fd, usefile;
304
305 doc = (char **)shell_builtins[i].long_doc;
306
307 usefile = (doc && doc[0] && *doc[0] == '/' && doc[1] == (char *)NULL);
308 if (usefile)
309 {
310 fd = open_helpfile (doc[0]);
311 if (fd < 0)
312 return;
313 zmapfd (fd, &line, doc[0]);
314 close (fd);
315 }
316 else
317 line = doc ? _(doc[0]) : (char *)NULL;
318
319 /* NAME */
320 printf ("NAME\n");
321 printf ("%*s%s - ", BASE_INDENT, " ", name);
322 for (j = 0; line && line[j]; j++)
323 {
324 putchar (line[j]);
325 if (line[j] == '\n')
326 break;
327 }
328 printf ("\n");
329
330 /* SYNOPSIS */
331 printf ("SYNOPSIS\n");
495aee44 332 printf ("%*s%s\n\n", BASE_INDENT, " ", _(shell_builtins[i].short_doc));
3185942a
JA
333
334 /* DESCRIPTION */
335 printf ("DESCRIPTION\n");
336 if (usefile == 0)
337 {
338 for (j = 0; doc[j]; j++)
339 printf ("%*s%s\n", BASE_INDENT, " ", _(doc[j]));
340 }
341 else
342 {
343 for (j = 0; line && line[j]; j++)
344 {
345 putchar (line[j]);
346 if (line[j] == '\n')
347 printf ("%*s", BASE_INDENT, " ");
348 }
349 }
350 putchar ('\n');
351
352 /* SEE ALSO */
353 printf ("SEE ALSO\n");
354 printf ("%*sbash(1)\n\n", BASE_INDENT, " ");
355
356 /* IMPLEMENTATION */
357 printf ("IMPLEMENTATION\n");
358 printf ("%*s", BASE_INDENT, " ");
359 show_shell_version (0);
360 printf ("%*s", BASE_INDENT, " ");
361 printf ("%s\n", _(bash_copyright));
362 printf ("%*s", BASE_INDENT, " ");
363 printf ("%s\n", _(bash_license));
364
365 fflush (stdout);
366 if (usefile)
367 free (line);
368}
369
ac50fbac
CR
370static void
371dispcolumn (i, buf, bufsize, width, height)
372 int i;
373 char *buf;
374 size_t bufsize;
375 int width, height;
376{
377 int j;
a0c0a00f 378 int dispcols;
ac50fbac
CR
379 char *helpdoc;
380
381 /* first column */
382 helpdoc = _(shell_builtins[i].short_doc);
383
384 buf[0] = (shell_builtins[i].flags & BUILTIN_ENABLED) ? ' ' : '*';
385 strncpy (buf + 1, helpdoc, width - 2);
386 buf[width - 2] = '>'; /* indicate truncation */
387 buf[width - 1] = '\0';
388 printf ("%s", buf);
389 if (((i << 1) >= num_shell_builtins) || (i+height >= num_shell_builtins))
390 {
391 printf ("\n");
392 return;
393 }
394
a0c0a00f 395 dispcols = strlen (buf);
ac50fbac 396 /* two spaces */
a0c0a00f 397 for (j = dispcols; j < width; j++)
ac50fbac
CR
398 putc (' ', stdout);
399
400 /* second column */
401 helpdoc = _(shell_builtins[i+height].short_doc);
402
403 buf[0] = (shell_builtins[i+height].flags & BUILTIN_ENABLED) ? ' ' : '*';
404 strncpy (buf + 1, helpdoc, width - 3);
405 buf[width - 3] = '>'; /* indicate truncation */
406 buf[width - 2] = '\0';
407
408 printf ("%s\n", buf);
409}
410
411#if defined (HANDLE_MULTIBYTE)
412static void
413wdispcolumn (i, buf, bufsize, width, height)
414 int i;
415 char *buf;
416 size_t bufsize;
417 int width, height;
418{
419 int j;
a0c0a00f 420 int dispcols, dispchars;
ac50fbac
CR
421 char *helpdoc;
422 wchar_t *wcstr;
423 size_t slen, n;
424 int wclen;
425
426 /* first column */
427 helpdoc = _(shell_builtins[i].short_doc);
428
429 wcstr = 0;
430 slen = mbstowcs ((wchar_t *)0, helpdoc, 0);
431 if (slen == -1)
432 {
433 dispcolumn (i, buf, bufsize, width, height);
434 return;
435 }
436
437 /* No bigger than the passed max width */
438 if (slen >= width)
439 slen = width - 2;
440 wcstr = (wchar_t *)xmalloc (sizeof (wchar_t) * (width + 2));
441 n = mbstowcs (wcstr+1, helpdoc, slen + 1);
442 wcstr[n+1] = L'\0';
443
444 /* Turn tabs and newlines into spaces for column display, since wcwidth
445 returns -1 for them */
446 for (j = 1; j < n; j++)
447 if (wcstr[j] == L'\n' || wcstr[j] == L'\t')
448 wcstr[j] = L' ';
449
a0c0a00f
CR
450 /* dispchars == number of characters that will be displayed */
451 dispchars = wcsnwidth (wcstr+1, slen, width - 2);
452 /* dispcols == number of columns required to display DISPCHARS */
453 dispcols = wcswidth (wcstr+1, dispchars) + 1; /* +1 for ' ' or '*' */
454
ac50fbac
CR
455 wcstr[0] = (shell_builtins[i].flags & BUILTIN_ENABLED) ? L' ' : L'*';
456
a0c0a00f
CR
457 if (dispcols >= width-2)
458 {
459 wcstr[dispchars] = L'>'; /* indicate truncation */
460 wcstr[dispchars+1] = L'\0';
461 }
ac50fbac
CR
462
463 printf ("%ls", wcstr);
464 if (((i << 1) >= num_shell_builtins) || (i+height >= num_shell_builtins))
465 {
466 printf ("\n");
a0c0a00f 467 free (wcstr);
ac50fbac
CR
468 return;
469 }
470
471 /* at least one space */
a0c0a00f 472 for (j = dispcols; j < width; j++)
ac50fbac
CR
473 putc (' ', stdout);
474
475 /* second column */
476 helpdoc = _(shell_builtins[i+height].short_doc);
477 slen = mbstowcs ((wchar_t *)0, helpdoc, 0);
478 if (slen == -1)
479 {
480 /* for now */
481 printf ("%c%s\n", (shell_builtins[i+height].flags & BUILTIN_ENABLED) ? ' ' : '*', helpdoc);
a0c0a00f 482 free (wcstr);
ac50fbac
CR
483 return;
484 }
485
486 /* Reuse wcstr since it is already width wide chars long */
487 if (slen >= width)
488 slen = width - 2;
489 n = mbstowcs (wcstr+1, helpdoc, slen + 1);
490 wcstr[n+1] = L'\0'; /* make sure null-terminated */
491
492 /* Turn tabs and newlines into spaces for column display */
493 for (j = 1; j < n; j++)
494 if (wcstr[j] == L'\n' || wcstr[j] == L'\t')
495 wcstr[j] = L' ';
496
a0c0a00f
CR
497 /* dispchars == number of characters that will be displayed */
498 dispchars = wcsnwidth (wcstr+1, slen, width - 2);
499 dispcols = wcswidth (wcstr+1, dispchars) + 1; /* +1 for ' ' or '*' */
ac50fbac
CR
500
501 wcstr[0] = (shell_builtins[i+height].flags & BUILTIN_ENABLED) ? L' ' : L'*';
502
a0c0a00f
CR
503 /* The dispchars-1 is there for terminals that behave strangely when you
504 have \n in the nth column for terminal width n; this is what bash-4.3
505 did. */
506 if (dispcols >= width - 2)
507 {
508 wcstr[dispchars-1] = L'>'; /* indicate truncation */
509 wcstr[dispchars] = L'\0';
510 }
ac50fbac
CR
511
512 printf ("%ls\n", wcstr);
513
514 free (wcstr);
515}
516#endif /* HANDLE_MULTIBYTE */
517
ccc6cda3
JA
518static void
519show_builtin_command_help ()
520{
521 int i, j;
3185942a
JA
522 int height, width;
523 char *t, blurb[128];
ccc6cda3
JA
524
525 printf (
b80f6443 526_("These shell commands are defined internally. Type `help' to see this list.\n\
ccc6cda3
JA
527Type `help name' to find out more about the function `name'.\n\
528Use `info bash' to find out more about the shell in general.\n\
7117c2d2 529Use `man -k' or `info' to find out more about commands not in this list.\n\
ccc6cda3
JA
530\n\
531A star (*) next to a name means that the command is disabled.\n\
b80f6443 532\n"));
ccc6cda3 533
3185942a
JA
534 t = get_string_value ("COLUMNS");
535 width = (t && *t) ? atoi (t) : 80;
536 if (width <= 0)
537 width = 80;
538
539 width /= 2;
540 if (width > sizeof (blurb))
541 width = sizeof (blurb);
0001803f
CR
542 if (width <= 3)
543 width = 40;
3185942a
JA
544 height = (num_shell_builtins + 1) / 2; /* number of rows */
545
546 for (i = 0; i < height; i++)
ccc6cda3
JA
547 {
548 QUIT;
3185942a 549
ac50fbac
CR
550#if defined (HANDLE_MULTIBYTE)
551 if (MB_CUR_MAX > 1)
552 wdispcolumn (i, blurb, sizeof (blurb), width, height);
553 else
554#endif
555 dispcolumn (i, blurb, sizeof (blurb), width, height);
ccc6cda3 556 }
ccc6cda3
JA
557}
558#endif /* HELP_BUILTIN */