1 This file is enable.def, from which is created enable.c.
2 It implements the builtin "enable" in Bash.
4 Copyright (C) 1987, 1989, 1991 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"
63 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
64 static int dyn_load_builtin ();
67 #if defined (HAVE_DLCLOSE)
68 static int dyn_unload_builtin ();
82 static int enable_shell_command ();
83 static void list_some_builtins ();
85 /* Enable/disable shell commands present in LIST. If list is not specified,
86 then print out a list of shell commands showing which are enabled and
87 which are disabled. */
94 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
98 result = EXECUTION_SUCCESS;
101 reset_internal_getopt ();
102 while ((opt = internal_getopt (list, "adnpsf:")) != -1)
119 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
121 filename = list_optarg;
124 builtin_error ("dynamic loading not available");
127 #if defined (HAVE_DLCLOSE)
132 builtin_error ("dynamic loading not available");
134 #endif /* HAVE_DLCLOSE */
143 #if defined (RESTRICTED_SHELL)
144 /* Restricted shells cannot load new builtins. */
145 if (restricted && (flags & (FFLAG|DFLAG)))
147 builtin_error ("restricted");
148 return (EXECUTION_FAILURE);
152 if (list == 0 || (flags & PFLAG))
154 filter = (flags & AFLAG) ? (ENABLED | DISABLED)
155 : (flags & NFLAG) ? DISABLED : ENABLED;
160 list_some_builtins (filter);
162 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
163 else if (flags & FFLAG)
165 filter = (flags & NFLAG) ? DISABLED : ENABLED;
169 result = dyn_load_builtin (list, filter, filename);
170 #if defined (PROGRAMMABLE_COMPLETION)
171 set_itemlist_dirty (&it_builtins);
175 #if defined (HAVE_DLCLOSE)
176 else if (flags & DFLAG)
180 opt = dyn_unload_builtin (list->word->word);
181 if (opt == EXECUTION_FAILURE)
182 result = EXECUTION_FAILURE;
185 #if defined (PROGRAMMABLE_COMPLETION)
186 set_itemlist_dirty (&it_builtins);
194 opt = enable_shell_command (list->word->word, flags & NFLAG);
196 if (opt == EXECUTION_FAILURE)
198 builtin_error ("%s: not a shell builtin", list->word->word);
199 result = EXECUTION_FAILURE;
207 /* List some builtins.
208 FILTER is a mask with two slots: ENABLED and DISABLED. */
210 list_some_builtins (filter)
215 for (i = 0; i < num_shell_builtins; i++)
217 if (shell_builtins[i].function == 0 || (shell_builtins[i].flags & BUILTIN_DELETED))
220 if ((filter & SPECIAL) &&
221 (shell_builtins[i].flags & SPECIAL_BUILTIN) == 0)
224 if ((filter & ENABLED) && (shell_builtins[i].flags & BUILTIN_ENABLED))
225 printf ("enable %s\n", shell_builtins[i].name);
226 else if ((filter & DISABLED) &&
227 ((shell_builtins[i].flags & BUILTIN_ENABLED) == 0))
228 printf ("enable -n %s\n", shell_builtins[i].name);
232 /* Enable the shell command NAME. If DISABLE_P is non-zero, then
233 disable NAME instead. */
235 enable_shell_command (name, disable_p)
241 b = builtin_address_internal (name, 1);
243 return (EXECUTION_FAILURE);
246 b->flags &= ~BUILTIN_ENABLED;
248 b->flags |= BUILTIN_ENABLED;
250 #if defined (PROGRAMMABLE_COMPLETION)
251 set_itemlist_dirty (&it_enabled);
252 set_itemlist_dirty (&it_disabled);
255 return (EXECUTION_SUCCESS);
258 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
260 #if defined (HAVE_DLFCN_H)
265 dyn_load_builtin (list, flags, filename)
273 int total, size, new, replaced;
274 char *struct_name, *name;
275 struct builtin **new_builtins, *b, *new_shell_builtins, *old_builtin;
278 return (EXECUTION_FAILURE);
285 handle = dlopen (filename, RTLD_NOW|RTLD_GLOBAL);
287 handle = dlopen (filename, RTLD_LAZY);
292 builtin_error ("cannot open shared object %s: %s", filename, dlerror ());
293 return (EXECUTION_FAILURE);
296 for (new = 0, l = list; l; l = l->next, new++)
298 new_builtins = (struct builtin **)xmalloc (new * sizeof (struct builtin *));
300 /* For each new builtin in the shared object, find it and its describing
301 structure. If this is overwriting an existing builtin, do so, otherwise
302 save the loaded struct for creating the new list of builtins. */
303 for (replaced = new = 0; list; list = list->next)
305 name = list->word->word;
307 size = strlen (name);
308 struct_name = xmalloc (size + 8);
309 strcpy (struct_name, name);
310 strcpy (struct_name + size, "_struct");
312 b = (struct builtin *)dlsym (handle, struct_name);
315 builtin_error ("cannot find %s in shared object %s: %s", struct_name,
316 filename, dlerror ());
323 b->flags &= ~STATIC_BUILTIN;
325 b->flags |= SPECIAL_BUILTIN;
328 if (old_builtin = builtin_address_internal (name, 1))
331 FASTCOPY ((char *)b, (char *)old_builtin, sizeof (struct builtin));
334 new_builtins[new++] = b;
337 if (replaced == 0 && new == 0)
341 return (EXECUTION_FAILURE);
346 total = num_shell_builtins + new;
347 size = (total + 1) * sizeof (struct builtin);
349 new_shell_builtins = (struct builtin *)xmalloc (size);
350 FASTCOPY ((char *)shell_builtins, (char *)new_shell_builtins,
351 num_shell_builtins * sizeof (struct builtin));
352 for (replaced = 0; replaced < new; replaced++)
353 FASTCOPY ((char *)new_builtins[replaced],
354 (char *)&new_shell_builtins[num_shell_builtins + replaced],
355 sizeof (struct builtin));
357 new_shell_builtins[total].name = (char *)0;
358 new_shell_builtins[total].function = (Function *)0;
359 new_shell_builtins[total].flags = 0;
361 if (shell_builtins != static_shell_builtins)
362 free (shell_builtins);
364 shell_builtins = new_shell_builtins;
365 num_shell_builtins = total;
366 initialize_shell_builtins ();
370 return (EXECUTION_SUCCESS);
374 #if defined (HAVE_DLCLOSE)
380 struct builtin *new_shell_builtins;
382 /* XXX - funky pointer arithmetic - XXX */
384 ind = b - shell_builtins;
386 ind = ((int)b - (int)shell_builtins) / sizeof (struct builtin);
388 size = num_shell_builtins * sizeof (struct builtin);
389 new_shell_builtins = (struct builtin *)xmalloc (size);
391 /* Copy shell_builtins[0]...shell_builtins[ind - 1] to new_shell_builtins */
393 FASTCOPY ((char *)shell_builtins, (char *)new_shell_builtins,
394 ind * sizeof (struct builtin));
395 /* Copy shell_builtins[ind+1]...shell_builtins[num_shell_builtins to
396 new_shell_builtins, starting at ind. */
397 FASTCOPY ((char *)(&shell_builtins[ind+1]),
398 (char *)(&new_shell_builtins[ind]),
399 (num_shell_builtins - ind) * sizeof (struct builtin));
401 if (shell_builtins != static_shell_builtins)
402 free (shell_builtins);
404 /* The result is still sorted. */
405 num_shell_builtins--;
406 shell_builtins = new_shell_builtins;
409 /* Tenon's MachTen has a dlclose that doesn't return a value, so we
410 finesse it with a local wrapper. */
412 local_dlclose (handle)
415 #if !defined (__MACHTEN__)
416 return (dlclose (handle));
417 #else /* __MACHTEN__ */
419 return ((dlerror () != NULL) ? -1 : 0);
420 #endif /* __MACHTEN__ */
424 dyn_unload_builtin (name)
432 b = builtin_address_internal (name, 1);
435 builtin_error ("%s: not a shell builtin", name);
436 return (EXECUTION_FAILURE);
438 if (b->flags & STATIC_BUILTIN)
440 builtin_error ("%s: not dynamically loaded", name);
441 return (EXECUTION_FAILURE);
444 handle = (void *)b->handle;
445 for (ref = i = 0; i < num_shell_builtins; i++)
447 if (shell_builtins[i].handle == b->handle)
451 /* Don't remove the shared object unless the reference count of builtins
452 using it drops to zero. */
453 if (ref == 1 && local_dlclose (handle) != 0)
455 builtin_error ("cannot delete %s: %s", name, dlerror ());
456 return (EXECUTION_FAILURE);
459 /* Now remove this entry from the builtin table and reinitialize. */
462 return (EXECUTION_SUCCESS);