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