source: vendor/bash/3.1/builtins/enable.def

Last change on this file was 3228, checked in by bird, 18 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
375 shell_builtins = new_shell_builtins;
376 num_shell_builtins = total;
377 initialize_shell_builtins ();
378 }
379
380 free (new_builtins);
381 return (EXECUTION_SUCCESS);
382}
383#endif
384
385#if defined (HAVE_DLCLOSE)
386static void
387delete_builtin (b)
388 struct builtin *b;
389{
390 int ind, size;
391 struct builtin *new_shell_builtins;
392
393 /* XXX - funky pointer arithmetic - XXX */
394#ifdef __STDC__
395 ind = b - shell_builtins;
396#else
397 ind = ((int)b - (int)shell_builtins) / sizeof (struct builtin);
398#endif
399 size = num_shell_builtins * sizeof (struct builtin);
400 new_shell_builtins = (struct builtin *)xmalloc (size);
401
402 /* Copy shell_builtins[0]...shell_builtins[ind - 1] to new_shell_builtins */
403 if (ind)
404 FASTCOPY ((char *)shell_builtins, (char *)new_shell_builtins,
405 ind * sizeof (struct builtin));
406 /* Copy shell_builtins[ind+1]...shell_builtins[num_shell_builtins to
407 new_shell_builtins, starting at ind. */
408 FASTCOPY ((char *)(&shell_builtins[ind+1]),
409 (char *)(&new_shell_builtins[ind]),
410 (num_shell_builtins - ind) * sizeof (struct builtin));
411
412 if (shell_builtins != static_shell_builtins)
413 free (shell_builtins);
414
415 /* The result is still sorted. */
416 num_shell_builtins--;
417 shell_builtins = new_shell_builtins;
418}
419
420/* Tenon's MachTen has a dlclose that doesn't return a value, so we
421 finesse it with a local wrapper. */
422static int
423local_dlclose (handle)
424 void *handle;
425{
426#if !defined (__MACHTEN__)
427 return (dlclose (handle));
428#else /* __MACHTEN__ */
429 dlclose (handle);
430 return ((dlerror () != NULL) ? -1 : 0);
431#endif /* __MACHTEN__ */
432}
433
434static int
435dyn_unload_builtin (name)
436 char *name;
437{
438 struct builtin *b;
439 void *handle;
440 int ref, i;
441
442 b = builtin_address_internal (name, 1);
443 if (b == 0)
444 {
445 sh_notbuiltin (name);
446 return (EXECUTION_FAILURE);
447 }
448 if (b->flags & STATIC_BUILTIN)
449 {
450 builtin_error (_("%s: not dynamically loaded"), name);
451 return (EXECUTION_FAILURE);
452 }
453
454 handle = (void *)b->handle;
455 for (ref = i = 0; i < num_shell_builtins; i++)
456 {
457 if (shell_builtins[i].handle == b->handle)
458 ref++;
459 }
460
461 /* Don't remove the shared object unless the reference count of builtins
462 using it drops to zero. */
463 if (ref == 1 && local_dlclose (handle) != 0)
464 {
465 builtin_error (_("%s: cannot delete: %s"), name, dlerror ());
466 return (EXECUTION_FAILURE);
467 }
468
469 /* Now remove this entry from the builtin table and reinitialize. */
470 delete_builtin (b);
471
472 return (EXECUTION_SUCCESS);
473}
474#endif
Note: See TracBrowser for help on using the repository browser.