50b4dc7a37b80ddf68f2e9a64ef319855738db03
[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, 1989, 1991 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       builtin_error ("restricted");
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   else
250     b->flags |= BUILTIN_ENABLED;
251
252 #if defined (PROGRAMMABLE_COMPLETION)
253   set_itemlist_dirty (&it_enabled);
254   set_itemlist_dirty (&it_disabled);
255 #endif
256
257   return (EXECUTION_SUCCESS);
258 }
259
260 #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
261
262 #if defined (HAVE_DLFCN_H)
263 #  include <dlfcn.h>
264 #endif
265
266 static int
267 dyn_load_builtin (list, flags, filename)
268      WORD_LIST *list;
269      int flags;
270      char *filename;
271 {
272   WORD_LIST *l;
273   void *handle;
274   
275   int total, size, new, replaced;
276   char *struct_name, *name;
277   struct builtin **new_builtins, *b, *new_shell_builtins, *old_builtin;
278
279   if (list == 0)
280     return (EXECUTION_FAILURE);
281
282 #ifndef RTLD_LAZY
283 #define RTLD_LAZY 1
284 #endif
285
286 #if defined (_AIX)
287   handle = dlopen (filename, RTLD_NOW|RTLD_GLOBAL);
288 #else
289   handle = dlopen (filename, RTLD_LAZY);
290 #endif /* !_AIX */
291
292   if (handle == 0)
293     {
294       builtin_error ("cannot open shared object %s: %s", filename, dlerror ());
295       return (EXECUTION_FAILURE);
296     }
297
298   for (new = 0, l = list; l; l = l->next, new++)
299     ;
300   new_builtins = (struct builtin **)xmalloc (new * sizeof (struct builtin *));
301
302   /* For each new builtin in the shared object, find it and its describing
303      structure.  If this is overwriting an existing builtin, do so, otherwise
304      save the loaded struct for creating the new list of builtins. */
305   for (replaced = new = 0; list; list = list->next)
306     {
307       name = list->word->word;
308
309       size = strlen (name);
310       struct_name = (char *)xmalloc (size + 8);
311       strcpy (struct_name, name);
312       strcpy (struct_name + size, "_struct");
313
314       b = (struct builtin *)dlsym (handle, struct_name);
315       if (b == 0)
316         {
317           builtin_error ("cannot find %s in shared object %s: %s", struct_name,
318                           filename, dlerror ());
319           free (struct_name);
320           continue;
321         }
322
323       free (struct_name);
324
325       b->flags &= ~STATIC_BUILTIN;
326       if (flags & SPECIAL)
327         b->flags |= SPECIAL_BUILTIN;
328       b->handle = handle;
329
330       if (old_builtin = builtin_address_internal (name, 1))
331         {
332           replaced++;
333           FASTCOPY ((char *)b, (char *)old_builtin, sizeof (struct builtin));
334         }
335       else
336           new_builtins[new++] = b;
337     }
338
339   if (replaced == 0 && new == 0)
340     {
341       free (new_builtins);
342       dlclose (handle);
343       return (EXECUTION_FAILURE);
344     }
345
346   if (new)
347     {
348       total = num_shell_builtins + new;
349       size = (total + 1) * sizeof (struct builtin);
350
351       new_shell_builtins = (struct builtin *)xmalloc (size);
352       FASTCOPY ((char *)shell_builtins, (char *)new_shell_builtins,
353                 num_shell_builtins * sizeof (struct builtin));
354       for (replaced = 0; replaced < new; replaced++)
355         FASTCOPY ((char *)new_builtins[replaced],
356                   (char *)&new_shell_builtins[num_shell_builtins + replaced],
357                   sizeof (struct builtin));
358
359       new_shell_builtins[total].name = (char *)0;
360       new_shell_builtins[total].function = (sh_builtin_func_t *)0;
361       new_shell_builtins[total].flags = 0;
362
363       if (shell_builtins != static_shell_builtins)
364         free (shell_builtins);
365
366       shell_builtins = new_shell_builtins;
367       num_shell_builtins = total;
368       initialize_shell_builtins ();
369     }
370
371   free (new_builtins);
372   return (EXECUTION_SUCCESS);
373 }
374 #endif
375
376 #if defined (HAVE_DLCLOSE)
377 static void
378 delete_builtin (b)
379      struct builtin *b;
380 {
381   int ind, size;
382   struct builtin *new_shell_builtins;
383
384   /* XXX - funky pointer arithmetic - XXX */
385 #ifdef __STDC__
386   ind = b - shell_builtins;
387 #else
388   ind = ((int)b - (int)shell_builtins) / sizeof (struct builtin);
389 #endif
390   size = num_shell_builtins * sizeof (struct builtin);
391   new_shell_builtins = (struct builtin *)xmalloc (size);
392
393   /* Copy shell_builtins[0]...shell_builtins[ind - 1] to new_shell_builtins */
394   if (ind)
395     FASTCOPY ((char *)shell_builtins, (char *)new_shell_builtins,
396               ind * sizeof (struct builtin));
397   /* Copy shell_builtins[ind+1]...shell_builtins[num_shell_builtins to
398      new_shell_builtins, starting at ind. */
399   FASTCOPY ((char *)(&shell_builtins[ind+1]),
400             (char *)(&new_shell_builtins[ind]),
401             (num_shell_builtins - ind) * sizeof (struct builtin));
402
403   if (shell_builtins != static_shell_builtins)
404     free (shell_builtins);
405
406   /* The result is still sorted. */
407   num_shell_builtins--;
408   shell_builtins = new_shell_builtins;
409 }
410
411 /* Tenon's MachTen has a dlclose that doesn't return a value, so we
412    finesse it with a local wrapper. */
413 static int
414 local_dlclose (handle)
415      void *handle;
416 {
417 #if !defined (__MACHTEN__)
418   return (dlclose (handle));
419 #else /* __MACHTEN__ */
420   dlclose (handle);
421   return ((dlerror () != NULL) ? -1 : 0);    
422 #endif /* __MACHTEN__ */
423 }
424
425 static int
426 dyn_unload_builtin (name)
427      char *name;
428 {
429   struct builtin *b;
430   void *handle;
431   int ref, i;
432
433   b = builtin_address_internal (name, 1);
434   if (b == 0)
435     {
436       builtin_error ("%s: not a shell builtin", name);
437       return (EXECUTION_FAILURE);
438     }
439   if (b->flags & STATIC_BUILTIN)
440     {
441       builtin_error ("%s: not dynamically loaded", name);
442       return (EXECUTION_FAILURE);
443     }
444
445   handle = (void *)b->handle;
446   for (ref = i = 0; i < num_shell_builtins; i++)
447     {
448       if (shell_builtins[i].handle == b->handle)
449         ref++;
450     }
451
452   /* Don't remove the shared object unless the reference count of builtins
453      using it drops to zero. */
454   if (ref == 1 && local_dlclose (handle) != 0)
455     {
456       builtin_error ("cannot delete %s: %s", name, dlerror ());
457       return (EXECUTION_FAILURE);
458     }
459
460   /* Now remove this entry from the builtin table and reinitialize. */
461   delete_builtin (b);
462
463   return (EXECUTION_SUCCESS);
464 }
465 #endif