004abe29f7fbcbf7d7ac62a3238d6703a991e8a6
[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-2009 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 [-ds] [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;
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 (i = 0; name = shell_builtins[i].name; i++)
141         {
142           QUIT;
143           if ((strncmp (pattern, name, plen) == 0) ||
144               (strmatch (pattern, name, FNMATCH_EXTFLAG) != FNM_NOMATCH))
145             {
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
158               printf ("%s: %s\n", name, shell_builtins[i].short_doc);
159
160               if (sflag == 0)
161                 show_longdoc (i);
162             }
163         }
164     }
165
166   if (match_found == 0)
167     {
168       builtin_error (_("no help topics match `%s'.  Try `help help' or `man -k %s' or `info %s'."), pattern, pattern, pattern);
169       return (EXECUTION_FAILURE);
170     }
171
172   fflush (stdout);
173   return (EXECUTION_SUCCESS);
174 }
175
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
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     {
206       fd = open_helpfile (doc[0]);
207       if (fd < 0)
208         return;
209       zcatfd (fd, 1, doc[0]);
210       close (fd);
211     }
212   else
213     for (j = 0; doc[j]; j++)
214       printf ("%*s%s\n", BASE_INDENT, " ", _(doc[j]));
215 }
216
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");
291   printf ("%*s%s\n\n", BASE_INDENT, " ", shell_builtins[i].short_doc);
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
329 static void
330 show_builtin_command_help ()
331 {
332   int i, j;
333   int height, width;
334   char *t, blurb[128];
335
336   printf (
337 _("These shell commands are defined internally.  Type `help' to see this list.\n\
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\
340 Use `man -k' or `info' to find out more about commands not in this list.\n\
341 \n\
342 A star (*) next to a name means that the command is disabled.\n\
343 \n"));
344
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);
353   height = (num_shell_builtins + 1) / 2;        /* number of rows */
354
355   for (i = 0; i < height; i++)
356     {
357       QUIT;
358
359       /* first column */
360       blurb[0] = (shell_builtins[i].flags & BUILTIN_ENABLED) ? ' ' : '*';
361       strncpy (blurb + 1, shell_builtins[i].short_doc, width - 2);
362       blurb[width - 2] = '>';           /* indicate truncation */
363       blurb[width - 1] = '\0';
364       printf ("%s", blurb);
365       if (((i << 1) >= num_shell_builtins) || (i+height >= num_shell_builtins))
366         {
367           printf ("\n");
368           break;
369         }
370
371       /* two spaces */
372       for (j = strlen (blurb); j < width; j++)
373         putc (' ', stdout);
374
375       /* second column */
376       blurb[0] = (shell_builtins[i+height].flags & BUILTIN_ENABLED) ? ' ' : '*';
377       strncpy (blurb + 1, shell_builtins[i+height].short_doc, width - 3);
378       blurb[width - 3] = '>';           /* indicate truncation */
379       blurb[width - 2] = '\0';
380       printf ("%s\n", blurb);
381     }
382 }
383 #endif /* HELP_BUILTIN */