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 */
 | 
						|
}
 |