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