219 lines
		
	
	
	
		
			5.9 KiB
		
	
	
	
		
			Modula-2
		
	
	
	
	
	
			
		
		
	
	
			219 lines
		
	
	
	
		
			5.9 KiB
		
	
	
	
		
			Modula-2
		
	
	
	
	
	
| This file is command.def, from which is created command.c.
 | |
| It implements the builtin "command" in Bash.
 | |
| 
 | |
| Copyright (C) 1987-2009 Free Software Foundation, Inc.
 | |
| 
 | |
| This file is part of GNU Bash, the Bourne Again SHell.
 | |
| 
 | |
| 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.
 | |
| 
 | |
| 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.
 | |
| 
 | |
| You should have received a copy of the GNU General Public License
 | |
| along with Bash.  If not, see <http://www.gnu.org/licenses/>.
 | |
| 
 | |
| $PRODUCES command.c
 | |
| 
 | |
| $BUILTIN command
 | |
| $FUNCTION command_builtin
 | |
| $SHORT_DOC command [-pVv] command [arg ...]
 | |
| Execute a simple command or display information about commands.
 | |
| 
 | |
| Runs COMMAND with ARGS suppressing  shell function lookup, or display
 | |
| information about the specified COMMANDs.  Can be used to invoke commands
 | |
| on disk when a function with the same name exists.
 | |
| 
 | |
| Options:
 | |
|   -p	use a default value for PATH that is guaranteed to find all of
 | |
| 	the standard utilities
 | |
|   -v	print a description of COMMAND similar to the `type' builtin
 | |
|   -V	print a more verbose description of each COMMAND
 | |
| 
 | |
| Exit Status:
 | |
| Returns exit status of COMMAND, or failure if COMMAND is not found.
 | |
| $END
 | |
| 
 | |
| #include <config.h>
 | |
| 
 | |
| #if defined (HAVE_UNISTD_H)
 | |
| #  ifdef _MINIX
 | |
| #    include <sys/types.h>
 | |
| #  endif
 | |
| #  include <unistd.h>
 | |
| #endif
 | |
| 
 | |
| #include "../bashansi.h"
 | |
| 
 | |
| #include "../shell.h"
 | |
| #include "../execute_cmd.h"
 | |
| #include "../flags.h"
 | |
| #include "bashgetopt.h"
 | |
| #include "common.h"
 | |
| 
 | |
| #if defined (_CS_PATH) && defined (HAVE_CONFSTR) && !HAVE_DECL_CONFSTR
 | |
| extern size_t confstr __P((int, char *, size_t));
 | |
| #endif
 | |
| 
 | |
| extern int subshell_environment;
 | |
| 
 | |
| static void restore_path __P((char *));
 | |
| static char *get_standard_path __P((void));
 | |
| 
 | |
| /* Run the commands mentioned in LIST without paying attention to shell
 | |
|    functions. */
 | |
| int
 | |
| command_builtin (list)
 | |
|      WORD_LIST *list;
 | |
| {
 | |
|   int result, verbose, use_standard_path, opt;
 | |
|   char *old_path, *standard_path;
 | |
|   COMMAND *command;
 | |
| 
 | |
|   verbose = use_standard_path = 0;
 | |
|   reset_internal_getopt ();
 | |
|   while ((opt = internal_getopt (list, "pvV")) != -1)
 | |
|     {
 | |
|       switch (opt)
 | |
| 	{
 | |
| 	case 'p':
 | |
| 	  use_standard_path = 1;
 | |
| 	  break;
 | |
| 	case 'V':
 | |
| 	  verbose = CDESC_SHORTDESC|CDESC_ABSPATH;	/* look in common.h for constants */
 | |
| 	  break;
 | |
| 	case 'v':
 | |
| 	  verbose = CDESC_REUSABLE;	/* ditto */
 | |
| 	  break;
 | |
| 	default:
 | |
| 	  builtin_usage ();
 | |
| 	  return (EX_USAGE);
 | |
| 	}
 | |
|     }
 | |
|   list = loptend;
 | |
| 
 | |
|   if (list == 0)
 | |
|     return (EXECUTION_SUCCESS);
 | |
| 
 | |
| #if defined (RESTRICTED_SHELL)
 | |
|   if (use_standard_path && restricted)
 | |
|     {
 | |
|       sh_restricted ("-p");
 | |
|       return (EXECUTION_FAILURE);
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|   begin_unwind_frame ("command_builtin");
 | |
| 
 | |
|   if (use_standard_path)
 | |
|     {      
 | |
|       old_path = get_string_value ("PATH");
 | |
|       /* If old_path is NULL, $PATH is unset.  If so, we want to make sure
 | |
| 	 it's unset after this command completes. */
 | |
|       if (old_path)
 | |
| 	old_path = savestring (old_path);
 | |
|       add_unwind_protect ((Function *)restore_path, old_path);
 | |
| 
 | |
|       standard_path = get_standard_path ();
 | |
|       bind_variable ("PATH", standard_path ? standard_path : "", 0);
 | |
|       stupidly_hack_special_variables ("PATH");
 | |
|       FREE (standard_path);
 | |
|     }
 | |
| 
 | |
|   if (verbose)
 | |
|     {
 | |
|       int found, any_found;
 | |
| 
 | |
|       for (any_found = 0; list; list = list->next)
 | |
| 	{
 | |
| 	  found = describe_command (list->word->word, verbose);
 | |
| 
 | |
| 	  if (found == 0 && verbose != CDESC_REUSABLE)
 | |
| 	    sh_notfound (list->word->word);
 | |
| 
 | |
| 	  any_found += found;
 | |
| 	}
 | |
| 
 | |
|       run_unwind_frame ("command_builtin");
 | |
|       return (any_found ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
 | |
|     }
 | |
| 
 | |
| #define COMMAND_BUILTIN_FLAGS (CMD_NO_FUNCTIONS | CMD_INHIBIT_EXPANSION | CMD_COMMAND_BUILTIN)
 | |
| 
 | |
|   /* We don't want this to be reparsed (consider command echo 'foo &'), so
 | |
|      just make a simple_command structure and call execute_command with it. */
 | |
|   command = make_bare_simple_command ();
 | |
|   command->value.Simple->words = (WORD_LIST *)copy_word_list (list);
 | |
|   command->value.Simple->redirects = (REDIRECT *)NULL;
 | |
|   command->flags |= COMMAND_BUILTIN_FLAGS;
 | |
|   command->value.Simple->flags |= COMMAND_BUILTIN_FLAGS;
 | |
| #if 0
 | |
|   /* This breaks for things like ( cd /tmp ; command z ababa ; echo next )
 | |
|      or $(command echo a ; command echo b;) or even
 | |
|      { command echo a; command echo b; } & */
 | |
|   /* If we're in a subshell, see if we can get away without forking
 | |
|      again, since we've already forked to run this builtin. */
 | |
|   if (subshell_environment)
 | |
|     {
 | |
|       command->flags |= CMD_NO_FORK;
 | |
|       command->value.Simple->flags |= CMD_NO_FORK;
 | |
|     }
 | |
| #endif
 | |
|   add_unwind_protect ((char *)dispose_command, command);
 | |
|   result = execute_command (command);
 | |
| 
 | |
|   run_unwind_frame ("command_builtin");
 | |
| 
 | |
|   return (result);
 | |
| }
 | |
| 
 | |
| /* Restore the value of the $PATH variable after replacing it when
 | |
|    executing `command -p'. */
 | |
