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

« back to all changes in this revision

Viewing changes to builtins/enable.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 enable.def, from which is created enable.c.
 
2
It implements the builtin "enable" 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 enable.c
 
22
 
 
23
$BUILTIN enable
 
24
$FUNCTION enable_builtin
 
25
$SHORT_DOC enable [-a] [-dnps] [-f filename] [name ...]
 
26
Enable and disable shell builtins.
 
27
 
 
28
Enables and disables builtin shell commands.  Disabling allows you to
 
29
execute a disk command which has the same name as a shell builtin
 
30
without using a full pathname.
 
31
 
 
32
Options:
 
33
  -a    print a list of builtins showing whether or not each is enabled
 
34
  -n    disable each NAME or display a list of disabled builtins
 
35
  -p    print the list of builtins in a reusable format
 
36
  -s    print only the names of Posix `special' builtins
 
37
 
 
38
Options controlling dynamic loading:
 
39
  -f    Load builtin NAME from shared object FILENAME
 
40
  -d    Remove a builtin loaded with -f
 
41
 
 
42
Without options, each NAME is enabled.
 
43
 
 
44
To use the `test' found in $PATH instead of the shell builtin
 
45
version, type `enable -n test'.
 
46
 
 
47
Exit Status:
 
48
Returns success unless NAME is not a shell builtin or an error occurs.
 
49
$END
 
50
 
 
51
#include <config.h>
 
52
 
 
53
#if defined (HAVE_UNISTD_H)
 
54
#  ifdef _MINIX
 
55
#    include <sys/types.h>
 
56
#  endif
 
57
#  include <unistd.h>
 
58
#endif
 
59
 
 
60
#include <stdio.h>
 
61
#include "../bashansi.h"
 
62
#include "../bashintl.h"
 
63
 
 
64
#include "../shell.h"
 
65
#include "../builtins.h"
 
66
#include "../flags.h"
 
67
#include "common.h"
 
68
#include "bashgetopt.h"
 
69
 
 
70
#if defined (PROGRAMMABLE_COMPLETION)
 
71
#  include "../pcomplete.h"
 
72
#endif
 
73
 
 
74
#define ENABLED  1
 
75
#define DISABLED 2
 
76
#define SPECIAL  4
 
77
 
 
78
#define AFLAG   0x01
 
79
#define DFLAG   0x02
 
80
#define FFLAG   0x04
 
81
#define NFLAG   0x08
 
82
#define PFLAG   0x10
 
83
#define SFLAG   0x20
 
84
 
 
85
#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
 
86
static int dyn_load_builtin __P((WORD_LIST *, int, char *));
 
87
#endif
 
88
 
 
89
#if defined (HAVE_DLCLOSE)
 
90
static int dyn_unload_builtin __P((char *));
 
91
static void delete_builtin __P((struct builtin *));
 
92
static int local_dlclose __P((void *));
 
93
#endif
 
94
 
 
95
static void list_some_builtins __P((int));
 
96
static int enable_shell_command __P((char *, int));
 
97
 
 
98
/* Enable/disable shell commands present in LIST.  If list is not specified,
 
99
   then print out a list of shell commands showing which are enabled and
 
100
   which are disabled. */
 
101
int
 
102
enable_builtin (list)
 
103
     WORD_LIST *list;
 
104
{
 
105
  int result, flags;
 
106
  int opt, filter;
 
107
#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
 
108
  char *filename;
 
109
#endif
 
110
 
 
111
  result = EXECUTION_SUCCESS;
 
112
  flags = 0;
 
113
 
 
114
  reset_internal_getopt ();
 
115
  while ((opt = internal_getopt (list, "adnpsf:")) != -1)
 
116
    {
 
117
      switch (opt)
 
118
        {
 
119
        case 'a':
 
120
          flags |= AFLAG;
 
121
          break;
 
122
        case 'n':
 
123
          flags |= NFLAG;
 
124
          break;
 
125
        case 'p':
 
126
          flags |= PFLAG;
 
127
          break;
 
128
        case 's':
 
129
          flags |= SFLAG;
 
130
          break;
 
131
        case 'f':
 
132
#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
 
133
          flags |= FFLAG;
 
134
          filename = list_optarg;
 
135
          break;
 
136
#else
 
137
          builtin_error (_("dynamic loading not available"));
 
138
          return (EX_USAGE);
 
139
#endif
 
140
#if defined (HAVE_DLCLOSE)
 
141
        case 'd':
 
142
          flags |= DFLAG;
 
143
          break;
 
144
#else
 
145
          builtin_error (_("dynamic loading not available"));
 
146
          return (EX_USAGE);
 
147
#endif /* HAVE_DLCLOSE */
 
148
        default:
 
149
          builtin_usage ();
 
150
          return (EX_USAGE);
 
151
        }
 
152
    }
 
153
 
 
154
  list = loptend;
 
155
 
 
156
#if defined (RESTRICTED_SHELL)
 
157
  /* Restricted shells cannot load new builtins. */
 
158
  if (restricted && (flags & (FFLAG|DFLAG)))
 
159
    {
 
160
      sh_restricted ((char *)NULL);
 
161
      return (EXECUTION_FAILURE);
 
162
    }
 
163
#endif
 
164
 
 
165
  if (list == 0 || (flags & PFLAG))
 
166
    {
 
167
      filter = (flags & AFLAG) ? (ENABLED | DISABLED)
 
168
                               : (flags & NFLAG) ? DISABLED : ENABLED;
 
169
 
 
170
      if (flags & SFLAG)
 
171
        filter |= SPECIAL;
 
172
 
 
173
      list_some_builtins (filter);
 
174
    }
 
175
#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
 
176
  else if (flags & FFLAG)
 
177
    {
 
178
      filter = (flags & NFLAG) ? DISABLED : ENABLED;
 
179
      if (flags & SFLAG)
 
180
        filter |= SPECIAL;
 
181
 
 
182
      result = dyn_load_builtin (list, filter, filename);
 
183
#if defined (PROGRAMMABLE_COMPLETION)
 
184
      set_itemlist_dirty (&it_builtins);
 
185
#endif
 
186
    }
 
187
#endif
 
188
#if defined (HAVE_DLCLOSE)
 
189
  else if (flags & DFLAG)
 
190
    {
 
191
      while (list)
 
192
        {
 
193
          opt = dyn_unload_builtin (list->word->word);
 
194
          if (opt == EXECUTION_FAILURE)
 
195
            result = EXECUTION_FAILURE;
 
196
          list = list->next;
 
197
        }
 
198
#if defined (PROGRAMMABLE_COMPLETION)
 
199
      set_itemlist_dirty (&it_builtins);
 
200
#endif
 
201
    }
 
202
#endif
 
203
  else
 
204
    {
 
205
      while (list)
 
206
        {
 
207
          opt = enable_shell_command (list->word->word, flags & NFLAG);
 
208
 
 
209
          if (opt == EXECUTION_FAILURE)
 
210
            {
 
211
              sh_notbuiltin (list->word->word);
 
212
              result = EXECUTION_FAILURE;
 
213
            }
 
214
          list = list->next;
 
215
        }
 
216
    }
 
217
  return (result);
 
218
}
 
219
 
 
220
/* List some builtins.
 
221
   FILTER is a mask with two slots: ENABLED and DISABLED. */
 
222
static void
 
223
list_some_builtins (filter)
 
224
     int filter;
 
225
{
 
226
  register int i;
 
227
 
 
228
  for (i = 0; i < num_shell_builtins; i++)
 
229
    {
 
230
      if (shell_builtins[i].function == 0 || (shell_builtins[i].flags & BUILTIN_DELETED))
 
231
        continue;
 
232
 
 
233
      if ((filter & SPECIAL) &&
 
234
          (shell_builtins[i].flags & SPECIAL_BUILTIN) == 0)
 
235
        continue;
 
236
 
 
237
      if ((filter & ENABLED) && (shell_builtins[i].flags & BUILTIN_ENABLED))
 
238
        printf ("enable %s\n", shell_builtins[i].name);
 
239
      else if ((filter & DISABLED) &&
 
240
               ((shell_builtins[i].flags & BUILTIN_ENABLED) == 0))
 
241
        printf ("enable -n %s\n", shell_builtins[i].name);
 
242
    }
 
243
}
 
244
 
 
245
/* Enable the shell command NAME.  If DISABLE_P is non-zero, then
 
246
   disable NAME instead. */
 
247
static int
 
248
enable_shell_command (name, disable_p)
 
249
     char *name;
 
250
     int disable_p;
 
251
{
 
252
  struct builtin *b;
 
253
 
 
254
  b = builtin_address_internal (name, 1);
 
255
  if (b == 0)
 
256
    return (EXECUTION_FAILURE);
 
257
 
 
258
  if (disable_p)
 
259
    b->flags &= ~BUILTIN_ENABLED;
 
260
#if defined (RESTRICTED_SHELL)
 
261
  else if (restricted && ((b->flags & BUILTIN_ENABLED) == 0))
 
262
    {
 
263
      sh_restricted ((char *)NULL);
 
264
      return (EXECUTION_FAILURE);
 
265
    }
 
266
#endif
 
267
  else
 
268
    b->flags |= BUILTIN_ENABLED;
 
269
 
 
270
#if defined (PROGRAMMABLE_COMPLETION)
 
271
  set_itemlist_dirty (&it_enabled);
 
272
  set_itemlist_dirty (&it_disabled);
 
273
#endif
 
274
 
 
275
  return (EXECUTION_SUCCESS);
 
276
}
 
277
 
 
278
#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
 
279
 
 
280
#if defined (HAVE_DLFCN_H)
 
281
#  include <dlfcn.h>
 
282
#endif
 
283
 
 
284
static int
 
285
dyn_load_builtin (list, flags, filename)
 
286
     WORD_LIST *list;
 
287
     int flags;
 
288
     char *filename;
 
289
{
 
290
  WORD_LIST *l;
 
291
  void *handle;
 
292
  
 
293
  int total, size, new, replaced;
 
294
  char *struct_name, *name;
 
295
  struct builtin **new_builtins, *b, *new_shell_builtins, *old_builtin;
 
296
 
 
297
  if (list == 0)
 
298
    return (EXECUTION_FAILURE);
 
299
 
 
300
#ifndef RTLD_LAZY
 
301
#define RTLD_LAZY 1
 
302
#endif
 
303
 
 
304
#if defined (_AIX)
 
305
  handle = dlopen (filename, RTLD_NOW|RTLD_GLOBAL);
 
306
#else
 
307
  handle = dlopen (filename, RTLD_LAZY);
 
308
#endif /* !_AIX */
 
309
 
 
310
  if (handle == 0)
 
311
    {
 
312
      builtin_error (_("cannot open shared object %s: %s"), filename, dlerror ());
 
313
      return (EXECUTION_FAILURE);
 
314
    }
 
315
 
 
316
  for (new = 0, l = list; l; l = l->next, new++)
 
317
    ;
 
318
  new_builtins = (struct builtin **)xmalloc (new * sizeof (struct builtin *));
 
319
 
 
320
  /* For each new builtin in the shared object, find it and its describing
 
321
     structure.  If this is overwriting an existing builtin, do so, otherwise
 
322
     save the loaded struct for creating the new list of builtins. */
 
323
  for (replaced = new = 0; list; list = list->next)
 
324
    {
 
325
      name = list->word->word;
 
326
 
 
327
      size = strlen (name);
 
328
      struct_name = (char *)xmalloc (size + 8);
 
329
      strcpy (struct_name, name);
 
330
      strcpy (struct_name + size, "_struct");
 
331
 
 
332
      b = (struct builtin *)dlsym (handle, struct_name);
 
333
      if (b == 0)
 
334
        {
 
335
          builtin_error (_("cannot find %s in shared object %s: %s"),
 
336
                          struct_name, filename, dlerror ());
 
337
          free (struct_name);
 
338
          continue;
 
339
        }
 
340
 
 
341
      free (struct_name);
 
342
 
 
343
      b->flags &= ~STATIC_BUILTIN;
 
344
      if (flags & SPECIAL)
 
345
        b->flags |= SPECIAL_BUILTIN;
 
346
      b->handle = handle;
 
347
 
 
348
      if (old_builtin = builtin_address_internal (name, 1))
 
349
        {
 
350
          replaced++;
 
351
          FASTCOPY ((char *)b, (char *)old_builtin, sizeof (struct builtin));
 
352
        }
 
353
      else
 
354
          new_builtins[new++] = b;
 
355
    }
 
356
 
 
357
  if (replaced == 0 && new == 0)
 
358
    {
 
359
      free (new_builtins);
 
360
      dlclose (handle);
 
361
      return (EXECUTION_FAILURE);
 
362
    }
 
363
 
 
364
  if (new)
 
365
    {
 
366
      total = num_shell_builtins + new;
 
367
      size = (total + 1) * sizeof (struct builtin);
 
368
 
 
369
      new_shell_builtins = (struct builtin *)xmalloc (size);
 
370
      FASTCOPY ((char *)shell_builtins, (char *)new_shell_builtins,
 
371
                num_shell_builtins * sizeof (struct builtin));
 
372
      for (replaced = 0; replaced < new; replaced++)
 
373
        FASTCOPY ((char *)new_builtins[replaced],
 
374
                  (char *)&new_shell_builtins[num_shell_builtins + replaced],
 
375
                  sizeof (struct builtin));
 
376
 
 
377
      new_shell_builtins[total].name = (char *)0;
 
378
      new_shell_builtins[total].function = (sh_builtin_func_t *)0;
 
379
      new_shell_builtins[total].flags = 0;
 
380
 
 
381
      if (shell_builtins != static_shell_builtins)
 
382
        free (shell_builtins);
 
383
 
 
384
      shell_builtins = new_shell_builtins;
 
385
      num_shell_builtins = total;
 
386
      initialize_shell_builtins ();
 
387
    }
 
388
 
 
389
  free (new_builtins);
 
390
  return (EXECUTION_SUCCESS);
 
391
}
 
392
#endif
 
393
 
 
394
#if defined (HAVE_DLCLOSE)
 
395
static void
 
396
delete_builtin (b)
 
397
     struct builtin *b;
 
398
{
 
399
  int ind, size;
 
400
  struct builtin *new_shell_builtins;
 
401
 
 
402
  /* XXX - funky pointer arithmetic - XXX */
 
403
#ifdef __STDC__
 
404
  ind = b - shell_builtins;
 
405
#else
 
406
  ind = ((int)b - (int)shell_builtins) / sizeof (struct builtin);
 
407
#endif
 
408
  size = num_shell_builtins * sizeof (struct builtin);
 
409
  new_shell_builtins = (struct builtin *)xmalloc (size);
 
410
 
 
411
  /* Copy shell_builtins[0]...shell_builtins[ind - 1] to new_shell_builtins */
 
412
  if (ind)
 
413
    FASTCOPY ((char *)shell_builtins, (char *)new_shell_builtins,
 
414
              ind * sizeof (struct builtin));
 
415
  /* Copy shell_builtins[ind+1]...shell_builtins[num_shell_builtins to
 
416
     new_shell_builtins, starting at ind. */
 
417
  FASTCOPY ((char *)(&shell_builtins[ind+1]),
 
418
            (char *)(&new_shell_builtins[ind]),
 
419
            (num_shell_builtins - ind) * sizeof (struct builtin));
 
420
 
 
421
  if (shell_builtins != static_shell_builtins)
 
422
    free (shell_builtins);
 
423
 
 
424
  /* The result is still sorted. */
 
425
  num_shell_builtins--;
 
426
  shell_builtins = new_shell_builtins;
 
427
}
 
428
 
 
429
/* Tenon's MachTen has a dlclose that doesn't return a value, so we
 
430
   finesse it with a local wrapper. */
 
431
static int
 
432
local_dlclose (handle)
 
433
     void *handle;
 
434
{
 
435
#if !defined (__MACHTEN__)
 
436
  return (dlclose (handle));
 
437
#else /* __MACHTEN__ */
 
438
  dlclose (handle);
 
439
  return ((dlerror () != NULL) ? -1 : 0);    
 
440
#endif /* __MACHTEN__ */
 
441
}
 
442
 
 
443
static int
 
444
dyn_unload_builtin (name)
 
445
     char *name;
 
446
{
 
447
  struct builtin *b;
 
448
  void *handle;
 
449
  int ref, i;
 
450
 
 
451
  b = builtin_address_internal (name, 1);
 
452
  if (b == 0)
 
453
    {
 
454
      sh_notbuiltin (name);
 
455
      return (EXECUTION_FAILURE);
 
456
    }
 
457
  if (b->flags & STATIC_BUILTIN)
 
458
    {
 
459
      builtin_error (_("%s: not dynamically loaded"), name);
 
460
      return (EXECUTION_FAILURE);
 
461
    }
 
462
 
 
463
  handle = (void *)b->handle;
 
464
  for (ref = i = 0; i < num_shell_builtins; i++)
 
465
    {
 
466
      if (shell_builtins[i].handle == b->handle)
 
467
        ref++;
 
468
    }
 
469
 
 
470
  /* Don't remove the shared object unless the reference count of builtins
 
471
     using it drops to zero. */
 
472
  if (ref == 1 && local_dlclose (handle) != 0)
 
473
    {
 
474
      builtin_error (_("%s: cannot delete: %s"), name, dlerror ());
 
475
      return (EXECUTION_FAILURE);
 
476
    }
 
477
 
 
478
  /* Now remove this entry from the builtin table and reinitialize. */
 
479
  delete_builtin (b);
 
480
 
 
481
  return (EXECUTION_SUCCESS);
 
482
}
 
483
#endif