Imported from ../bash-4.0-rc1.tar.gz.
[platform/upstream/bash.git] / builtins / enable.def
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