Imported from ../bash-2.05b.tar.gz.
[platform/upstream/bash.git] / builtins / enable.def
1 This file is enable.def, from which is created enable.c.
2 It implements the builtin "enable" in Bash.
3
4 Copyright (C) 1987-2002 Free Software Foundation, Inc.
5
6 This file is part of GNU Bash, the Bourne Again SHell.
7
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.
12
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.
17
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.
21
22 $PRODUCES enable.c
23
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
41
42 #include <config.h>
43
44 #if defined (HAVE_UNISTD_H)
45 #  ifdef _MINIX
46 #    include <sys/types.h>
47 #  endif
48 #  include <unistd.h>
49 #endif
50
51 #include <stdio.h>
52 #include "../bashansi.h"
53 #include "../shell.h"
54 #include "../builtins.h"
55 #include "../flags.h"
56 #include "common.h"
57 #include "bashgetopt.h"
58
59 #if defined (PROGRAMMABLE_COMPLETION)
60 #  include "../pcomplete.h"
61 #endif
62
63 #define ENABLED  1
64 #define DISABLED 2
65 #define SPECIAL  4
66
67 #define AFLAG   0x01
68 #define DFLAG   0x02
69 #define FFLAG   0x04
70 #define NFLAG   0x08
71 #define PFLAG   0x10
72 #define SFLAG   0x20
73
74 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
75 static int dyn_load_builtin __P((WORD_LIST *, int, char *));
76 #endif
77
78 #if defined (HAVE_DLCLOSE)
79 static int dyn_unload_builtin __P((char *));
80 static void delete_builtin __P((struct builtin *));
81 static int local_dlclose __P((void *));
82 #endif
83
84 static void list_some_builtins __P((int));
85 static int enable_shell_command __P((char *, int));
86
87 /* Enable/disable shell commands present in LIST.  If list is not specified,
88    then print out a list of shell commands showing which are enabled and
89    which are disabled. */
90 int
91 enable_builtin (list)
92      WORD_LIST *list;
93 {
94   int result, flags;
95   int opt, filter;
96 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
97   char *filename;
98 #endif
99
100   result = EXECUTION_SUCCESS;
101   flags = 0;
102
103   reset_internal_getopt ();
104   while ((opt = internal_getopt (list, "adnpsf:")) != -1)
105     {
106       switch (opt)
107         {
108         case 'a':
109           flags |= AFLAG;
110           break;
111         case 'n':
112           flags |= NFLAG;
113           break;
114         case 'p':
115           flags |= PFLAG;
116           break;
117         case 's':
118           flags |= SFLAG;
119           break;
120         case 'f':
121 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
122           flags |= FFLAG;
123           filename = list_optarg;
124           break;
125 #else
126           builtin_error ("dynamic loading not available");
127           return (EX_USAGE);
128 #endif
129 #if defined (HAVE_DLCLOSE)
130         case 'd':
131           flags |= DFLAG;
132           break;
133 #else
134           builtin_error ("dynamic loading not available");
135           return (EX_USAGE);
136 #endif /* HAVE_DLCLOSE */
137         default:
138           builtin_usage ();
139           return (EX_USAGE);
140         }
141     }
142
143   list = loptend;
144
145 #if defined (RESTRICTED_SHELL)
146   /* Restricted shells cannot load new builtins. */
147   if (restricted && (flags & (FFLAG|DFLAG)))
148     {
149       sh_restricted ((char *)NULL);
150       return (EXECUTION_FAILURE);
151     }
152 #endif
153
154   if (list == 0 || (flags & PFLAG))
155     {
156       filter = (flags & AFLAG) ? (ENABLED | DISABLED)
157                                : (flags & NFLAG) ? DISABLED : ENABLED;
158
159       if (flags & SFLAG)
160         filter |= SPECIAL;
161
162       list_some_builtins (filter);
163     }
164 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
165   else if (flags & FFLAG)
166     {
167       filter = (flags & NFLAG) ? DISABLED : ENABLED;
168       if (flags & SFLAG)
169         filter |= SPECIAL;
170
171       result = dyn_load_builtin (list, filter, filename);
172 #if defined (PROGRAMMABLE_COMPLETION)
173       set_itemlist_dirty (&it_builtins);
174 #endif
175     }
176 #endif
177 #if defined (HAVE_DLCLOSE)
178   else if (flags & DFLAG)
179     {
180       while (list)
181         {
182           opt = dyn_unload_builtin (list->word->word);
183           if (opt == EXECUTION_FAILURE)
184             result = EXECUTION_FAILURE;
185           list = list->next;
186         }
187 #if defined (PROGRAMMABLE_COMPLETION)
188       set_itemlist_dirty (&it_builtins);
189 #endif
190     }
191 #endif
192   else
193     {
194       while (list)
195         {
196           opt = enable_shell_command (list->word->word, flags & NFLAG);
197
198           if (opt == EXECUTION_FAILURE)
199             {
200               builtin_error ("%s: not a shell builtin", list->word->word);
201               result = EXECUTION_FAILURE;
202             }
203           list = list->next;
204         }
205     }
206   return (result);
207 }
208
209 /* List some builtins.
210    FILTER is a mask with two slots: ENABLED and DISABLED. */
211 static void
212 list_some_builtins (filter)
213      int filter;
214 {
215   register int i;
216
217   for (i = 0; i < num_shell_builtins; i++)
218     {
219       if (shell_builtins[i].function == 0 || (shell_builtins[i].flags & BUILTIN_DELETED))
220         continue;
221
222       if ((filter & SPECIAL) &&
223           (shell_builtins[i].flags & SPECIAL_BUILTIN) == 0)
224         continue;
225
226       if ((filter & ENABLED) && (shell_builtins[i].flags & BUILTIN_ENABLED))
227         printf ("enable %s\n", shell_builtins[i].name);
228       else if ((filter & DISABLED) &&
229                ((shell_builtins[i].flags & BUILTIN_ENABLED) == 0))
230         printf ("enable -n %s\n", shell_builtins[i].name);
231     }
232 }
233
234 /* Enable the shell command NAME.  If DISABLE_P is non-zero, then
235    disable NAME instead. */
236 static int
237 enable_shell_command (name, disable_p)
238      char *name;
239      int disable_p;
240 {
241   struct builtin *b;
242
243   b = builtin_address_internal (name, 1);
244   if (b == 0)
245     return (EXECUTION_FAILURE);
246
247   if (disable_p)
248     b->flags &= ~BUILTIN_ENABLED;
249 #if defined (RESTRICTED_SHELL)
250   else if (restricted && ((b->flags & BUILTIN_ENABLED) == 0))
251     {
252       sh_restricted ((char *)NULL);
253       return (EXECUTION_FAILURE);
254     }
255 #endif
256   else
257     b->flags |= BUILTIN_ENABLED;
258
259 #if defined (PROGRAMMABLE_COMPLETION)
260   set_itemlist_dirty (&it_enabled);
261   set_itemlist_dirty (&it_disabled);
262 #endif
263
264   return (EXECUTION_SUCCESS);
265 }
266
267 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
268
269 #if defined (HAVE_DLFCN_H)
270 #  include <dlfcn.h>
271 #endif
272
273 static int
274 dyn_load_builtin (list, flags, filename)
275      WORD_LIST *list;
276      int flags;
277      char *filename;
278 {
279   WORD_LIST *l;
280   void *handle;
281   
282   int total, size, new, replaced;
283   char *struct_name, *name;
284   struct builtin **new_builtins, *b, *new_shell_builtins, *old_builtin;
285
286   if (list == 0)
287     return (EXECUTION_FAILURE);
288
289 #ifndef RTLD_LAZY
290 #define RTLD_LAZY 1
291 #endif
292
293 #if defined (_AIX)
294   handle = dlopen (filename, RTLD_NOW|RTLD_GLOBAL);
295 #else
296   handle = dlopen (filename, RTLD_LAZY);
297 #endif /* !_AIX */
298
299   if (handle == 0)
300     {
301       builtin_error ("cannot open shared object %s: %s", filename, dlerror ());
302       return (EXECUTION_FAILURE);
303     }
304
305   for (new = 0, l = list; l; l = l->next, new++)
306     ;
307   new_builtins = (struct builtin **)xmalloc (new * sizeof (struct builtin *));
308
309   /* For each new builtin in the shared object, find it and its describing
310      structure.  If this is overwriting an existing builtin, do so, otherwise
311      save the loaded struct for creating the new list of builtins. */
312   for (replaced = new = 0; list; list = list->next)
313     {
314       name = list->word->word;
315
316       size = strlen (name);
317       struct_name = (char *)xmalloc (size + 8);
318       strcpy (struct_name, name);
319       strcpy (struct_name + size, "_struct");
320
321       b = (struct builtin *)dlsym (handle, struct_name);
322       if (b == 0)
323         {
324           builtin_error ("cannot find %s in shared object %s: %s", struct_name,
325                           filename, dlerror ());
326           free (struct_name);
327           continue;
328         }
329
330       free (struct_name);
331
332       b->flags &= ~STATIC_BUILTIN;
333       if (flags & SPECIAL)
334         b->flags |= SPECIAL_BUILTIN;
335       b->handle = handle;
336
337       if (old_builtin = builtin_address_internal (name, 1))
338         {
339           replaced++;
340           FASTCOPY ((char *)b, (char *)old_builtin, sizeof (struct builtin));
341         }
342       else
343           new_builtins[new++] = b;
344     }
345
346   if (replaced == 0 && new == 0)
347     {
348       free (new_builtins);
349       dlclose (handle);
350       return (EXECUTION_FAILURE);
351     }
352
353   if (new)
354     {
355       total = num_shell_builtins + new;
356       size = (total + 1) * sizeof (struct builtin);
357
358       new_shell_builtins = (struct builtin *)xmalloc (size);
359       FASTCOPY ((char *)shell_builtins, (char *)new_shell_builtins,
360                 num_shell_builtins * sizeof (struct builtin));
361       for (replaced = 0; replaced < new; replaced++)
362         FASTCOPY ((char *)new_builtins[replaced],
363                   (char *)&new_shell_builtins[num_shell_builtins + replaced],
364                   sizeof (struct builtin));
365
366       new_shell_builtins[total].name = (char *)0;
367       new_shell_builtins[total].function = (sh_builtin_func_t *)0;
368       new_shell_builtins[total].flags = 0;
369
370       if (shell_builtins != static_shell_builtins)
371         free (shell_builtins);
372
373       shell_builtins = new_shell_builtins;
374       num_shell_builtins = total;
375       initialize_shell_builtins ();
376     }
377
378   free (new_builtins);
379   return (EXECUTION_SUCCESS);
380 }
381 #endif
382
383 #if defined (HAVE_DLCLOSE)
384 static void
385 delete_builtin (b)
386      struct builtin *b;
387 {
388   int ind, size;
389   struct builtin *new_shell_builtins;
390
391   /* XXX - funky pointer arithmetic - XXX */
392 #ifdef __STDC__
393   ind = b - shell_builtins;
394 #else
395   ind = ((int)b - (int)shell_builtins) / sizeof (struct builtin);
396 #endif
397   size = num_shell_builtins * sizeof (struct builtin);
398   new_shell_builtins = (struct builtin *)xmalloc (size);
399
400   /* Copy shell_builtins[0]...shell_builtins[ind - 1] to new_shell_builtins */
401   if (ind)
402     FASTCOPY ((char *)shell_builtins, (char *)new_shell_builtins,
403               ind * sizeof (struct builtin));
404   /* Copy shell_builtins[ind+1]...shell_builtins[num_shell_builtins to
405      new_shell_builtins, starting at ind. */
406   FASTCOPY ((char *)(&shell_builtins[ind+1]),
407             (char *)(&new_shell_builtins[ind]),
408             (num_shell_builtins - ind) * sizeof (struct builtin));
409
410   if (shell_builtins != static_shell_builtins)
411     free (shell_builtins);
412
413   /* The result is still sorted. */
414   num_shell_builtins--;
415   shell_builtins = new_shell_builtins;
416 }
417
418 /* Tenon's MachTen has a dlclose that doesn't return a value, so we
419    finesse it with a local wrapper. */
420 static int
421 local_dlclose (handle)
422      void *handle;
423 {
424 #if !defined (__MACHTEN__)
425   return (dlclose (handle));
426 #else /* __MACHTEN__ */
427   dlclose (handle);
428   return ((dlerror () != NULL) ? -1 : 0);    
429 #endif /* __MACHTEN__ */
430 }
431
432 static int
433 dyn_unload_builtin (name)
434      char *name;
435 {
436   struct builtin *b;
437   void *handle;
438   int ref, i;
439
440   b = builtin_address_internal (name, 1);
441   if (b == 0)
442     {
443       builtin_error ("%s: not a shell builtin", name);
444       return (EXECUTION_FAILURE);
445     }
446   if (b->flags & STATIC_BUILTIN)
447     {
448       builtin_error ("%s: not dynamically loaded", name);
449       return (EXECUTION_FAILURE);
450     }
451
452   handle = (void *)b->handle;
453   for (ref = i = 0; i < num_shell_builtins; i++)
454     {
455       if (shell_builtins[i].handle == b->handle)
456         ref++;
457     }
458
459   /* Don't remove the shared object unless the reference count of builtins
460      using it drops to zero. */
461   if (ref == 1 && local_dlclose (handle) != 0)
462     {
463       builtin_error ("%s: cannot delete: %s", name, dlerror ());
464       return (EXECUTION_FAILURE);
465     }
466
467   /* Now remove this entry from the builtin table and reinitialize. */
468   delete_builtin (b);
469
470   return (EXECUTION_SUCCESS);
471 }
472 #endif