Bash-4.3 distribution sources and documentation
[platform/upstream/bash.git] / builtins / help.def
1 This file is help.def, from which is created help.c.
2 It implements the builtin "help" in Bash.
3
4 Copyright (C) 1987-2013 Free Software Foundation, Inc.
5
6 This file is part of GNU Bash, the Bourne Again SHell.
7
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.
12
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.
17
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/>.
20
21 $PRODUCES help.c
22
23 $BUILTIN help
24 $FUNCTION help_builtin
25 $DEPENDS_ON HELP_BUILTIN
26 $SHORT_DOC help [-dms] [pattern ...]
27 Display information about builtin commands.
28
29 Displays brief summaries of builtin commands.  If PATTERN is
30 specified, gives detailed help on all commands matching PATTERN,
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.
44 $END
45
46 #include <config.h>
47
48 #if defined (HELP_BUILTIN)
49 #include <stdio.h>
50
51 #if defined (HAVE_UNISTD_H)
52 #  ifdef _MINIX
53 #    include <sys/types.h>
54 #  endif
55 #  include <unistd.h>
56 #endif
57
58 #include <errno.h>
59
60 #include <filecntl.h>
61
62 #include "../bashintl.h"
63
64 #include "../shell.h"
65 #include "../builtins.h"
66 #include "../pathexp.h"
67 #include "common.h"
68 #include "bashgetopt.h"
69
70 #include <glob/strmatch.h>
71 #include <glob/glob.h>
72
73 #ifndef errno
74 extern int errno;
75 #endif
76
77 extern const char * const bash_copyright;
78 extern const char * const bash_license;
79
80 static void show_builtin_command_help __P((void));
81 static int open_helpfile __P((char *));
82 static void show_desc __P((char *, int));
83 static void show_manpage __P((char *, int));
84 static void show_longdoc __P((int));
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. */
89 int
90 help_builtin (list)
91      WORD_LIST *list;
92 {
93   register int i;
94   char *pattern, *name;
95   int plen, match_found, sflag, dflag, mflag, m, pass, this_found;
96
97   dflag = sflag = mflag = 0;
98   reset_internal_getopt ();
99   while ((i = internal_getopt (list, "dms")) != -1)
100     {
101       switch (i)
102         {
103         case 'd':
104           dflag = 1;
105           break;
106         case 'm':
107           mflag = 1;
108           break;
109         case 's':
110           sflag = 1;
111           break;
112         default:
113           builtin_usage ();
114           return (EX_USAGE);
115         }
116     }
117   list = loptend;
118
119   if (list == 0)
120     {
121       show_shell_version (0);
122       show_builtin_command_help ();
123       return (EXECUTION_SUCCESS);
124     }
125
126   /* We should consider making `help bash' do something. */
127
128   if (glob_pattern_p (list->word->word))
129     {
130       printf (ngettext ("Shell commands matching keyword `", "Shell commands matching keywords `", (list->next ? 2 : 1)));
131       print_word_list (list, ", ");
132       printf ("'\n\n");
133     }
134
135   for (match_found = 0, pattern = ""; list; list = list->next)
136     {
137       pattern = list->word->word;
138       plen = strlen (pattern);
139
140       for (pass = 1, this_found = 0; pass < 3; pass++)
141         {
142           for (i = 0; name = shell_builtins[i].name; i++)
143             {
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                 }
174             }
175           if (pass == 1 && this_found == 1)
176             break;
177         }
178     }
179
180   if (match_found == 0)
181     {
182       builtin_error (_("no help topics match `%s'.  Try `help help' or `man -k %s' or `info %s'."), pattern, pattern, pattern);
183       return (EXECUTION_FAILURE);
184     }
185
186   fflush (stdout);
187   return (EXECUTION_SUCCESS);
188 }
189
190 static int
191 open_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
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.  */
208 static void
209 show_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     {
220       fd = open_helpfile (doc[0]);
221       if (fd < 0)
222         return;
223       zcatfd (fd, 1, doc[0]);
224       close (fd);
225     }
226   else if (doc)
227     for (j = 0; doc[j]; j++)
228       printf ("%*s%s\n", BASE_INDENT, " ", _(doc[j]));
229 }
230
231 static void
232 show_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. */
269 static void
270 show_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");
305   printf ("%*s%s\n\n", BASE_INDENT, " ", _(shell_builtins[i].short_doc));
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
343 static void
344 dispcolumn (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)
385 static void
386 wdispcolumn (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
477 static void
478 show_builtin_command_help ()
479 {
480   int i, j;
481   int height, width;
482   char *t, blurb[128];
483
484   printf (
485 _("These shell commands are defined internally.  Type `help' to see this list.\n\
486 Type `help name' to find out more about the function `name'.\n\
487 Use `info bash' to find out more about the shell in general.\n\
488 Use `man -k' or `info' to find out more about commands not in this list.\n\
489 \n\
490 A star (*) next to a name means that the command is disabled.\n\
491 \n"));
492
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);
501   if (width <= 3)
502     width = 40;
503   height = (num_shell_builtins + 1) / 2;        /* number of rows */
504
505   for (i = 0; i < height; i++)
506     {
507       QUIT;
508
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);
515     }
516 }
517 #endif /* HELP_BUILTIN */