| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | This file is enable.def, from which is created enable.c. | 
					
						
							|  |  |  | It implements the builtin "enable" in Bash. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  | Copyright (C) 1987-2016 Free Software Foundation, Inc. | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | This file is part of GNU Bash, the Bourne Again SHell. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | Bash is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | it under the terms of the GNU General Public License as published by | 
					
						
							|  |  |  | the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | (at your option) any later version. | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | Bash is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  | GNU General Public License for more details. | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  | along with Bash.  If not, see <http://www.gnu.org/licenses/>. | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | $PRODUCES enable.c | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | $BUILTIN enable | 
					
						
							|  |  |  | $FUNCTION enable_builtin | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | $SHORT_DOC enable [-a] [-dnps] [-f filename] [name ...] | 
					
						
							|  |  |  | Enable and disable shell builtins. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Enables and disables builtin shell commands.  Disabling allows you to | 
					
						
							|  |  |  | execute a disk command which has the same name as a shell builtin | 
					
						
							|  |  |  | without using a full pathname. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Options: | 
					
						
							|  |  |  |   -a	print a list of builtins showing whether or not each is enabled | 
					
						
							|  |  |  |   -n	disable each NAME or display a list of disabled builtins | 
					
						
							|  |  |  |   -p	print the list of builtins in a reusable format | 
					
						
							|  |  |  |   -s	print only the names of Posix `special' builtins | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Options controlling dynamic loading: | 
					
						
							|  |  |  |   -f	Load builtin NAME from shared object FILENAME | 
					
						
							|  |  |  |   -d	Remove a builtin loaded with -f | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Without options, each NAME is enabled. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | To use the `test' found in $PATH instead of the shell builtin | 
					
						
							|  |  |  | version, type `enable -n test'. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Exit Status: | 
					
						
							|  |  |  | Returns success unless NAME is not a shell builtin or an error occurs. | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | $END | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #include <config.h> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (HAVE_UNISTD_H) | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | #  ifdef _MINIX | 
					
						
							|  |  |  | #    include <sys/types.h> | 
					
						
							|  |  |  | #  endif | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #  include <unistd.h> | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <stdio.h> | 
					
						
							|  |  |  | #include "../bashansi.h" | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | #include "../bashintl.h" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #include "../shell.h" | 
					
						
							|  |  |  | #include "../builtins.h" | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #include "../flags.h" | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #include "common.h" | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #include "bashgetopt.h" | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  | #include "findcmd.h" | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #if defined (PROGRAMMABLE_COMPLETION) | 
					
						
							|  |  |  | #  include "../pcomplete.h" | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #define ENABLED  1 | 
					
						
							|  |  |  | #define DISABLED 2 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #define SPECIAL  4 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define AFLAG	0x01 | 
					
						
							|  |  |  | #define DFLAG	0x02 | 
					
						
							|  |  |  | #define FFLAG	0x04 | 
					
						
							|  |  |  | #define NFLAG	0x08 | 
					
						
							|  |  |  | #define PFLAG	0x10 | 
					
						
							|  |  |  | #define SFLAG	0x20 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM) | 
					
						
							|  |  |  | static int dyn_load_builtin __P((WORD_LIST *, int, char *)); | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (HAVE_DLCLOSE) | 
					
						
							|  |  |  | static int dyn_unload_builtin __P((char *)); | 
					
						
							|  |  |  | static void delete_builtin __P((struct builtin *)); | 
					
						
							|  |  |  | static int local_dlclose __P((void *)); | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  | #define STRUCT_SUFFIX	"_struct" | 
					
						
							|  |  |  | /* for now */ | 
					
						
							|  |  |  | #define LOAD_SUFFIX	"_builtin_load" | 
					
						
							|  |  |  | #define UNLOAD_SUFFIX	"_builtin_unload" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | static void list_some_builtins __P((int)); | 
					
						
							|  |  |  | static int enable_shell_command __P((char *, int)); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Enable/disable shell commands present in LIST.  If list is not specified, | 
					
						
							|  |  |  |    then print out a list of shell commands showing which are enabled and | 
					
						
							|  |  |  |    which are disabled. */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | int | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | enable_builtin (list) | 
					
						
							|  |  |  |      WORD_LIST *list; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   int result, flags; | 
					
						
							|  |  |  |   int opt, filter; | 
					
						
							|  |  |  | #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM) | 
					
						
							|  |  |  |   char *filename; | 
					
						
							|  |  |  | #endif | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   result = EXECUTION_SUCCESS; | 
					
						
							|  |  |  |   flags = 0; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   reset_internal_getopt (); | 
					
						
							|  |  |  |   while ((opt = internal_getopt (list, "adnpsf:")) != -1) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       switch (opt) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	case 'a': | 
					
						
							|  |  |  | 	  flags |= AFLAG; | 
					
						
							|  |  |  | 	  break; | 
					
						
							|  |  |  | 	case 'n': | 
					
						
							|  |  |  | 	  flags |= NFLAG; | 
					
						
							|  |  |  | 	  break; | 
					
						
							|  |  |  | 	case 'p': | 
					
						
							|  |  |  | 	  flags |= PFLAG; | 
					
						
							|  |  |  | 	  break; | 
					
						
							|  |  |  | 	case 's': | 
					
						
							|  |  |  | 	  flags |= SFLAG; | 
					
						
							|  |  |  | 	  break; | 
					
						
							|  |  |  | 	case 'f': | 
					
						
							|  |  |  | #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM) | 
					
						
							|  |  |  | 	  flags |= FFLAG; | 
					
						
							|  |  |  | 	  filename = list_optarg; | 
					
						
							|  |  |  | 	  break; | 
					
						
							|  |  |  | #else | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	  builtin_error (_("dynamic loading not available")); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	  return (EX_USAGE); | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | #if defined (HAVE_DLCLOSE) | 
					
						
							|  |  |  | 	case 'd': | 
					
						
							|  |  |  | 	  flags |= DFLAG; | 
					
						
							|  |  |  | 	  break; | 
					
						
							|  |  |  | #else | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	  builtin_error (_("dynamic loading not available")); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	  return (EX_USAGE); | 
					
						
							|  |  |  | #endif /* HAVE_DLCLOSE */ | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  | 	CASE_HELPOPT; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	default: | 
					
						
							|  |  |  | 	  builtin_usage (); | 
					
						
							|  |  |  | 	  return (EX_USAGE); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   list = loptend; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (RESTRICTED_SHELL) | 
					
						
							|  |  |  |   /* Restricted shells cannot load new builtins. */ | 
					
						
							|  |  |  |   if (restricted && (flags & (FFLAG|DFLAG))) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       sh_restricted ((char *)NULL); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       return (EXECUTION_FAILURE); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #endif | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   if (list == 0 || (flags & PFLAG)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       filter = (flags & AFLAG) ? (ENABLED | DISABLED) | 
					
						
							|  |  |  | 			       : (flags & NFLAG) ? DISABLED : ENABLED; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (flags & SFLAG) | 
					
						
							|  |  |  | 	filter |= SPECIAL; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       list_some_builtins (filter); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM) | 
					
						
							|  |  |  |   else if (flags & FFLAG) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       filter = (flags & NFLAG) ? DISABLED : ENABLED; | 
					
						
							|  |  |  |       if (flags & SFLAG) | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	filter |= SPECIAL; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       result = dyn_load_builtin (list, filter, filename); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #if defined (PROGRAMMABLE_COMPLETION) | 
					
						
							|  |  |  |       set_itemlist_dirty (&it_builtins); | 
					
						
							|  |  |  | #endif | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | #if defined (HAVE_DLCLOSE) | 
					
						
							|  |  |  |   else if (flags & DFLAG) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       while (list) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  opt = dyn_unload_builtin (list->word->word); | 
					
						
							|  |  |  | 	  if (opt == EXECUTION_FAILURE) | 
					
						
							|  |  |  | 	    result = EXECUTION_FAILURE; | 
					
						
							|  |  |  | 	  list = list->next; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #if defined (PROGRAMMABLE_COMPLETION) | 
					
						
							|  |  |  |       set_itemlist_dirty (&it_builtins); | 
					
						
							|  |  |  | #endif | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | #endif | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       while (list) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	  opt = enable_shell_command (list->word->word, flags & NFLAG); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	  if (opt == EXECUTION_FAILURE) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	    { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	      sh_notbuiltin (list->word->word); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	      result = EXECUTION_FAILURE; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	    } | 
					
						
							|  |  |  | 	  list = list->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   return (result); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* List some builtins. | 
					
						
							|  |  |  |    FILTER is a mask with two slots: ENABLED and DISABLED. */ | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | list_some_builtins (filter) | 
					
						
							|  |  |  |      int filter; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   register int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (i = 0; i < num_shell_builtins; i++) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       if (shell_builtins[i].function == 0 || (shell_builtins[i].flags & BUILTIN_DELETED)) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       if ((filter & SPECIAL) && | 
					
						
							|  |  |  | 	  (shell_builtins[i].flags & SPECIAL_BUILTIN) == 0) | 
					
						
							|  |  |  | 	continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if ((filter & ENABLED) && (shell_builtins[i].flags & BUILTIN_ENABLED)) | 
					
						
							|  |  |  | 	printf ("enable %s\n", shell_builtins[i].name); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       else if ((filter & DISABLED) && | 
					
						
							|  |  |  | 	       ((shell_builtins[i].flags & BUILTIN_ENABLED) == 0)) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	printf ("enable -n %s\n", shell_builtins[i].name); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Enable the shell command NAME.  If DISABLE_P is non-zero, then | 
					
						
							|  |  |  |    disable NAME instead. */ | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | enable_shell_command (name, disable_p) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  |      int disable_p; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   struct builtin *b; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   b = builtin_address_internal (name, 1); | 
					
						
							|  |  |  |   if (b == 0) | 
					
						
							|  |  |  |     return (EXECUTION_FAILURE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (disable_p) | 
					
						
							|  |  |  |     b->flags &= ~BUILTIN_ENABLED; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #if defined (RESTRICTED_SHELL) | 
					
						
							|  |  |  |   else if (restricted && ((b->flags & BUILTIN_ENABLED) == 0)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       sh_restricted ((char *)NULL); | 
					
						
							|  |  |  |       return (EXECUTION_FAILURE); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #endif | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   else | 
					
						
							|  |  |  |     b->flags |= BUILTIN_ENABLED; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #if defined (PROGRAMMABLE_COMPLETION) | 
					
						
							|  |  |  |   set_itemlist_dirty (&it_enabled); | 
					
						
							|  |  |  |   set_itemlist_dirty (&it_disabled); | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   return (EXECUTION_SUCCESS); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM) | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if defined (HAVE_DLFCN_H) | 
					
						
							|  |  |  | #  include <dlfcn.h> | 
					
						
							|  |  |  | #endif | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | dyn_load_builtin (list, flags, filename) | 
					
						
							|  |  |  |      WORD_LIST *list; | 
					
						
							|  |  |  |      int flags; | 
					
						
							|  |  |  |      char *filename; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   WORD_LIST *l; | 
					
						
							|  |  |  |   void *handle; | 
					
						
							|  |  |  |    | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  |   int total, size, new, replaced, r; | 
					
						
							|  |  |  |   char *struct_name, *name, *funcname; | 
					
						
							|  |  |  |   sh_load_func_t *loadfunc; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   struct builtin **new_builtins, *b, *new_shell_builtins, *old_builtin; | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  |   char *loadables_path, *load_path; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (list == 0) | 
					
						
							|  |  |  |     return (EXECUTION_FAILURE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef RTLD_LAZY | 
					
						
							|  |  |  | #define RTLD_LAZY 1 | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  |   handle = 0; | 
					
						
							|  |  |  |   if (absolute_program (filename) == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       loadables_path = get_string_value ("BASH_LOADABLES_PATH"); | 
					
						
							|  |  |  |       if (loadables_path) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  load_path = find_in_path (filename, loadables_path, FS_NODIRS|FS_EXEC_PREFERRED); | 
					
						
							|  |  |  | 	  if (load_path) | 
					
						
							|  |  |  | 	    { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #if defined (_AIX) | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  | 	      handle = dlopen (load_path, RTLD_NOW|RTLD_GLOBAL); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #else | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  | 	      handle = dlopen (load_path, RTLD_LAZY); | 
					
						
							|  |  |  | #endif /* !_AIX */ | 
					
						
							|  |  |  | 	      free (load_path); | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Fall back to current directory for now */ | 
					
						
							|  |  |  |   if (handle == 0) | 
					
						
							|  |  |  | #if defined (_AIX) | 
					
						
							|  |  |  |     handle = dlopen (filename, RTLD_NOW|RTLD_GLOBAL); | 
					
						
							|  |  |  | #else | 
					
						
							|  |  |  |     handle = dlopen (filename, RTLD_LAZY); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #endif /* !_AIX */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (handle == 0) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  |       name = printable_filename (filename, 0); | 
					
						
							|  |  |  |       builtin_error (_("cannot open shared object %s: %s"), name, dlerror ()); | 
					
						
							|  |  |  |       if (name != filename) | 
					
						
							|  |  |  | 	free (name); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       return (EXECUTION_FAILURE); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   for (new = 0, l = list; l; l = l->next, new++) | 
					
						
							|  |  |  |     ; | 
					
						
							|  |  |  |   new_builtins = (struct builtin **)xmalloc (new * sizeof (struct builtin *)); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   /* For each new builtin in the shared object, find it and its describing | 
					
						
							|  |  |  |      structure.  If this is overwriting an existing builtin, do so, otherwise | 
					
						
							|  |  |  |      save the loaded struct for creating the new list of builtins. */ | 
					
						
							|  |  |  |   for (replaced = new = 0; list; list = list->next) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       name = list->word->word; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       size = strlen (name); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |       struct_name = (char *)xmalloc (size + 8); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       strcpy (struct_name, name); | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  |       strcpy (struct_name + size, STRUCT_SUFFIX); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       b = (struct builtin *)dlsym (handle, struct_name); | 
					
						
							|  |  |  |       if (b == 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  | 	  name = printable_filename (filename, 0); | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	  builtin_error (_("cannot find %s in shared object %s: %s"), | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  | 			  struct_name, name, dlerror ()); | 
					
						
							|  |  |  | 	  if (name != filename) | 
					
						
							|  |  |  | 	    free (name); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	  free (struct_name); | 
					
						
							|  |  |  | 	  continue; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  |       funcname = xrealloc (struct_name, size + sizeof (LOAD_SUFFIX) + 1); | 
					
						
							|  |  |  |       strcpy (funcname, name); | 
					
						
							|  |  |  |       strcpy (funcname + size, LOAD_SUFFIX); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       loadfunc = (sh_load_func_t *)dlsym (handle, funcname); | 
					
						
							|  |  |  |       if (loadfunc) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  r = (*loadfunc) (name); | 
					
						
							|  |  |  | 	  if (r == 0) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      builtin_error (_("load function for %s returns failure (%d): not loaded"), name, r); | 
					
						
							|  |  |  | 	      free (funcname); | 
					
						
							|  |  |  | 	      continue; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       free (funcname); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       b->flags &= ~STATIC_BUILTIN; | 
					
						
							|  |  |  |       if (flags & SPECIAL) | 
					
						
							|  |  |  | 	b->flags |= SPECIAL_BUILTIN; | 
					
						
							|  |  |  |       b->handle = handle; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (old_builtin = builtin_address_internal (name, 1)) | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	  replaced++; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	  FASTCOPY ((char *)b, (char *)old_builtin, sizeof (struct builtin)); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       else | 
					
						
							|  |  |  | 	  new_builtins[new++] = b; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (replaced == 0 && new == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       free (new_builtins); | 
					
						
							|  |  |  |       dlclose (handle); | 
					
						
							|  |  |  |       return (EXECUTION_FAILURE); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (new) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       total = num_shell_builtins + new; | 
					
						
							|  |  |  |       size = (total + 1) * sizeof (struct builtin); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       new_shell_builtins = (struct builtin *)xmalloc (size); | 
					
						
							|  |  |  |       FASTCOPY ((char *)shell_builtins, (char *)new_shell_builtins, | 
					
						
							|  |  |  | 		num_shell_builtins * sizeof (struct builtin)); | 
					
						
							|  |  |  |       for (replaced = 0; replaced < new; replaced++) | 
					
						
							|  |  |  | 	FASTCOPY ((char *)new_builtins[replaced], | 
					
						
							|  |  |  | 		  (char *)&new_shell_builtins[num_shell_builtins + replaced], | 
					
						
							|  |  |  | 		  sizeof (struct builtin)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       new_shell_builtins[total].name = (char *)0; | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |       new_shell_builtins[total].function = (sh_builtin_func_t *)0; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       new_shell_builtins[total].flags = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (shell_builtins != static_shell_builtins) | 
					
						
							|  |  |  | 	free (shell_builtins); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       shell_builtins = new_shell_builtins; | 
					
						
							|  |  |  |       num_shell_builtins = total; | 
					
						
							|  |  |  |       initialize_shell_builtins (); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   free (new_builtins); | 
					
						
							|  |  |  |   return (EXECUTION_SUCCESS); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (HAVE_DLCLOSE) | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | delete_builtin (b) | 
					
						
							|  |  |  |      struct builtin *b; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   int ind, size; | 
					
						
							|  |  |  |   struct builtin *new_shell_builtins; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* XXX - funky pointer arithmetic - XXX */ | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | #ifdef __STDC__ | 
					
						
							|  |  |  |   ind = b - shell_builtins; | 
					
						
							|  |  |  | #else | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   ind = ((int)b - (int)shell_builtins) / sizeof (struct builtin); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | #endif | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   size = num_shell_builtins * sizeof (struct builtin); | 
					
						
							|  |  |  |   new_shell_builtins = (struct builtin *)xmalloc (size); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Copy shell_builtins[0]...shell_builtins[ind - 1] to new_shell_builtins */ | 
					
						
							|  |  |  |   if (ind) | 
					
						
							|  |  |  |     FASTCOPY ((char *)shell_builtins, (char *)new_shell_builtins, | 
					
						
							|  |  |  | 	      ind * sizeof (struct builtin)); | 
					
						
							|  |  |  |   /* Copy shell_builtins[ind+1]...shell_builtins[num_shell_builtins to | 
					
						
							|  |  |  |      new_shell_builtins, starting at ind. */ | 
					
						
							|  |  |  |   FASTCOPY ((char *)(&shell_builtins[ind+1]), | 
					
						
							|  |  |  |   	    (char *)(&new_shell_builtins[ind]), | 
					
						
							|  |  |  |   	    (num_shell_builtins - ind) * sizeof (struct builtin)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (shell_builtins != static_shell_builtins) | 
					
						
							|  |  |  |     free (shell_builtins); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* The result is still sorted. */ | 
					
						
							|  |  |  |   num_shell_builtins--; | 
					
						
							|  |  |  |   shell_builtins = new_shell_builtins; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  | /* Tenon's MachTen has a dlclose that doesn't return a value, so we | 
					
						
							|  |  |  |    finesse it with a local wrapper. */ | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | local_dlclose (handle) | 
					
						
							|  |  |  |      void *handle; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if !defined (__MACHTEN__) | 
					
						
							|  |  |  |   return (dlclose (handle)); | 
					
						
							|  |  |  | #else /* __MACHTEN__ */ | 
					
						
							|  |  |  |   dlclose (handle); | 
					
						
							|  |  |  |   return ((dlerror () != NULL) ? -1 : 0);     | 
					
						
							|  |  |  | #endif /* __MACHTEN__ */ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | dyn_unload_builtin (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   struct builtin *b; | 
					
						
							|  |  |  |   void *handle; | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  |   char *funcname; | 
					
						
							|  |  |  |   sh_unload_func_t *unloadfunc; | 
					
						
							|  |  |  |   int ref, i, size; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   b = builtin_address_internal (name, 1); | 
					
						
							|  |  |  |   if (b == 0) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       sh_notbuiltin (name); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       return (EXECUTION_FAILURE); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   if (b->flags & STATIC_BUILTIN) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       builtin_error (_("%s: not dynamically loaded"), name); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       return (EXECUTION_FAILURE); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   handle = (void *)b->handle; | 
					
						
							|  |  |  |   for (ref = i = 0; i < num_shell_builtins; i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (shell_builtins[i].handle == b->handle) | 
					
						
							|  |  |  | 	ref++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  |   /* Call any unload function */ | 
					
						
							|  |  |  |   size = strlen (name); | 
					
						
							|  |  |  |   funcname = xmalloc (size + sizeof (UNLOAD_SUFFIX) + 1); | 
					
						
							|  |  |  |   strcpy (funcname, name); | 
					
						
							|  |  |  |   strcpy (funcname + size, UNLOAD_SUFFIX); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   unloadfunc = (sh_unload_func_t *)dlsym (handle, funcname); | 
					
						
							|  |  |  |   if (unloadfunc) | 
					
						
							|  |  |  |     (*unloadfunc) (name);	/* void function */ | 
					
						
							|  |  |  |   free (funcname); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   /* Don't remove the shared object unless the reference count of builtins | 
					
						
							|  |  |  |      using it drops to zero. */ | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |   if (ref == 1 && local_dlclose (handle) != 0) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       builtin_error (_("%s: cannot delete: %s"), name, dlerror ()); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       return (EXECUTION_FAILURE); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Now remove this entry from the builtin table and reinitialize. */ | 
					
						
							|  |  |  |   delete_builtin (b); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (EXECUTION_SUCCESS); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #endif |