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