source: trunk/essentials/app-shells/bash/builtins/enable.def@ 3258

Last change on this file since 3258 was 3228, checked in by bird, 19 years ago

bash 3.1

File size: 11.7 KB
Line 
1This file is enable.def, from which is created enable.c.
2It implements the builtin "enable" in Bash.
3
4Copyright (C) 1987-2003 Free Software Foundation, Inc.
5
6This file is part of GNU Bash, the Bourne Again SHell.
7
8Bash is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 2, or (at your option) any later
11version.
12
13Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License along
19with Bash; see the file COPYING. If not, write to the Free Software
20Foundation, 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 ...]
27Enable and disable builtin shell commands. This allows
28you to use a disk command which has the same name as a shell
29builtin without specifying a full pathname. If -n is used, the
30NAMEs become disabled; otherwise NAMEs are enabled. For example,
31to use the `test' found in $PATH instead of the shell builtin
32version, type `enable -n test'. On systems supporting dynamic
33loading, the -f option may be used to load new builtins from the
34shared object FILENAME. The -d option will delete a builtin
35previously loaded with -f. If no non-option names are given, or
36the -p option is supplied, a list of builtins is printed. The
37-a option means to print every builtin with an indication of whether
38or 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 "../bashintl.h"
54
55#include "../shell.h"
56#include "../builtins.h"
57#include "../flags.h"
58#include "common.h"
59#include "bashgetopt.h"
60
61#if defined (PROGRAMMABLE_COMPLETION)
62# include "../pcomplete.h"
63#endif
64
65#define ENABLED 1
66#define DISABLED 2
67#define SPECIAL 4
68
69#define AFLAG 0x01
70#define DFLAG 0x02
71#define FFLAG 0x04
72#define NFLAG 0x08
73#define PFLAG 0x10
74#define SFLAG 0x20
75
76#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
77static int dyn_load_builtin __P((WORD_LIST *, int, char *));
78#endif
79
80#if defined (HAVE_DLCLOSE)
81static int dyn_unload_builtin __P((char *));
82static void delete_builtin __P((struct builtin *));
83static int local_dlclose __P((void *));
84#endif
85
86static void list_some_builtins __P((int));
87static int enable_shell_command __P((char *, int));
88
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. */
92int
93enable_builtin (list)
94 WORD_LIST *list;
95{
96 int result, flags;
97 int opt, filter;
98#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
99 char *filename;
100#endif
101
102 result = EXECUTION_SUCCESS;
103 flags = 0;
104
105 reset_internal_getopt ();
106 while ((opt = internal_getopt (list, "adnpsf:")) != -1)
107 {
108 switch (opt)
109 {
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);
142 }
143 }
144
145 list = loptend;
146
147#if defined (RESTRICTED_SHELL)
148 /* Restricted shells cannot load new builtins. */
149 if (restricted && (flags & (FFLAG|DFLAG)))
150 {
151 sh_restricted ((char *)NULL);
152 return (EXECUTION_FAILURE);
153 }
154#endif
155
156 if (list == 0 || (flags & PFLAG))
157 {
158 filter = (flags & AFLAG) ? (ENABLED | DISABLED)
159 : (flags & NFLAG) ? DISABLED : ENABLED;
160
161 if (flags & SFLAG)
162 filter |= SPECIAL;
163
164 list_some_builtins (filter);
165 }
166#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
167 else if (flags & FFLAG)
168 {
169 filter = (flags & NFLAG) ? DISABLED : ENABLED;
170 if (flags & SFLAG)
171 filter |= SPECIAL;
172
173 result = dyn_load_builtin (list, filter, filename);
174#if defined (PROGRAMMABLE_COMPLETION)
175 set_itemlist_dirty (&it_builtins);
176#endif
177 }
178#endif
179#if defined (HAVE_DLCLOSE)
180 else if (flags & DFLAG)
181 {
182 while (list)
183 {
184 opt = dyn_unload_builtin (list->word->word);
185 if (opt == EXECUTION_FAILURE)
186 result = EXECUTION_FAILURE;
187 list = list->next;
188 }
189#if defined (PROGRAMMABLE_COMPLETION)
190 set_itemlist_dirty (&it_builtins);
191#endif
192 }
193#endif
194 else
195 {
196 while (list)
197 {
198 opt = enable_shell_command (list->word->word, flags & NFLAG);
199
200 if (opt == EXECUTION_FAILURE)
201 {
202 sh_notbuiltin (list->word->word);
203 result = EXECUTION_FAILURE;
204 }
205 list = list->next;
206 }
207 }
208 return (result);
209}
210
211/* List some builtins.
212 FILTER is a mask with two slots: ENABLED and DISABLED. */
213static void
214list_some_builtins (filter)
215 int filter;
216{
217 register int i;
218
219 for (i = 0; i < num_shell_builtins; i++)
220 {
221 if (shell_builtins[i].function == 0 || (shell_builtins[i].flags & BUILTIN_DELETED))
222 continue;
223
224 if ((filter & SPECIAL) &&
225 (shell_builtins[i].flags & SPECIAL_BUILTIN) == 0)
226 continue;
227
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);
233 }
234}
235
236/* Enable the shell command NAME. If DISABLE_P is non-zero, then
237 disable NAME instead. */
238static int
239enable_shell_command (name, disable_p)
240 char *name;
241 int disable_p;
242{
243 struct builtin *b;
244
245 b = builtin_address_internal (name, 1);
246 if (b == 0)
247 return (EXECUTION_FAILURE);
248
249 if (disable_p)
250 b->flags &= ~BUILTIN_ENABLED;
251#if defined (RESTRICTED_SHELL)
252 else if (restricted && ((b->flags & BUILTIN_ENABLED) == 0))
253 {
254 sh_restricted ((char *)NULL);
255 return (EXECUTION_FAILURE);
256 }
257#endif
258 else
259 b->flags |= BUILTIN_ENABLED;
260
261#if defined (PROGRAMMABLE_COMPLETION)
262 set_itemlist_dirty (&it_enabled);
263 set_itemlist_dirty (&it_disabled);
264#endif
265
266 return (EXECUTION_SUCCESS);
267}
268
269#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
270
271#if defined (HAVE_DLFCN_H)
272# include <dlfcn.h>
273#endif
274
275static int
276dyn_load_builtin (list, flags, filename)
277 WORD_LIST *list;
278 int flags;
279 char *filename;
280{
281 WORD_LIST *l;
282 void *handle;
283
284 int total, size, new, replaced;
285 char *struct_name, *name;
286 struct builtin **new_builtins, *b, *new_shell_builtins, *old_builtin;
287
288 if (list == 0)
289 return (EXECUTION_FAILURE);
290
291#ifndef RTLD_LAZY
292#define RTLD_LAZY 1
293#endif
294
295#if defined (_AIX)
296 handle = dlopen (filename, RTLD_NOW|RTLD_GLOBAL);
297#else
298 handle = dlopen (filename, RTLD_LAZY);
299#endif /* !_AIX */
300
301 if (handle == 0)
302 {
303 builtin_error (_("cannot open shared object %s: %s"), filename, dlerror ());
304 return (EXECUTION_FAILURE);
305 }
306
307 for (new = 0, l = list; l; l = l->next, new++)
308 ;
309 new_builtins = (struct builtin **)xmalloc (new * sizeof (struct builtin *));
310
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)
315 {
316 name = list->word->word;
317
318 size = strlen (name);
319 struct_name = (char *)xmalloc (size + 8);
320 strcpy (struct_name, name);
321 strcpy (struct_name + size, "_struct");
322
323 b = (struct builtin *)dlsym (handle, struct_name);
324 if (b == 0)
325 {
326 builtin_error (_("cannot find %s in shared object %s: %s"),
327 struct_name, filename, dlerror ());
328 free (struct_name);
329 continue;
330 }
331
332 free (struct_name);
333
334 b->flags &= ~STATIC_BUILTIN;
335 if (flags & SPECIAL)
336 b->flags |= SPECIAL_BUILTIN;
337 b->handle = handle;
338
339 if (old_builtin = builtin_address_internal (name, 1))
340 {
341 replaced++;
342 FASTCOPY ((char *)b, (char *)old_builtin, sizeof (struct builtin));
343 }
344 else
345 new_builtins[new++] = b;
346 }
347
348 if (replaced == 0 && new == 0)
349 {
350 free (new_builtins);
351 dlclose (handle);
352 return (EXECUTION_FAILURE);
353 }
354
355 if (new)
356 {
357 total = num_shell_builtins + new;
358 size = (total + 1) * sizeof (struct builtin);
359
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));
367
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;
371
372 if (shell_builtins != static_shell_builtins)
373 free (shell_builtins);
374