| static void
 | |
| restore_path (var)
 | |
|      char *var;
 | |
| {
 | |
|   if (var)
 | |
|     {
 | |
|       bind_variable ("PATH", var, 0);
 | |
|       free (var);
 | |
|     }
 | |
|   else
 | |
|     unbind_variable ("PATH");
 | |
| 
 | |
|   stupidly_hack_special_variables ("PATH");
 | |
| }
 | |
| 
 | |
| /* Return a value for PATH that is guaranteed to find all of the standard
 | |
|    utilities.  This uses Posix.2 configuration variables, if present.  It
 | |
|    uses a value defined in config.h as a last resort. */
 | |
| static char *
 | |
| get_standard_path ()
 | |
| {
 | |
| #if defined (_CS_PATH) && defined (HAVE_CONFSTR)
 | |
|   char *p;
 | |
|   size_t len;
 | |
| 
 | |
|   len = (size_t)confstr (_CS_PATH, (char *)NULL, (size_t)0);
 | |
|   if (len > 0)
 | |
|     {
 | |
|       p = (char *)xmalloc (len + 2);
 | |
|       *p = '\0';
 | |
|       confstr (_CS_PATH, p, len);
 | |
|       return (p);
 | |
|     }
 | |
|   else
 | |
|     return (savestring (STANDARD_UTILS_PATH));
 | |
| #else /* !_CS_PATH || !HAVE_CONFSTR  */
 | |
| #  if defined (CS_PATH)
 | |
|   return (savestring (CS_PATH));
 | |
| #  else
 | |
|   return (savestring (STANDARD_UTILS_PATH));
 | |
| #  endif /* !CS_PATH */
 | |
| #endif /* !_CS_PATH || !HAVE_CONFSTR */
 | |
| }
 | 
