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 1, 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, 675 Mass Ave, Cambridge, MA 02139, 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. If -n is used, the NAMEs become disabled; otherwise
30 NAMEs are enabled. For example, to use the `test' found on your
31 path instead of the shell builtin version, type `enable -n test'.
32 On systems supporting dynamic loading, the -f option may be used
33 to load new builtins from the shared object FILENAME. The -d
34 option will delete a builtin previously loaded with -f. If no
35 non-option names are given, or the -p option is supplied, a list
36 of builtins is printed. The -a option means to print every builtin
37 with an indication of whether or not it is enabled. The -s option
38 restricts the output to the Posix.2 `special' builtins. The -n
39 option displays a list of all disabled builtins.
44 #if defined (HAVE_UNISTD_H)
49 #include "../bashansi.h"
51 #include "../builtins.h"
54 #include "bashgetopt.h"
56 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
57 static int dyn_load_builtin ();
60 #if defined (HAVE_DLCLOSE)
61 static int dyn_unload_builtin ();
75 static int enable_shell_command ();
76 static void list_some_builtins ();
78 /* Enable/disable shell commands present in LIST. If list is not specified,
79 then print out a list of shell commands showing which are enabled and
80 which are disabled. */
87 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
91 result = EXECUTION_SUCCESS;
94 reset_internal_getopt ();
95 while ((opt = internal_getopt (list, "adnpsf:")) != -1)
112 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
114 filename = list_optarg;
117 builtin_error ("dynamic loading not available");
120 #if defined (HAVE_DLCLOSE)
125 builtin_error ("dynamic loading not available");
127 #endif /* HAVE_DLCLOSE */
136 #if defined (RESTRICTED_SHELL)
137 /* Restricted shells cannot load new builtins. */
138 if (restricted && (flags & (FFLAG|DFLAG)))
140 builtin_error ("restricted");
141 return (EXECUTION_FAILURE);
145 if (list == 0 || (flags & PFLAG))
147 filter = (flags & AFLAG) ? (ENABLED | DISABLED)
148 : (flags & NFLAG) ? DISABLED : ENABLED;
153 list_some_builtins (filter);
155 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
156 else if (flags & FFLAG)
158 filter = (flags & NFLAG) ? DISABLED : ENABLED;
162 result = dyn_load_builtin (list, filter, filename);
165 #if defined (HAVE_DLCLOSE)
166 else if (flags & DFLAG)
170 opt = dyn_unload_builtin (list->word->word);
171 if (opt == EXECUTION_FAILURE)
172 result = EXECUTION_FAILURE;
181 opt = enable_shell_command (list->word->word, flags & NFLAG);
183 if (opt == EXECUTION_FAILURE)
185 builtin_error ("%s: not a shell builtin", list->word->word);
186 result = EXECUTION_FAILURE;
194 /* List some builtins.
195 FILTER is a mask with two slots: ENABLED and DISABLED. */
197 list_some_builtins (filter)
202 for (i = 0; i < num_shell_builtins; i++)
204 if (shell_builtins[i].function == 0 || (shell_builtins[i].flags & BUILTIN_DELETED))
207 if ((filter & SPECIAL) &&
208 (shell_builtins[i].flags & SPECIAL_BUILTIN) == 0)
211 if ((filter & ENABLED) && (shell_builtins[i].flags & BUILTIN_ENABLED))
212 printf ("enable %s\n", shell_builtins[i].name);
213 else if ((filter & DISABLED) &&
214 ((shell_builtins[i].flags & BUILTIN_ENABLED) == 0))
215 printf ("enable -n %s\n", shell_builtins[i].name);
219 /* Enable the shell command NAME. If DISABLE_P is non-zero, then
220 disable NAME instead. */
222 enable_shell_command (name, disable_p)
228 b = builtin_address_internal (name, 1);
230 return (EXECUTION_FAILURE);
233 b->flags &= ~BUILTIN_ENABLED;
235 b->flags |= BUILTIN_ENABLED;
237 return (EXECUTION_SUCCESS);
240 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
242 #if defined (HAVE_DLFCN_H)
247 dyn_load_builtin (list, flags, filename)
255 int total, size, new, replaced;
256 char *struct_name, *name;
257 struct builtin **new_builtins, *b, *new_shell_builtins, *old_builtin;
260 return (EXECUTION_FAILURE);
267 handle = dlopen (filename, RTLD_NOW|RTLD_GLOBAL);
269 handle = dlopen (filename, RTLD_LAZY);
274 builtin_error ("cannot open shared object %s: %s", filename, dlerror ());
275 return (EXECUTION_FAILURE);
278 for (new = 0, l = list; l; l = l->next, new++)
280 new_builtins = (struct builtin **)xmalloc (new * sizeof (struct builtin *));
282 /* For each new builtin in the shared object, find it and its describing
283 structure. If this is overwriting an existing builtin, do so, otherwise
284 save the loaded struct for creating the new list of builtins. */
285 for (replaced = new = 0; list; list = list->next)
287 name = list->word->word;
289 size = strlen (name);
290 struct_name = xmalloc (size + 8);
291 strcpy (struct_name, name);
292 strcpy (struct_name + size, "_struct");
294 b = (struct builtin *)dlsym (handle, struct_name);
297 builtin_error ("cannot find %s in shared object %s: %s", struct_name,
298 filename, dlerror ());
305 b->flags &= ~STATIC_BUILTIN;
307 b->flags |= SPECIAL_BUILTIN;
310 if (old_builtin = builtin_address_internal (name, 1))
313 FASTCOPY ((char *)b, (char *)old_builtin, sizeof (struct builtin));
316 new_builtins[new++] = b;
319 if (replaced == 0 && new == 0)
323 return (EXECUTION_FAILURE);
328 total = num_shell_builtins + new;
329 size = (total + 1) * sizeof (struct builtin);
331 new_shell_builtins = (struct builtin *)xmalloc (size);
332 FASTCOPY ((char *)shell_builtins, (char *)new_shell_builtins,
333 num_shell_builtins * sizeof (struct builtin));
334 for (replaced = 0; replaced < new; replaced++)
335 FASTCOPY ((char *)new_builtins[replaced],
336 (char *)&new_shell_builtins[num_shell_builtins + replaced],
337 sizeof (struct builtin));
339 new_shell_builtins[total].name = (char *)0;
340 new_shell_builtins[total].function = (Function *)0;
341 new_shell_builtins[total].flags = 0;
343 if (shell_builtins != static_shell_builtins)
344 free (shell_builtins);
346 shell_builtins = new_shell_builtins;
347 num_shell_builtins = total;
348 initialize_shell_builtins ();
352 return (EXECUTION_SUCCESS);
356 #if defined (HAVE_DLCLOSE)
362 struct builtin *new_shell_builtins;
364 /* XXX - funky pointer arithmetic - XXX */
366 ind = b - shell_builtins;
368 ind = ((int)b - (int)shell_builtins) / sizeof (struct builtin);
370 size = num_shell_builtins * sizeof (struct builtin);
371 new_shell_builtins = (struct builtin *)xmalloc (size);
373 /* Copy shell_builtins[0]...shell_builtins[ind - 1] to new_shell_builtins */
375 FASTCOPY ((char *)shell_builtins, (char *)new_shell_builtins,
376 ind * sizeof (struct builtin));
377 /* Copy shell_builtins[ind+1]...shell_builtins[num_shell_builtins to
378 new_shell_builtins, starting at ind. */
379 FASTCOPY ((char *)(&shell_builtins[ind+1]),
380 (char *)(&new_shell_builtins[ind]),
381 (num_shell_builtins - ind) * sizeof (struct builtin));
383 if (shell_builtins != static_shell_builtins)
384 free (shell_builtins);
386 /* The result is still sorted. */
387 num_shell_builtins--;
388 shell_builtins = new_shell_builtins;
392 dyn_unload_builtin (name)
399 b = builtin_address_internal (name, 1);
402 builtin_error ("%s: not a shell builtin", name);
403 return (EXECUTION_FAILURE);
405 if (b->flags & STATIC_BUILTIN)
407 builtin_error ("%s: not dynamically loaded", name);
408 return (EXECUTION_FAILURE);
411 handle = (void *)b->handle;
412 for (ref = i = 0; i < num_shell_builtins; i++)
414 if (shell_builtins[i].handle == b->handle)
418 /* Don't remove the shared object unless the reference count of builtins
419 using it drops to zero. */
420 if (ref == 1 && dlclose (handle) != 0)
422 builtin_error ("cannot delete %s: %s", name, dlerror ());
423 return (EXECUTION_FAILURE);
426 /* Now remove this entry from the builtin table and reinitialize. */
429 return (EXECUTION_SUCCESS);