1 This file is enable.def
, from which is created enable.c.
2 It implements the builtin
"enable" in Bush.
4 Copyright (C
) 1987-2020 Free Software Foundation
, Inc.
6 This file is part of GNU Bush
, the Bourne Again SHell.
8 Bush 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.
13 Bush 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.
18 You should have received a copy of the GNU General Public License
19 along with Bush. If not
, see
<http
://www.gnu.org
/licenses
/>.
24 $FUNCTION enable_builtin
25 $SHORT_DOC enable
[-a
] [-dnps
] [-f filename
] [name ...
]
26 Enable and disable shell builtins.
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.
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
38 Options controlling dynamic loading:
39 -f Load builtin NAME from shared object FILENAME
40 -d Remove a builtin loaded with -f
42 Without options, each NAME is enabled.
44 To use the `test' found in $PATH instead of the shell builtin
45 version
, type `enable
-n test
'.
48 Returns success unless NAME is not a shell builtin or an error occurs.
53 #if defined (HAVE_UNISTD_H)
55 # include <sys/types.h>
61 #include "../src/bushansi.h"
62 #include "../src/bushintl.h"
64 #include "../src/shell.h"
65 #include "../src/builtins.h"
66 #include "../src/flags.h"
68 #include "bushgetopt.h"
69 #include "impl/findcmd.h"
71 #if defined (PROGRAMMABLE_COMPLETION)
72 # include "../src/pcomplete.h"
86 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
87 static int dyn_load_builtin PARAMS((WORD_LIST *, int, char *));
90 #if defined (HAVE_DLCLOSE)
91 static int dyn_unload_builtin PARAMS((char *));
92 static void delete_builtin PARAMS((struct builtin *));
93 static int local_dlclose PARAMS((void *));
96 #define STRUCT_SUFFIX "_struct"
98 #define LOAD_SUFFIX "_builtin_load"
99 #define UNLOAD_SUFFIX "_builtin_unload"
101 static void list_some_builtins PARAMS((int));
102 static int enable_shell_command PARAMS((char *, int));
104 /* Enable/disable shell commands present in LIST. If list is not specified,
105 then print out a list of shell commands showing which are enabled and
106 which are disabled. */
108 enable_builtin (list)
113 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
117 result = EXECUTION_SUCCESS;
120 reset_internal_getopt ();
121 while ((opt = internal_getopt (list, "adnpsf:")) != -1)
138 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
140 filename = list_optarg;
143 builtin_error (_("dynamic loading not available"));
146 #if defined (HAVE_DLCLOSE)
151 builtin_error (_("dynamic loading not available"));
153 #endif /* HAVE_DLCLOSE */
163 #if defined (RESTRICTED_SHELL)
164 /* Restricted shells cannot load new builtins. */
165 if (restricted && (flags & (FFLAG|DFLAG)))
167 sh_restricted ((char *)NULL);
168 return (EXECUTION_FAILURE);
172 if (list == 0 || (flags & PFLAG))
174 filter = (flags & AFLAG) ? (ENABLED | DISABLED)
175 : (flags & NFLAG) ? DISABLED : ENABLED;
180 list_some_builtins (filter);
182 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
183 else if (flags & FFLAG)
185 filter = (flags & NFLAG) ? DISABLED : ENABLED;
189 result = dyn_load_builtin (list, filter, filename);
190 #if defined (PROGRAMMABLE_COMPLETION)
191 set_itemlist_dirty (&it_builtins);
195 #if defined (HAVE_DLCLOSE)
196 else if (flags & DFLAG)
200 opt = dyn_unload_builtin (list->word->word);
201 if (opt == EXECUTION_FAILURE)
202 result = EXECUTION_FAILURE;
205 #if defined (PROGRAMMABLE_COMPLETION)
206 set_itemlist_dirty (&it_builtins);
214 opt = enable_shell_command (list->word->word, flags & NFLAG);
216 if (opt == EXECUTION_FAILURE)
218 sh_notbuiltin (list->word->word);
219 result = EXECUTION_FAILURE;
227 /* List some builtins.
228 FILTER is a mask with two slots: ENABLED and DISABLED. */
230 list_some_builtins (filter)
235 for (i = 0; i < num_shell_builtins; i++)
237 if (shell_builtins[i].function == 0 || (shell_builtins[i].flags & BUILTIN_DELETED))
240 if ((filter & SPECIAL) &&
241 (shell_builtins[i].flags & SPECIAL_BUILTIN) == 0)
244 if ((filter & ENABLED) && (shell_builtins[i].flags & BUILTIN_ENABLED))
245 printf ("enable %s\n", shell_builtins[i].name);
246 else if ((filter & DISABLED) &&
247 ((shell_builtins[i].flags & BUILTIN_ENABLED) == 0))
248 printf ("enable -n %s\n", shell_builtins[i].name);
252 /* Enable the shell command NAME. If DISABLE_P is non-zero, then
253 disable NAME instead. */
255 enable_shell_command (name, disable_p)
261 b = builtin_address_internal (name, 1);
263 return (EXECUTION_FAILURE);
266 b->flags &= ~BUILTIN_ENABLED;
267 #if defined (RESTRICTED_SHELL)
268 else if (restricted && ((b->flags & BUILTIN_ENABLED) == 0))
270 sh_restricted ((char *)NULL);
271 return (EXECUTION_FAILURE);
275 b->flags |= BUILTIN_ENABLED;
277 #if defined (PROGRAMMABLE_COMPLETION)
278 set_itemlist_dirty (&it_enabled);
279 set_itemlist_dirty (&it_disabled);
282 return (EXECUTION_SUCCESS);
285 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
287 #if defined (HAVE_DLFCN_H)
292 dyn_load_builtin (list, flags, filename)
300 int total, size, new, replaced, r;
301 char *struct_name, *name, *funcname;
302 sh_load_func_t *loadfunc;
303 struct builtin **new_builtins, *b, *new_shell_builtins, *old_builtin;
304 char *loadables_path, *load_path;
307 return (EXECUTION_FAILURE);
314 if (absolute_program (filename) == 0)
316 loadables_path = get_string_value ("BUSH_LOADABLES_PATH");
319 load_path = find_in_path (filename, loadables_path, FS_NODIRS|FS_EXEC_PREFERRED);
323 handle = dlopen (load_path, RTLD_NOW|RTLD_GLOBAL);
325 handle = dlopen (load_path, RTLD_LAZY);
332 /* Fall back to current directory for now */
335 handle = dlopen (filename, RTLD_NOW|RTLD_GLOBAL);
337 handle = dlopen (filename, RTLD_LAZY);
342 name = printable_filename (filename, 0);
343 builtin_error (_("cannot open shared object %s: %s"), name, dlerror ());
344 if (name != filename)
346 return (EXECUTION_FAILURE);
349 for (new = 0, l = list; l; l = l->next, new++)
351 new_builtins = (struct builtin **)xmalloc (new * sizeof (struct builtin *));
353 /* For each new builtin in the shared object, find it and its describing
354 structure. If this is overwriting an existing builtin, do so, otherwise
355 save the loaded struct for creating the new list of builtins. */
356 for (replaced = new = 0; list; list = list->next)
358 name = list->word->word;
360 size = strlen (name);
361 struct_name = (char *)xmalloc (size + 8);
362 strcpy (struct_name, name);
363 strcpy (struct_name + size, STRUCT_SUFFIX);
365 old_builtin = builtin_address_internal (name, 1);
367 b = (struct builtin *)dlsym (handle, struct_name);
370 name = printable_filename (filename, 0);
371 builtin_error (_("cannot find %s in shared object %s: %s"),
372 struct_name, name, dlerror ());
373 if (name != filename)
379 funcname = xrealloc (struct_name, size + sizeof (LOAD_SUFFIX) + 1);
380 strcpy (funcname, name);
381 strcpy (funcname + size, LOAD_SUFFIX);
383 loadfunc = (sh_load_func_t *)dlsym (handle, funcname);
386 /* Add warning if running an init function more than once */
387 if (old_builtin && (old_builtin->flags & STATIC_BUILTIN) == 0)
388 builtin_warning (_("%s: dynamic builtin already loaded"), name);
389 r = (*loadfunc) (name);
392 builtin_error (_("load function for %s returns failure (%d): not loaded"), name, r);
399 b->flags &= ~STATIC_BUILTIN;
401 b->flags |= SPECIAL_BUILTIN;
407 FASTCOPY ((char *)b, (char *)old_builtin, sizeof (struct builtin));
410 new_builtins[new++] = b;
413 if (replaced == 0 && new == 0)
417 return (EXECUTION_FAILURE);
422 total = num_shell_builtins + new;
423 size = (total + 1) * sizeof (struct builtin);
425 new_shell_builtins = (struct builtin *)xmalloc (size);
426 FASTCOPY ((char *)shell_builtins, (char *)new_shell_builtins,
427 num_shell_builtins * sizeof (struct builtin));
428 for (replaced = 0; replaced < new; replaced++)
429 FASTCOPY ((char *)new_builtins[replaced],
430 (char *)&new_shell_builtins[num_shell_builtins + replaced],
431 sizeof (struct builtin));
433 new_shell_builtins[total].name = (char *)0;
434 new_shell_builtins[total].function = (sh_builtin_func_t *)0;
435 new_shell_builtins[total].flags = 0;
437 if (shell_builtins != static_shell_builtins)
438 free (shell_builtins);
440 shell_builtins = new_shell_builtins;
441 num_shell_builtins = total;
442 initialize_shell_builtins ();
446 return (EXECUTION_SUCCESS);
450 #if defined (HAVE_DLCLOSE)
456 struct builtin *new_shell_builtins;
458 /* XXX - funky pointer arithmetic - XXX */
460 ind = b - shell_builtins;
462 ind = ((int)b - (int)shell_builtins) / sizeof (struct builtin);
464 size = num_shell_builtins * sizeof (struct builtin);
465 new_shell_builtins = (struct builtin *)xmalloc (size);
467 /* Copy shell_builtins[0]...shell_builtins[ind - 1] to new_shell_builtins */
469 FASTCOPY ((char *)shell_builtins, (char *)new_shell_builtins,
470 ind * sizeof (struct builtin));
471 /* Copy shell_builtins[ind+1]...shell_builtins[num_shell_builtins to
472 new_shell_builtins, starting at ind. */
473 FASTCOPY ((char *)(&shell_builtins[ind+1]),
474 (char *)(&new_shell_builtins[ind]),
475 (num_shell_builtins - ind) * sizeof (struct builtin));
477 if (shell_builtins != static_shell_builtins)
478 free (shell_builtins);
480 /* The result is still sorted. */
481 num_shell_builtins--;
482 shell_builtins = new_shell_builtins;
485 /* Tenon's MachTen has a dlclose that doesn
't return a value, so we
486 finesse it with a local wrapper. */
488 local_dlclose (handle)
491 #if !defined (__MACHTEN__)
492 return (dlclose (handle));
493 #else /* __MACHTEN__ */
495 return ((dlerror () != NULL) ? -1 : 0);
496 #endif /* __MACHTEN__ */
500 dyn_unload_builtin (name)
506 sh_unload_func_t *unloadfunc;
509 b = builtin_address_internal (name, 1);
512 sh_notbuiltin (name);
513 return (EXECUTION_FAILURE);
515 if (b->flags & STATIC_BUILTIN)
517 builtin_error (_("%s: not dynamically loaded"), name);
518 return (EXECUTION_FAILURE);
521 handle = (void *)b->handle;
522 for (ref = i = 0; i < num_shell_builtins; i++)
524 if (shell_builtins[i].handle == b->handle)
528 /* Call any unload function */
529 size = strlen (name);
530 funcname = xmalloc (size + sizeof (UNLOAD_SUFFIX) + 1);
531 strcpy (funcname, name);
532 strcpy (funcname + size, UNLOAD_SUFFIX);
534 unloadfunc = (sh_unload_func_t *)dlsym (handle, funcname);
536 (*unloadfunc) (name); /* void function */
539 /* Don't remove the shared object unless the reference count of builtins
540 using it drops to zero.
*/
541 if (ref
== 1 && local_dlclose (handle
) != 0)
543 builtin_error (_("%s: cannot delete: %s"), name
, dlerror ());
544 return (EXECUTION_FAILURE
);
547 /* Now remove this entry from the builtin table and reinitialize.
*/
550 return (EXECUTION_SUCCESS
);