~ubuntu-branches/ubuntu/trusty/bash/trusty-security

« back to all changes in this revision

Viewing changes to builtins/help.def

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2014-03-03 22:52:05 UTC
  • mfrom: (1.3.5) (2.2.6 experimental)
  • Revision ID: package-import@ubuntu.com-20140303225205-87ltrt5kspeq0g1b
Tags: 4.3-1ubuntu1
* Merge with Debian; remaining changes:
  - skel.bashrc:
    - Run lesspipe.
    - Enable ls aliases.
    - Set options in ll alias to -alF.
    - Define an alert alias.
    - Enabled colored grep aliases.
  - etc.bash.bashrc:
    - Add sudo hint.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 */