improve of cmpl.
[bush.git] / builtins / enable.def
blob710ce31b406055daa70846ad1a4a8dcdbc112e66
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/>.
21 $PRODUCES enable.c
23 $BUILTIN enable
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.
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
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'.
47 Exit Status:
48 Returns success unless NAME is not a shell builtin or an error occurs.
49 $END
51 #include <config.h>
53 #if defined (HAVE_UNISTD_H)
54 # ifdef _MINIX
55 # include <sys/types.h>
56 # endif
57 # include <unistd.h>
58 #endif
60 #include <stdio.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"
67 #include "common.h"
68 #include "bushgetopt.h"
69 #include "impl/findcmd.h"
71 #if defined (PROGRAMMABLE_COMPLETION)
72 # include "../src/pcomplete.h"
73 #endif
75 #define ENABLED 1
76 #define DISABLED 2
77 #define SPECIAL 4
79 #define AFLAG 0x01
80 #define DFLAG 0x02
81 #define FFLAG 0x04
82 #define NFLAG 0x08
83 #define PFLAG 0x10
84 #define SFLAG 0x20
86 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
87 static int dyn_load_builtin PARAMS((WORD_LIST *, int, char *));
88 #endif
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 *));
94 #endif
96 #define STRUCT_SUFFIX "_struct"
97 /* for now */
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)
109 WORD_LIST *list;
111 int result, flags;
112 int opt, filter;
113 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
114 char *filename;
115 #endif
117 result = EXECUTION_SUCCESS;
118 flags = 0;
120 reset_internal_getopt ();
121 while ((opt = internal_getopt (list, "adnpsf:")) != -1)
123 switch (opt)
125 case 'a':
126 flags |= AFLAG;
127 break;
128 case 'n':
129 flags |= NFLAG;
130 break;
131 case 'p':
132 flags |= PFLAG;
133 break;
134 case 's':
135 flags |= SFLAG;
136 break;
137 case 'f':
138 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
139 flags |= FFLAG;
140 filename = list_optarg;
141 break;
142 #else
143 builtin_error (_("dynamic loading not available"));
144 return (EX_USAGE);
145 #endif
146 #if defined (HAVE_DLCLOSE)
147 case 'd':
148 flags |= DFLAG;
149 break;
150 #else
151 builtin_error (_("dynamic loading not available"));
152 return (EX_USAGE);
153 #endif /* HAVE_DLCLOSE */
154 CASE_HELPOPT;
155 default:
156 builtin_usage ();
157 return (EX_USAGE);
161 list = loptend;
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);
170 #endif
172 if (list == 0 || (flags & PFLAG))
174 filter = (flags & AFLAG) ? (ENABLED | DISABLED)
175 : (flags & NFLAG) ? DISABLED : ENABLED;
177 if (flags & SFLAG)
178 filter |= SPECIAL;
180 list_some_builtins (filter);
182 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
183 else if (flags & FFLAG)
185 filter = (flags & NFLAG) ? DISABLED : ENABLED;
186 if (flags & SFLAG)
187 filter |= SPECIAL;
189 result = dyn_load_builtin (list, filter, filename);
190 #if defined (PROGRAMMABLE_COMPLETION)
191 set_itemlist_dirty (&it_builtins);
192 #endif
194 #endif
195 #if defined (HAVE_DLCLOSE)
196 else if (flags & DFLAG)
198 while (list)
200 opt = dyn_unload_builtin (list->word->word);
201 if (opt == EXECUTION_FAILURE)
202 result = EXECUTION_FAILURE;
203 list = list->next;
205 #if defined (PROGRAMMABLE_COMPLETION)
206 set_itemlist_dirty (&it_builtins);
207 #endif
209 #endif
210 else
212 while (list)
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;
221 list = list->next;
224 return (result);
227 /* List some builtins.
228 FILTER is a mask with two slots: ENABLED and DISABLED. */
229 static void
230 list_some_builtins (filter)
231 int filter;
233 register int i;
235 for (i = 0; i < num_shell_builtins; i++)
237 if (shell_builtins[i].function == 0 || (shell_builtins[i].flags & BUILTIN_DELETED))
238 continue;
240 if ((filter & SPECIAL) &&
241 (shell_builtins[i].flags & SPECIAL_BUILTIN) == 0)
242 continue;
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. */
254 static int
255 enable_shell_command (name, disable_p)
256 char *name;
257 int disable_p;
259 struct builtin *b;
261 b = builtin_address_internal (name, 1);
262 if (b == 0)
263 return (EXECUTION_FAILURE);
265 if (disable_p)
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);
273 #endif
274 else
275 b->flags |= BUILTIN_ENABLED;
277 #if defined (PROGRAMMABLE_COMPLETION)
278 set_itemlist_dirty (&it_enabled);
279 set_itemlist_dirty (&it_disabled);
280 #endif
282 return (EXECUTION_SUCCESS);
285 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
287 #if defined (HAVE_DLFCN_H)
288 # include <dlfcn.h>
289 #endif
291 static int
292 dyn_load_builtin (list, flags, filename)
293 WORD_LIST *list;
294 int flags;
295 char *filename;
297 WORD_LIST *l;
298 void *handle;
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;
306 if (list == 0)
307 return (EXECUTION_FAILURE);
309 #ifndef RTLD_LAZY
310 #define RTLD_LAZY 1
311 #endif
313 handle = 0;
314 if (absolute_program (filename) == 0)
316 loadables_path = get_string_value ("BUSH_LOADABLES_PATH");
317 if (loadables_path)
319 load_path = find_in_path (filename, loadables_path, FS_NODIRS|FS_EXEC_PREFERRED);
320 if (load_path)
322 #if defined (_AIX)
323 handle = dlopen (load_path, RTLD_NOW|RTLD_GLOBAL);
324 #else
325 handle = dlopen (load_path, RTLD_LAZY);
326 #endif /* !_AIX */
327 free (load_path);
332 /* Fall back to current directory for now */
333 if (handle == 0)
334 #if defined (_AIX)
335 handle = dlopen (filename, RTLD_NOW|RTLD_GLOBAL);
336 #else
337 handle = dlopen (filename, RTLD_LAZY);
338 #endif /* !_AIX */
340 if (handle == 0)
342 name = printable_filename (filename, 0);
343 builtin_error (_("cannot open shared object %s: %s"), name, dlerror ());
344 if (name != filename)
345 free (name);
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);
368 if (b == 0)
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)
374 free (name);
375 free (struct_name);
376 continue;
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);
384 if (loadfunc)
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);
390 if (r == 0)
392 builtin_error (_("load function for %s returns failure (%d): not loaded"), name, r);
393 free (funcname);
394 continue;
397 free (funcname);
399 b->flags &= ~STATIC_BUILTIN;
400 if (flags & SPECIAL)
401 b->flags |= SPECIAL_BUILTIN;
402 b->handle = handle;
404 if (old_builtin)
406 replaced++;
407 FASTCOPY ((char *)b, (char *)old_builtin, sizeof (struct builtin));
409 else
410 new_builtins[new++] = b;
413 if (replaced == 0 && new == 0)
415 free (new_builtins);
416 dlclose (handle);
417 return (EXECUTION_FAILURE);
420 if (new)
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 ();
445 free (new_builtins);
446 return (EXECUTION_SUCCESS);
448 #endif
450 #if defined (HAVE_DLCLOSE)
451 static void
452 delete_builtin (b)
453 struct builtin *b;
455 int ind, size;
456 struct builtin *new_shell_builtins;
458 /* XXX - funky pointer arithmetic - XXX */
459 #ifdef __STDC__
460 ind = b - shell_builtins;
461 #else
462 ind = ((int)b - (int)shell_builtins) / sizeof (struct builtin);
463 #endif
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 */
468 if (ind)
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. */
487 static int
488 local_dlclose (handle)
489 void *handle;
491 #if !defined (__MACHTEN__)
492 return (dlclose (handle));
493 #else /* __MACHTEN__ */
494 dlclose (handle);
495 return ((dlerror () != NULL) ? -1 : 0);
496 #endif /* __MACHTEN__ */
499 static int
500 dyn_unload_builtin (name)
501 char *name;
503 struct builtin *b;
504 void *handle;
505 char *funcname;
506 sh_unload_func_t *unloadfunc;
507 int ref, i, size;
509 b = builtin_address_internal (name, 1);
510 if (b == 0)
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)
525 ref++;
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);
535 if (unloadfunc)
536 (*unloadfunc) (name); /* void function */
537 free (funcname);
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. */
548 delete_builtin (b);
550 return (EXECUTION_SUCCESS);
552 #endif