1 This file is enable.def, from which is created enable.c.
2 It implements the builtin "enable" in Bash.
4 Copyright (C) 1987-2002 Free Software Foundation, Inc.
6 This file is part of GNU Bash, the Bourne Again SHell.
8 Bash is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
13 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License along
19 with Bash; see the file COPYING. If not, write to the Free Software
20 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
25 $FUNCTION enable_builtin
26 $SHORT_DOC enable [-pnds] [-a] [-f filename] [name ...]
27 Enable and disable builtin shell commands. This allows
28 you to use a disk command which has the same name as a shell
29 builtin without specifying a full pathname. If -n is used, the
30 NAMEs become disabled; otherwise NAMEs are enabled. For example,
31 to use the `test' found in $PATH instead of the shell builtin
32 version, type `enable -n test'. On systems supporting dynamic
33 loading, the -f option may be used to load new builtins from the
34 shared object FILENAME. The -d option will delete a builtin
35 previously loaded with -f. If no non-option names are given, or
36 the -p option is supplied, a list of builtins is printed. The
37 -a option means to print every builtin with an indication of whether
38 or not it is enabled. The -s option restricts the output to the POSIX.2
39 `special' builtins. The -n option displays a list of all disabled builtins.
44 #if defined (HAVE_UNISTD_H)
46 # include <sys/types.h>
52 #include "../bashansi.h"
54 #include "../builtins.h"
57 #include "bashgetopt.h"
59 #if defined (PROGRAMMABLE_COMPLETION)
60 # include "../pcomplete.h"
74 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
75 static int dyn_load_builtin __P((WORD_LIST *, int, char *));
78 #if defined (HAVE_DLCLOSE)
79 static int dyn_unload_builtin __P((char *));
80 static void delete_builtin __P((struct builtin *));
81 static int local_dlclose __P((void *));
84 static void list_some_builtins __P((int));
85 static int enable_shell_command __P((char *, int));
87 /* Enable/disable shell commands present in LIST. If list is not specified,
88 then print out a list of shell commands showing which are enabled and
89 which are disabled. */
96 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
100 result = EXECUTION_SUCCESS;
103 reset_internal_getopt ();
104 while ((opt = internal_getopt (list, "adnpsf:")) != -1)
121 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
123 filename = list_optarg;
126 builtin_error ("dynamic loading not available");
129 #if defined (HAVE_DLCLOSE)
134 builtin_error ("dynamic loading not available");
136 #endif /* HAVE_DLCLOSE */
145 #if defined (RESTRICTED_SHELL)
146 /* Restricted shells cannot load new builtins. */
147 if (restricted && (flags & (FFLAG|DFLAG)))
149 sh_restricted ((char *)NULL);
150 return (EXECUTION_FAILURE);
154 if (list == 0 || (flags & PFLAG))
156 filter = (flags & AFLAG) ? (ENABLED | DISABLED)
157 : (flags & NFLAG) ? DISABLED : ENABLED;
162 list_some_builtins (filter);
164 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
165 else if (flags & FFLAG)
167 filter = (flags & NFLAG) ? DISABLED : ENABLED;
171 result = dyn_load_builtin (list, filter, filename);
172 #if defined (PROGRAMMABLE_COMPLETION)
173 set_itemlist_dirty (&it_builtins);
177 #if defined (HAVE_DLCLOSE)
178 else if (flags & DFLAG)
182 opt = dyn_unload_builtin (list->word->word);
183 if (opt == EXECUTION_FAILURE)
184 result = EXECUTION_FAILURE;
187 #if defined (PROGRAMMABLE_COMPLETION)
188 set_itemlist_dirty (&it_builtins);
196 opt = enable_shell_command (list->word->word, flags & NFLAG);
198 if (opt == EXECUTION_FAILURE)
200 builtin_error ("%s: not a shell builtin", list->word->word);
201 result = EXECUTION_FAILURE;
209 /* List some builtins.
210 FILTER is a mask with two slots: ENABLED and DISABLED. */
212 list_some_builtins (filter)
217 for (i = 0; i < num_shell_builtins; i++)
219 if (shell_builtins[i].function == 0 || (shell_builtins[i].flags & BUILTIN_DELETED))
222 if ((filter & SPECIAL) &&
223 (shell_builtins[i].flags & SPECIAL_BUILTIN) == 0)
226 if ((filter & ENABLED) && (shell_builtins[i].flags & BUILTIN_ENABLED))
227 printf ("enable %s\n", shell_builtins[i].name);
228 else if ((filter & DISABLED) &&
229 ((shell_builtins[i].flags & BUILTIN_ENABLED) == 0))
230 printf ("enable -n %s\n", shell_builtins[i].name);
234 /* Enable the shell command NAME. If DISABLE_P is non-zero, then
235 disable NAME instead. */
237 enable_shell_command (name, disable_p)
243 b = builtin_address_internal (name, 1);
245 return (EXECUTION_FAILURE);
248 b->flags &= ~BUILTIN_ENABLED;
249 #if defined (RESTRICTED_SHELL)
250 else if (restricted && ((b->flags & BUILTIN_ENABLED) == 0))
252 sh_restricted ((char *)NULL);
253 return (EXECUTION_FAILURE);
257 b->flags |= BUILTIN_ENABLED;
259 #if defined (PROGRAMMABLE_COMPLETION)
260 set_itemlist_dirty (&it_enabled);
261 set_itemlist_dirty (&it_disabled);
264 return (EXECUTION_SUCCESS);
267 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
269 #if defined (HAVE_DLFCN_H)
274 dyn_load_builtin (list, flags, filename)
282 int total, size, new, replaced;
283 char *struct_name, *name;
284 struct builtin **new_builtins, *b, *new_shell_builtins, *old_builtin;
287 return (EXECUTION_FAILURE);
294 handle = dlopen (filename, RTLD_NOW|RTLD_GLOBAL);
296 handle = dlopen (filename, RTLD_LAZY);
301 builtin_error ("cannot open shared object %s: %s", filename, dlerror ());
302 return (EXECUTION_FAILURE);
305 for (new = 0, l = list; l; l = l->next, new++)
307 new_builtins = (struct builtin **)xmalloc (new * sizeof (struct builtin *));
309 /* For each new builtin in the shared object, find it and its describing
310 structure. If this is overwriting an existing builtin, do so, otherwise
311 save the loaded struct for creating the new list of builtins. */
312 for (replaced = new = 0; list; list = list->next)
314 name = list->word->word;
316 size = strlen (name);
317 struct_name = (char *)xmalloc (size + 8);
318 strcpy (struct_name, name);
319 strcpy (struct_name + size, "_struct");
321 b = (struct builtin *)dlsym (handle, struct_name);
324 builtin_error ("cannot find %s in shared object %s: %s", struct_name,
325 filename, dlerror ());
332 b->flags &= ~STATIC_BUILTIN;
334 b->flags |= SPECIAL_BUILTIN;
337 if (old_builtin = builtin_address_internal (name, 1))
340 FASTCOPY ((char *)b, (char *)old_builtin, sizeof (struct builtin));
343 new_builtins[new++] = b;
346 if (replaced == 0 && new == 0)
350 return (EXECUTION_FAILURE);
355 total = num_shell_builtins + new;
356 size = (total + 1) * sizeof (struct builtin);
358 new_shell_builtins = (struct builtin *)xmalloc (size);
359 FASTCOPY ((char *)shell_builtins, (char *)new_shell_builtins,
360 num_shell_builtins * sizeof (struct builtin));
361 for (replaced = 0; replaced < new; replaced++)
362 FASTCOPY ((char *)new_builtins[replaced],
363 (char *)&new_shell_builtins[num_shell_builtins + replaced],
364 sizeof (struct builtin));
366 new_shell_builtins[total].name = (char *)0;
367 new_shell_builtins[total].function = (sh_builtin_func_t *)0;
368 new_shell_builtins[total].flags = 0;
370 if (shell_builtins != static_shell_builtins)
371 free (shell_builtins);
373 shell_builtins = new_shell_builtins;
374 num_shell_builtins = total;
375 initialize_shell_builtins ();
379 return (EXECUTION_SUCCESS);
383 #if defined (HAVE_DLCLOSE)
389 struct builtin *new_shell_builtins;
391 /* XXX - funky pointer arithmetic - XXX */
393 ind = b - shell_builtins;
395 ind = ((int)b - (int)shell_builtins) / sizeof (struct builtin);
397 size = num_shell_builtins * sizeof (struct builtin);
398 new_shell_builtins = (struct builtin *)xmalloc (size);
400 /* Copy shell_builtins[0]...shell_builtins[ind - 1] to new_shell_builtins */
402 FASTCOPY ((char *)shell_builtins, (char *)new_shell_builtins,
403 ind * sizeof (struct builtin));
404 /* Copy shell_builtins[ind+1]...shell_builtins[num_shell_builtins to
405 new_shell_builtins, starting at ind. */
406 FASTCOPY ((char *)(&shell_builtins[ind+1]),
407 (char *)(&new_shell_builtins[ind]),
408 (num_shell_builtins - ind) * sizeof (struct builtin));
410 if (shell_builtins != static_shell_builtins)
411 free (shell_builtins);
413 /* The result is still sorted. */
414 num_shell_builtins--;
415 shell_builtins = new_shell_builtins;
418 /* Tenon's MachTen has a dlclose that doesn't return a value, so we
419 finesse it with a local wrapper. */
421 local_dlclose (handle)
424 #if !defined (__MACHTEN__)
425 return (dlclose (handle));
426 #else /* __MACHTEN__ */
428 return ((dlerror () != NULL) ? -1 : 0);
429 #endif /* __MACHTEN__ */
433 dyn_unload_builtin (name)
440 b = builtin_address_internal (name, 1);
443 builtin_error ("%s: not a shell builtin", name);
444 return (EXECUTION_FAILURE);
446 if (b->flags & STATIC_BUILTIN)
448 builtin_error ("%s: not dynamically loaded", name);
449 return (EXECUTION_FAILURE);
452 handle = (void *)b->handle;
453 for (ref = i = 0; i < num_shell_builtins; i++)
455 if (shell_builtins[i].handle == b->handle)
459 /* Don't remove the shared object unless the reference count of builtins
460 using it drops to zero. */
461 if (ref == 1 && local_dlclose (handle) != 0)
463 builtin_error ("%s: cannot delete: %s", name, dlerror ());
464 return (EXECUTION_FAILURE);
467 /* Now remove this entry from the builtin table and reinitialize. */
470 return (EXECUTION_SUCCESS);