diff options
Diffstat (limited to 'builtins/command.def')
-rw-r--r-- | builtins/command.def | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/builtins/command.def b/builtins/command.def new file mode 100644 index 0000000..dbc1e9a --- /dev/null +++ b/builtins/command.def @@ -0,0 +1,207 @@ +This file is command.def, from which is created command.c. +It implements the builtin "command" in Bash. + +Copyright (C) 1987-2004 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 2, 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; see the file COPYING. If not, write to the Free Software +Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +$PRODUCES command.c + +$BUILTIN command +$FUNCTION command_builtin +$SHORT_DOC command [-pVv] command [arg ...] +Runs COMMAND with ARGS ignoring shell functions. If you have a shell +function called `ls', and you wish to call the command `ls', you can +say "command ls". If the -p option is given, a default value is used +for PATH that is guaranteed to find all of the standard utilities. If +the -V or -v option is given, a string is printed describing COMMAND. +The -V option produces a more verbose description. +$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 (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; + } + return (any_found ? EXECUTION_SUCCESS : EXECUTION_FAILURE); + } + +#if defined (RESTRICTED_SHELL) + if (use_standard_path && restricted) + { + sh_restricted ("-p"); + return (EXECUTION_FAILURE); + } +#endif + + begin_unwind_frame ("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. */ + 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); + FREE (standard_path); + } + +#define COMMAND_BUILTIN_FLAGS (CMD_NO_FUNCTIONS | CMD_INHIBIT_EXPANSION | CMD_COMMAND_BUILTIN) + + 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"); +} + +/* 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 */ +} |