Patch-ID: bash32-017
[bash.git] / builtins / enable.def
blob823c38f9bf222178fdd1285cec3d5d584b9d43a1
1 This file is enable.def, from which is created enable.c.
2 It implements the builtin "enable" in Bash.
4 Copyright (C) 1987-2003 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
11 version.
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
16 for more details.
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.
22 $PRODUCES enable.c
24 $BUILTIN enable
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.
40 $END
42 #include <config.h>
44 #if defined (HAVE_UNISTD_H)
45 # ifdef _MINIX
46 # include <sys/types.h>
47 # endif
48 # include <unistd.h>
49 #endif
51 #include <stdio.h>
52 #include "../bashansi.h"
53 #include "../bashintl.h"
55 #include "../shell.h"
56 #include "../builtins.h"
57 #include "../flags.h"
58 #include "common.h"
59 #include "bashgetopt.h"
61 #if defined (PROGRAMMABLE_COMPLETION)
62 # include "../pcomplete.h"
63 #endif
65 #define ENABLED 1
66 #define DISABLED 2
67 #define SPECIAL 4
69 #define AFLAG 0x01
70 #define DFLAG 0x02
71 #define FFLAG 0x04
72 #define NFLAG 0x08
73 #define PFLAG 0x10
74 #define SFLAG 0x20
76 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
77 static int dyn_load_builtin __P((WORD_LIST *, int, char *));
78 #endif
80 #if defined (HAVE_DLCLOSE)
81 static int dyn_unload_builtin __P((char *));
82 static void delete_builtin __P((struct builtin *));
83 static int local_dlclose __P((void *));
84 #endif
86 static void list_some_builtins __P((int));
87 static int enable_shell_command __P((char *, int));
89 /* Enable/disable shell commands present in LIST. If list is not specified,
90 then print out a list of shell commands showing which are enabled and
91 which are disabled. */
92 int
93 enable_builtin (list)
94 WORD_LIST *list;
96 int result, flags;
97 int opt, filter;
98 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
99 char *filename;
100 #endif
102 result = EXECUTION_SUCCESS;
103 flags = 0;
105 reset_internal_getopt ();
106 while ((opt = internal_getopt (list, "adnpsf:")) != -1)
108 switch (opt)
110 case 'a':
111 flags |= AFLAG;
112 break;
113 case 'n':
114 flags |= NFLAG;
115 break;
116 case 'p':
117 flags |= PFLAG;
118 break;
119 case 's':
120 flags |= SFLAG;
121 break;
122 case 'f':
123 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
124 flags |= FFLAG;
125 filename = list_optarg;
126 break;
127 #else
128 builtin_error (_("dynamic loading not available"));
129 return (EX_USAGE);
130 #endif
131 #if defined (HAVE_DLCLOSE)
132 case 'd':
133 flags |= DFLAG;
134 break;
135 #else
136 builtin_error (_("dynamic loading not available"));
137 return (EX_USAGE);
138 #endif /* HAVE_DLCLOSE */
139 default:
140 builtin_usage ();
141 return (EX_USAGE);
145 list = loptend;
147 #if defined (RESTRICTED_SHELL)
148 /* Restricted shells cannot load new builtins. */
149 if (restricted && (flags & (FFLAG|DFLAG)))
151 sh_restricted ((char *)NULL);
152 return (EXECUTION_FAILURE);
154 #endif
156 if (list == 0 || (flags & PFLAG))
158 filter = (flags & AFLAG) ? (ENABLED | DISABLED)
159 : (flags & NFLAG) ? DISABLED : ENABLED;
161 if (flags & SFLAG)
162 filter |= SPECIAL;
164 list_some_builtins (filter);
166 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
167 else if (flags & FFLAG)
169 filter = (flags & NFLAG) ? DISABLED : ENABLED;
170 if (flags & SFLAG)
171 filter |= SPECIAL;
173 result = dyn_load_builtin (list, filter, filename);
174 #if defined (PROGRAMMABLE_COMPLETION)
175 set_itemlist_dirty (&it_builtins);
176 #endif
178 #endif
179 #if defined (HAVE_DLCLOSE)
180 else if (flags & DFLAG)
182 while (list)
184 opt = dyn_unload_builtin (list->word->word);
185 if (opt == EXECUTION_FAILURE)
186 result = EXECUTION_FAILURE;
187 list = list->next;
189 #if defined (PROGRAMMABLE_COMPLETION)
190 set_itemlist_dirty (&it_builtins);
191 #endif
193 #endif
194 else
196 while (list)
198 opt = enable_shell_command (list->word->word, flags & NFLAG);
200 if (opt == EXECUTION_FAILURE)
202 sh_notbuiltin (list->word->word);
203 result = EXECUTION_FAILURE;
205 list = list->next;
208 return (result);
211 /* List some builtins.
212 FILTER is a mask with two slots: ENABLED and DISABLED. */
213 static void
214 list_some_builtins (filter)
215 int filter;
217 register int i;
219 for (i = 0; i < num_shell_builtins; i++)
221 if (shell_builtins[i].function == 0 || (shell_builtins[i].flags & BUILTIN_DELETED))
222 continue;
224 if ((filter & SPECIAL) &&
225 (shell_builtins[i].flags & SPECIAL_BUILTIN) == 0)
226 continue;
228 if ((filter & ENABLED) && (shell_builtins[i].flags & BUILTIN_ENABLED))
229 printf ("enable %s\n", shell_builtins[i].name);
230 else if ((filter & DISABLED) &&
231 ((shell_builtins[i].flags & BUILTIN_ENABLED) == 0))
232 printf ("enable -n %s\n", shell_builtins[i].name);
236 /* Enable the shell command NAME. If DISABLE_P is non-zero, then
237 disable NAME instead. */
238 static int
239 enable_shell_command (name, disable_p)
240 char *name;
241 int disable_p;
243 struct builtin *b;
245 b = builtin_address_internal (name, 1);
246 if (b == 0)
247 return (EXECUTION_FAILURE);
249 if (disable_p)
250 b->flags &= ~BUILTIN_ENABLED;
251 #if defined (RESTRICTED_SHELL)
252 else if (restricted && ((b->flags & BUILTIN_ENABLED) == 0))
254 sh_restricted ((char *)NULL);
255 return (EXECUTION_FAILURE);
257 #endif
258 else
259 b->flags |= BUILTIN_ENABLED;
261 #if defined (PROGRAMMABLE_COMPLETION)
262 set_itemlist_dirty (&it_enabled);
263 set_itemlist_dirty (&it_disabled);
264 #endif
266 return (EXECUTION_SUCCESS);
269 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
271 #if defined (HAVE_DLFCN_H)
272 # include <dlfcn.h>
273 #endif
275 static int
276 dyn_load_builtin (list, flags, filename)
277 WORD_LIST *list;
278 int flags;
279 char *filename;
281 WORD_LIST *l;
282 void *handle;
284 int total, size, new, replaced;
285 char *struct_name, *name;
286 struct builtin **new_builtins, *b, *new_shell_builtins, *old_builtin;
288 if (list == 0)
289 return (EXECUTION_FAILURE);
291 #ifndef RTLD_LAZY
292 #define RTLD_LAZY 1
293 #endif
295 #if defined (_AIX)
296 handle = dlopen (filename, RTLD_NOW|RTLD_GLOBAL);
297 #else
298 handle = dlopen (filename, RTLD_LAZY);
299 #endif /* !_AIX */
301 if (handle == 0)
303 builtin_error (_("cannot open shared object %s: %s"), filename, dlerror ());
304 return (EXECUTION_FAILURE);
307 for (new = 0, l = list; l; l = l->next, new++)
309 new_builtins = (struct builtin **)xmalloc (new * sizeof (struct builtin *));
311 /* For each new builtin in the shared object, find it and its describing
312 structure. If this is overwriting an existing builtin, do so, otherwise
313 save the loaded struct for creating the new list of builtins. */
314 for (replaced = new = 0; list; list = list->next)
316 name = list->word->word;
318 size = strlen (name);
319 struct_name = (char *)xmalloc (size + 8);
320 strcpy (struct_name, name);
321 strcpy (struct_name + size, "_struct");
323 b = (struct builtin *)dlsym (handle, struct_name);
324 if (b == 0)
326 builtin_error (_("cannot find %s in shared object %s: %s"),
327 struct_name, filename, dlerror ());
328 free (struct_name);
329 continue;
332 free (struct_name);
334 b->flags &= ~STATIC_BUILTIN;
335 if (flags & SPECIAL)
336 b->flags |= SPECIAL_BUILTIN;
337 b->handle = handle;
339 if (old_builtin = builtin_address_internal (name, 1))
341 replaced++;
342 FASTCOPY ((char *)b, (char *)old_builtin, sizeof (struct builtin));
344 else
345 new_builtins[new++] = b;
348 if (replaced == 0 && new == 0)
350 free (new_builtins);
351 dlclose (handle);
352 return (EXECUTION_FAILURE);
355 if (new)
357 total = num_shell_builtins + new;
358 size = (total + 1) * sizeof (struct builtin);
360 new_shell_builtins = (struct builtin *)xmalloc (size);
361 FASTCOPY ((char *)shell_builtins, (char *)new_shell_builtins,
362 num_shell_builtins * sizeof (struct builtin));
363 for (replaced = 0; replaced < new; replaced++)
364 FASTCOPY ((char *)new_builtins[replaced],
365 (char *)&new_shell_builtins[num_shell_builtins + replaced],
366 sizeof (struct builtin));
368 new_shell_builtins[total].name = (char *)0;
369 new_shell_builtins[total].function = (sh_builtin_func_t *)0;
370 new_shell_builtins[total].flags = 0;
372 if (shell_builtins != static_shell_builtins)
373 free (shell_builtins);
375 shell_builtins = new_shell_builtins;
376 num_shell_builtins = total;
377 initialize_shell_builtins ();
380 free (new_builtins);
381 return (EXECUTION_SUCCESS);
383 #endif
385 #if defined (HAVE_DLCLOSE)
386 static void
387 delete_builtin (b)
388 struct builtin *b;
390 int ind, size;
391 struct builtin *new_shell_builtins;
393 /* XXX - funky pointer arithmetic - XXX */
394 #ifdef __STDC__
395 ind = b - shell_builtins;
396 #else
397 ind = ((int)b - (int)shell_builtins) / sizeof (struct builtin);
398 #endif
399 size = num_shell_builtins * sizeof (struct builtin);
400 new_shell_builtins = (struct builtin *)xmalloc (size);
402 /* Copy shell_builtins[0]...shell_builtins[ind - 1] to new_shell_builtins */
403 if (ind)
404 FASTCOPY ((char *)shell_builtins, (char *)new_shell_builtins,
405 ind * sizeof (struct builtin));
406 /* Copy shell_builtins[ind+1]...shell_builtins[num_shell_builtins to
407 new_shell_builtins, starting at ind. */
408 FASTCOPY ((char *)(&shell_builtins[ind+1]),
409 (char *)(&new_shell_builtins[ind]),
410 (num_shell_builtins - ind) * sizeof (struct builtin));
412 if (shell_builtins != static_shell_builtins)
413 free (shell_builtins);
415 /* The result is still sorted. */
416 num_shell_builtins--;
417 shell_builtins = new_shell_builtins;
420 /* Tenon's MachTen has a dlclose that doesn't return a value, so we
421 finesse it with a local wrapper. */
422 static int
423 local_dlclose (handle)
424 void *handle;
426 #if !defined (__MACHTEN__)
427 return (dlclose (handle));
428 #else /* __MACHTEN__ */
429 dlclose (handle);
430 return ((dlerror () != NULL) ? -1 : 0);
431 #endif /* __MACHTEN__ */
434 static int
435 dyn_unload_builtin (name)
436 char *name;
438 struct builtin *b;
439 void *handle;
440 int ref, i;
442 b = builtin_address_internal (name, 1);
443 if (b == 0)
445 sh_notbuiltin (name);
446 return (EXECUTION_FAILURE);
448 if (b->flags & STATIC_BUILTIN)
450 builtin_error (_("%s: not dynamically loaded"), name);
451 return (EXECUTION_FAILURE);
454 handle = (void *)b->handle;
455 for (ref = i = 0; i < num_shell_builtins; i++)
457 if (shell_builtins[i].handle == b->handle)
458 ref++;
461 /* Don't remove the shared object unless the reference count of builtins
462 using it drops to zero. */
463 if (ref == 1 && local_dlclose (handle) != 0)
465 builtin_error (_("%s: cannot delete: %s"), name, dlerror ());
466 return (EXECUTION_FAILURE);
469 /* Now remove this entry from the builtin table and reinitialize. */
470 delete_builtin (b);
472 return (EXECUTION_SUCCESS);
474 #endif