]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/enable.def
Imported from ../bash-2.05.tar.gz.
[thirdparty/bash.git] / builtins / enable.def
CommitLineData
726f6388
JA
1This file is enable.def, from which is created enable.c.
2It implements the builtin "enable" in Bash.
3
4Copyright (C) 1987, 1989, 1991 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
bb70624e 10Software Foundation; either version 2, or (at your option) any later
726f6388
JA
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
bb70624e 20Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
726f6388
JA
21
22$PRODUCES enable.c
23
24$BUILTIN enable
25$FUNCTION enable_builtin
ccc6cda3 26$SHORT_DOC enable [-pnds] [-a] [-f filename] [name ...]
726f6388
JA
27Enable and disable builtin shell commands. This allows
28you to use a disk command which has the same name as a shell
b72432fd
JA
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.
726f6388
JA
40$END
41
ccc6cda3
JA
42#include <config.h>
43
44#if defined (HAVE_UNISTD_H)
cce855bc
JA
45# ifdef _MINIX
46# include <sys/types.h>
47# endif
ccc6cda3
JA
48# include <unistd.h>
49#endif
50
51#include <stdio.h>
52#include "../bashansi.h"
726f6388
JA
53#include "../shell.h"
54#include "../builtins.h"
ccc6cda3 55#include "../flags.h"
726f6388 56#include "common.h"
ccc6cda3
JA
57#include "bashgetopt.h"
58
bb70624e
JA
59#if defined (PROGRAMMABLE_COMPLETION)
60# include "../pcomplete.h"
61#endif
62
ccc6cda3
JA
63#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
64static int dyn_load_builtin ();
65#endif
66
67#if defined (HAVE_DLCLOSE)
68static int dyn_unload_builtin ();
69#endif
726f6388
JA
70
71#define ENABLED 1
72#define DISABLED 2
ccc6cda3
JA
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
726f6388
JA
81
82static int enable_shell_command ();
83static 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. */
ccc6cda3 88int
726f6388
JA
89enable_builtin (list)
90 WORD_LIST *list;
91{
ccc6cda3
JA
92 int result, flags;
93 int opt, filter;
94#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
95 char *filename;
96#endif
726f6388 97
ccc6cda3
JA
98 result = EXECUTION_SUCCESS;
99 flags = 0;
726f6388 100
ccc6cda3
JA
101 reset_internal_getopt ();
102 while ((opt = internal_getopt (list, "adnpsf:")) != -1)
726f6388 103 {
ccc6cda3 104 switch (opt)
726f6388 105 {
ccc6cda3
JA
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);
726f6388
JA
138 }
139 }
140
ccc6cda3
JA
141 list = loptend;
142
143#if defined (RESTRICTED_SHELL)
144 /* Restricted shells cannot load new builtins. */
145 if (restricted && (flags & (FFLAG|DFLAG)))
726f6388 146 {
ccc6cda3
JA
147 builtin_error ("restricted");
148 return (EXECUTION_FAILURE);
149 }
150#endif
726f6388 151
ccc6cda3
JA
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;
726f6388
JA
159
160 list_some_builtins (filter);
161 }
ccc6cda3
JA
162#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
163 else if (flags & FFLAG)
164 {
165 filter = (flags & NFLAG) ? DISABLED : ENABLED;
166 if (flags & SFLAG)
28ef6c31 167 filter |= SPECIAL;
ccc6cda3
JA
168
169 result = dyn_load_builtin (list, filter, filename);
bb70624e
JA
170#if defined (PROGRAMMABLE_COMPLETION)
171 set_itemlist_dirty (&it_builtins);
172#endif
ccc6cda3
JA
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 }
bb70624e
JA
185#if defined (PROGRAMMABLE_COMPLETION)
186 set_itemlist_dirty (&it_builtins);
187#endif
ccc6cda3
JA
188 }
189#endif
726f6388
JA
190 else
191 {
192 while (list)
193 {
ccc6cda3 194 opt = enable_shell_command (list->word->word, flags & NFLAG);
726f6388 195
ccc6cda3 196 if (opt == EXECUTION_FAILURE)
726f6388
JA
197 {
198 builtin_error ("%s: not a shell builtin", list->word->word);
ccc6cda3 199 result = EXECUTION_FAILURE;
726f6388
JA
200 }
201 list = list->next;
202 }
203 }
ccc6cda3 204 return (result);
726f6388
JA
205}
206
207/* List some builtins.
208 FILTER is a mask with two slots: ENABLED and DISABLED. */
209static void
210list_some_builtins (filter)
211 int filter;
212{
213 register int i;
214
215 for (i = 0; i < num_shell_builtins; i++)
216 {
ccc6cda3 217 if (shell_builtins[i].function == 0 || (shell_builtins[i].flags & BUILTIN_DELETED))
726f6388
JA
218 continue;
219
ccc6cda3
JA
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);
726f6388
JA
226 else if ((filter & DISABLED) &&
227 ((shell_builtins[i].flags & BUILTIN_ENABLED) == 0))
ccc6cda3 228 printf ("enable -n %s\n", shell_builtins[i].name);
726f6388
JA
229 }
230}
231
232/* Enable the shell command NAME. If DISABLE_P is non-zero, then
233 disable NAME instead. */
234static int
235enable_shell_command (name, disable_p)
236 char *name;
237 int disable_p;
238{
ccc6cda3 239 struct builtin *b;
726f6388 240
ccc6cda3
JA
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
bb70624e
JA
250#if defined (PROGRAMMABLE_COMPLETION)
251 set_itemlist_dirty (&it_enabled);
252 set_itemlist_dirty (&it_disabled);
253#endif
254
ccc6cda3
JA
255 return (EXECUTION_SUCCESS);
256}
257
258#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
d166f048
JA
259
260#if defined (HAVE_DLFCN_H)
261# include <dlfcn.h>
262#endif
ccc6cda3
JA
263
264static int
265dyn_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)
726f6388 291 {
ccc6cda3
JA
292 builtin_error ("cannot open shared object %s: %s", filename, dlerror ());
293 return (EXECUTION_FAILURE);
294 }
726f6388 295
ccc6cda3
JA
296 for (new = 0, l = list; l; l = l->next, new++)
297 ;
298 new_builtins = (struct builtin **)xmalloc (new * sizeof (struct builtin *));
726f6388 299
ccc6cda3
JA
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;
726f6388 319 }
ccc6cda3
JA
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))
28ef6c31
JA
329 {
330 replaced++;
ccc6cda3 331 FASTCOPY ((char *)b, (char *)old_builtin, sizeof (struct builtin));
28ef6c31 332 }
ccc6cda3
JA
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);
726f6388 342 }
ccc6cda3
JA
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)
375static void
376delete_builtin (b)
377 struct builtin *b;
378{
379 int ind, size;
380 struct builtin *new_shell_builtins;
381
382 /* XXX - funky pointer arithmetic - XXX */
d166f048
JA
383#ifdef __STDC__
384 ind = b - shell_builtins;
385#else
ccc6cda3 386 ind = ((int)b - (int)shell_builtins) / sizeof (struct builtin);
d166f048 387#endif
ccc6cda3
JA
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
b72432fd
JA
409/* Tenon's MachTen has a dlclose that doesn't return a value, so we
410 finesse it with a local wrapper. */
411static int
412local_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
ccc6cda3
JA
423static int
424dyn_unload_builtin (name)
425 char *name;
426{
427 struct builtin *b;
428 void *handle;
429 int ref, i;
b72432fd 430 char *uerror;
ccc6cda3
JA
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. */
b72432fd 453 if (ref == 1 && local_dlclose (handle) != 0)
ccc6cda3
JA
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);
726f6388 463}
ccc6cda3 464#endif