| Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/bash/src/builtins/exec.def |
| Source code | Switch to Preprocessed file |
| Line | Source | Count | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | This file is exec.def, from which is created exec.c. | - | ||||||||||||||||||
| 2 | It implements the builtin "exec" in Bash. | - | ||||||||||||||||||
| 3 | - | |||||||||||||||||||
| 4 | Copyright (C) 1987-2015 Free Software Foundation, Inc. | - | ||||||||||||||||||
| 5 | - | |||||||||||||||||||
| 6 | This file is part of GNU Bash, the Bourne Again SHell. | - | ||||||||||||||||||
| 7 | - | |||||||||||||||||||
| 8 | Bash is free software: you can redistribute it and/or modify | - | ||||||||||||||||||
| 9 | it under the terms of the GNU General Public License as published by | - | ||||||||||||||||||
| 10 | the Free Software Foundation, either version 3 of the License, or | - | ||||||||||||||||||
| 11 | (at your option) any later version. | - | ||||||||||||||||||
| 12 | - | |||||||||||||||||||
| 13 | Bash is distributed in the hope that it will be useful, | - | ||||||||||||||||||
| 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | - | ||||||||||||||||||
| 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | - | ||||||||||||||||||
| 16 | GNU General Public License for more details. | - | ||||||||||||||||||
| 17 | - | |||||||||||||||||||
| 18 | You should have received a copy of the GNU General Public License | - | ||||||||||||||||||
| 19 | along with Bash. If not, see <http://www.gnu.org/licenses/>. | - | ||||||||||||||||||
| 20 | - | |||||||||||||||||||
| 21 | $PRODUCES exec.c | - | ||||||||||||||||||
| 22 | - | |||||||||||||||||||
| 23 | $BUILTIN exec | - | ||||||||||||||||||
| 24 | $FUNCTION exec_builtin | - | ||||||||||||||||||
| 25 | $SHORT_DOC exec [-cl] [-a name] [command [arguments ...]] [redirection ...] | - | ||||||||||||||||||
| 26 | Replace the shell with the given command. | - | ||||||||||||||||||
| 27 | - | |||||||||||||||||||
| 28 | Execute COMMAND, replacing this shell with the specified program. | - | ||||||||||||||||||
| 29 | ARGUMENTS become the arguments to COMMAND. If COMMAND is not specified, | - | ||||||||||||||||||
| 30 | any redirections take effect in the current shell. | - | ||||||||||||||||||
| 31 | - | |||||||||||||||||||
| 32 | Options: | - | ||||||||||||||||||
| 33 | -a name pass NAME as the zeroth argument to COMMAND | - | ||||||||||||||||||
| 34 | -c execute COMMAND with an empty environment | - | ||||||||||||||||||
| 35 | -l place a dash in the zeroth argument to COMMAND | - | ||||||||||||||||||
| 36 | - | |||||||||||||||||||
| 37 | If the command cannot be executed, a non-interactive shell exits, unless | - | ||||||||||||||||||
| 38 | the shell option `execfail' is set. | - | ||||||||||||||||||
| 39 | - | |||||||||||||||||||
| 40 | Exit Status: | - | ||||||||||||||||||
| 41 | Returns success unless COMMAND is not found or a redirection error occurs. | - | ||||||||||||||||||
| 42 | $END | - | ||||||||||||||||||
| 43 | - | |||||||||||||||||||
| 44 | #include <config.h> | - | ||||||||||||||||||
| 45 | - | |||||||||||||||||||
| 46 | #include "../bashtypes.h" | - | ||||||||||||||||||
| 47 | #include "posixstat.h" | - | ||||||||||||||||||
| 48 | #include <signal.h> | - | ||||||||||||||||||
| 49 | #include <errno.h> | - | ||||||||||||||||||
| 50 | - | |||||||||||||||||||
| 51 | #if defined (HAVE_UNISTD_H) | - | ||||||||||||||||||
| 52 | # include <unistd.h> | - | ||||||||||||||||||
| 53 | #endif | - | ||||||||||||||||||
| 54 | - | |||||||||||||||||||
| 55 | #include "../bashansi.h" | - | ||||||||||||||||||
| 56 | #include "../bashintl.h" | - | ||||||||||||||||||
| 57 | - | |||||||||||||||||||
| 58 | #include "../shell.h" | - | ||||||||||||||||||
| 59 | #include "../execute_cmd.h" | - | ||||||||||||||||||
| 60 | #include "../findcmd.h" | - | ||||||||||||||||||
| 61 | #if defined (JOB_CONTROL) | - | ||||||||||||||||||
| 62 | # include "../jobs.h" | - | ||||||||||||||||||
| 63 | #endif | - | ||||||||||||||||||
| 64 | #include "../flags.h" | - | ||||||||||||||||||
| 65 | #include "../trap.h" | - | ||||||||||||||||||
| 66 | #if defined (HISTORY) | - | ||||||||||||||||||
| 67 | # include "../bashhist.h" | - | ||||||||||||||||||
| 68 | #endif | - | ||||||||||||||||||
| 69 | #include "common.h" | - | ||||||||||||||||||
| 70 | #include "bashgetopt.h" | - | ||||||||||||||||||
| 71 | - | |||||||||||||||||||
| 72 | /* Not all systems declare ERRNO in errno.h... and some systems #define it! */ | - | ||||||||||||||||||
| 73 | #if !defined (errno) | - | ||||||||||||||||||
| 74 | extern int errno; | - | ||||||||||||||||||
| 75 | #endif /* !errno */ | - | ||||||||||||||||||
| 76 | - | |||||||||||||||||||
| 77 | extern REDIRECT *redirection_undo_list; | - | ||||||||||||||||||
| 78 | extern char *exec_argv0; | - | ||||||||||||||||||
| 79 | - | |||||||||||||||||||
| 80 | int no_exit_on_failed_exec; | - | ||||||||||||||||||
| 81 | - | |||||||||||||||||||
| 82 | /* If the user wants this to look like a login shell, then | - | ||||||||||||||||||
| 83 | prepend a `-' onto NAME and return the new name. */ | - | ||||||||||||||||||
| 84 | static char * | - | ||||||||||||||||||
| 85 | mkdashname (name) | - | ||||||||||||||||||
| 86 | char *name; | - | ||||||||||||||||||
| 87 | { | - | ||||||||||||||||||
| 88 | char *ret; | - | ||||||||||||||||||
| 89 | - | |||||||||||||||||||
| 90 | ret = (char *)xmalloc (2 + strlen (name)); | - | ||||||||||||||||||
| 91 | ret[0] = '-'; | - | ||||||||||||||||||
| 92 | strcpy (ret + 1, name); | - | ||||||||||||||||||
| 93 | return ret; never executed: return ret; | 0 | ||||||||||||||||||
| 94 | } | - | ||||||||||||||||||
| 95 | - | |||||||||||||||||||
| 96 | int | - | ||||||||||||||||||
| 97 | exec_builtin (list) | - | ||||||||||||||||||
| 98 | WORD_LIST *list; | - | ||||||||||||||||||
| 99 | { | - | ||||||||||||||||||
| 100 | int exit_value = EXECUTION_FAILURE; | - | ||||||||||||||||||
| 101 | int cleanenv, login, opt; | - | ||||||||||||||||||
| 102 | char *argv0, *command, **args, **env, *newname, *com2; | - | ||||||||||||||||||
| 103 | - | |||||||||||||||||||
| 104 | cleanenv = login = 0; | - | ||||||||||||||||||
| 105 | exec_argv0 = argv0 = (char *)NULL; | - | ||||||||||||||||||
| 106 | - | |||||||||||||||||||
| 107 | reset_internal_getopt (); | - | ||||||||||||||||||
| 108 | while ((opt = internal_getopt (list, "cla:")) != -1)
| 5-262 | ||||||||||||||||||
| 109 | { | - | ||||||||||||||||||
| 110 | switch (opt) | - | ||||||||||||||||||
| 111 | { | - | ||||||||||||||||||
| 112 | case 'c': never executed: case 'c': | 0 | ||||||||||||||||||
| 113 | cleanenv = 1; | - | ||||||||||||||||||
| 114 | break; never executed: break; | 0 | ||||||||||||||||||
| 115 | case 'l': never executed: case 'l': | 0 | ||||||||||||||||||
| 116 | login = 1; | - | ||||||||||||||||||
| 117 | break; never executed: break; | 0 | ||||||||||||||||||
| 118 | case 'a': never executed: case 'a': | 0 | ||||||||||||||||||
| 119 | argv0 = list_optarg; | - | ||||||||||||||||||
| 120 | break; never executed: break; | 0 | ||||||||||||||||||
| 121 | CASE_HELPOPT; never executed: return (258);never executed: case -99: | 0 | ||||||||||||||||||
| 122 | default: executed 5 times by 1 test: default:Executed by:
| 5 | ||||||||||||||||||
| 123 | builtin_usage (); | - | ||||||||||||||||||
| 124 | return (EX_USAGE); executed 5 times by 1 test: return (258);Executed by:
| 5 | ||||||||||||||||||
| 125 | } | - | ||||||||||||||||||
| 126 | } | - | ||||||||||||||||||
| 127 | list = loptend; | - | ||||||||||||||||||
| 128 | - | |||||||||||||||||||
| 129 | /* First, let the redirections remain. */ | - | ||||||||||||||||||
| 130 | dispose_redirects (redirection_undo_list); | - | ||||||||||||||||||
| 131 | redirection_undo_list = (REDIRECT *)NULL; | - | ||||||||||||||||||
| 132 | - | |||||||||||||||||||
| 133 | if (list == 0)
| 3-259 | ||||||||||||||||||
| 134 | return (EXECUTION_SUCCESS); executed 259 times by 1 test: return (0);Executed by:
| 259 | ||||||||||||||||||
| 135 | - | |||||||||||||||||||
| 136 | #if defined (RESTRICTED_SHELL) | - | ||||||||||||||||||
| 137 | if (restricted)
| 1-2 | ||||||||||||||||||
| 138 | { | - | ||||||||||||||||||
| 139 | sh_restricted ((char *)NULL); | - | ||||||||||||||||||
| 140 | return (EXECUTION_FAILURE); executed 1 time by 1 test: return (1);Executed by:
| 1 | ||||||||||||||||||
| 141 | } | - | ||||||||||||||||||
| 142 | #endif /* RESTRICTED_SHELL */ | - | ||||||||||||||||||
| 143 | - | |||||||||||||||||||
| 144 | args = strvec_from_word_list (list, 1, 0, (int *)NULL); | - | ||||||||||||||||||
| 145 | env = (char **)0; | - | ||||||||||||||||||
| 146 | - | |||||||||||||||||||
| 147 | /* A command with a slash anywhere in its name is not looked up in $PATH. */ | - | ||||||||||||||||||
| 148 | command = absolute_program (args[0]) ? args[0] : search_for_command (args[0], 1);
| 0-2 | ||||||||||||||||||
| 149 | - | |||||||||||||||||||
| 150 | if (command == 0)
| 0-2 | ||||||||||||||||||
| 151 | { | - | ||||||||||||||||||
| 152 | if (file_isdir (args[0]))
| 0 | ||||||||||||||||||
| 153 | { | - | ||||||||||||||||||
| 154 | #if defined (EISDIR) | - | ||||||||||||||||||
| 155 | builtin_error (_("%s: cannot execute: %s"), args[0], strerror (EISDIR)); | - | ||||||||||||||||||
| 156 | #else | - | ||||||||||||||||||
| 157 | builtin_error (_("%s: cannot execute: %s"), args[0], strerror (errno)); | - | ||||||||||||||||||
| 158 | #endif | - | ||||||||||||||||||
| 159 | exit_value = EX_NOEXEC; | - | ||||||||||||||||||
| 160 | } never executed: end of block | 0 | ||||||||||||||||||
| 161 | else | - | ||||||||||||||||||
| 162 | { | - | ||||||||||||||||||
| 163 | sh_notfound (args[0]); | - | ||||||||||||||||||
| 164 | exit_value = EX_NOTFOUND; /* As per Posix.2, 3.14.6 */ | - | ||||||||||||||||||
| 165 | } never executed: end of block | 0 | ||||||||||||||||||
| 166 | goto failed_exec; never executed: goto failed_exec; | 0 | ||||||||||||||||||
| 167 | } | - | ||||||||||||||||||
| 168 | - | |||||||||||||||||||
| 169 | com2 = full_pathname (command); | - | ||||||||||||||||||
| 170 | if (com2)
| 0-2 | ||||||||||||||||||
| 171 | { | - | ||||||||||||||||||
| 172 | if (command != args[0])
| 0-2 | ||||||||||||||||||
| 173 | free (command); never executed: sh_xfree((command), "./exec.def", 173); | 0 | ||||||||||||||||||
| 174 | command = com2; | - | ||||||||||||||||||
| 175 | } executed 2 times by 1 test: end of blockExecuted by:
| 2 | ||||||||||||||||||
| 176 | - | |||||||||||||||||||
| 177 | if (argv0)
| 0-2 | ||||||||||||||||||
| 178 | { | - | ||||||||||||||||||
| 179 | free (args[0]); | - | ||||||||||||||||||
| 180 | args[0] = login ? mkdashname (argv0) : savestring (argv0);
| 0 | ||||||||||||||||||
| 181 | exec_argv0 = savestring (args[0]); | - | ||||||||||||||||||
| 182 | } never executed: end of block | 0 | ||||||||||||||||||
| 183 | else if (login)
| 0-2 | ||||||||||||||||||
| 184 | { | - | ||||||||||||||||||
| 185 | newname = mkdashname (args[0]); | - | ||||||||||||||||||
| 186 | free (args[0]); | - | ||||||||||||||||||
| 187 | args[0] = newname; | - | ||||||||||||||||||
| 188 | } never executed: end of block | 0 | ||||||||||||||||||
| 189 | - | |||||||||||||||||||
| 190 | /* Decrement SHLVL by 1 so a new shell started here has the same value, | - | ||||||||||||||||||
| 191 | preserving the appearance. After we do that, we need to change the | - | ||||||||||||||||||
| 192 | exported environment to include the new value. If we've already forked | - | ||||||||||||||||||
| 193 | and are in a subshell, we don't want to decrement the shell level, | - | ||||||||||||||||||
| 194 | since we are `increasing' the level */ | - | ||||||||||||||||||
| 195 | - | |||||||||||||||||||
| 196 | if (cleanenv == 0 && (subshell_environment & SUBSHELL_PAREN) == 0)
| 0-2 | ||||||||||||||||||
| 197 | adjust_shell_level (-1); executed 1 time by 1 test: adjust_shell_level (-1);Executed by:
| 1 | ||||||||||||||||||
| 198 | - | |||||||||||||||||||
| 199 | if (cleanenv)
| 0-2 | ||||||||||||||||||
| 200 | { | - | ||||||||||||||||||
| 201 | env = strvec_create (1); | - | ||||||||||||||||||
| 202 | env[0] = (char *)0; | - | ||||||||||||||||||
| 203 | } never executed: end of block | 0 | ||||||||||||||||||
| 204 | else | - | ||||||||||||||||||
| 205 | { | - | ||||||||||||||||||
| 206 | maybe_make_export_env (); | - | ||||||||||||||||||
| 207 | env = export_env; | - | ||||||||||||||||||
| 208 | } executed 2 times by 1 test: end of blockExecuted by:
| 2 | ||||||||||||||||||
| 209 | - | |||||||||||||||||||
| 210 | #if defined (HISTORY) | - | ||||||||||||||||||
| 211 | if (interactive_shell && subshell_environment == 0)
| 0-2 | ||||||||||||||||||
| 212 | maybe_save_shell_history (); never executed: maybe_save_shell_history (); | 0 | ||||||||||||||||||
| 213 | #endif /* HISTORY */ | - | ||||||||||||||||||
| 214 | - | |||||||||||||||||||
| 215 | restore_original_signals (); | - | ||||||||||||||||||
| 216 | - | |||||||||||||||||||
| 217 | #if defined (JOB_CONTROL) | - | ||||||||||||||||||
| 218 | if (subshell_environment == 0)
| 1 | ||||||||||||||||||
| 219 | end_job_control (); executed 1 time by 1 test: end_job_control ();Executed by:
| 1 | ||||||||||||||||||
| 220 | if (interactive || job_control)
| 0-2 | ||||||||||||||||||
| 221 | default_tty_job_signals (); /* undo initialize_job_signals */ never executed: default_tty_job_signals (); | 0 | ||||||||||||||||||
| 222 | #endif /* JOB_CONTROL */ | - | ||||||||||||||||||
| 223 | - | |||||||||||||||||||
| 224 | exit_value = shell_execve (command, args, env); | - | ||||||||||||||||||
| 225 | - | |||||||||||||||||||
| 226 | /* We have to set this to NULL because shell_execve has called realloc() | - | ||||||||||||||||||
| 227 | to stuff more items at the front of the array, which may have caused | - | ||||||||||||||||||
| 228 | the memory to be freed by realloc(). We don't want to free it twice. */ | - | ||||||||||||||||||
| 229 | args = (char **)NULL; | - | ||||||||||||||||||
| 230 | if (cleanenv == 0)
| 0-2 | ||||||||||||||||||
| 231 | adjust_shell_level (1); executed 2 times by 1 test: adjust_shell_level (1);Executed by:
| 2 | ||||||||||||||||||
| 232 | - | |||||||||||||||||||
| 233 | if (exit_value == EX_NOTFOUND) /* no duplicate error message */
| 0-2 | ||||||||||||||||||
| 234 | goto failed_exec; executed 2 times by 1 test: goto failed_exec;Executed by:
| 2 | ||||||||||||||||||
| 235 | else if (executable_file (command) == 0)
| 0 | ||||||||||||||||||
| 236 | { | - | ||||||||||||||||||
| 237 | builtin_error (_("%s: cannot execute: %s"), command, strerror (errno)); | - | ||||||||||||||||||
| 238 | exit_value = EX_NOEXEC; /* As per Posix.2, 3.14.6 */ | - | ||||||||||||||||||
| 239 | } never executed: end of block | 0 | ||||||||||||||||||
| 240 | else | - | ||||||||||||||||||
| 241 | file_error (command); never executed: file_error (command); | 0 | ||||||||||||||||||
| 242 | - | |||||||||||||||||||
| 243 | failed_exec: code before this statement never executed: failed_exec: | 0 | ||||||||||||||||||
| 244 | FREE (command); executed 2 times by 1 test: sh_xfree((command), "./exec.def", 244);Executed by:
| 0-2 | ||||||||||||||||||
| 245 | - | |||||||||||||||||||
| 246 | if (subshell_environment || (interactive == 0 && no_exit_on_failed_exec == 0))
| 0-1 | ||||||||||||||||||
| 247 | exit_shell (exit_value); executed 1 time by 1 test: exit_shell (exit_value);Executed by:
| 1 | ||||||||||||||||||
| 248 | - | |||||||||||||||||||
| 249 | if (args)
| 0-1 | ||||||||||||||||||
| 250 | strvec_dispose (args); never executed: strvec_dispose (args); | 0 | ||||||||||||||||||
| 251 | - | |||||||||||||||||||
| 252 | if (env && env != export_env)
| 0-1 | ||||||||||||||||||
| 253 | strvec_dispose (env); never executed: strvec_dispose (env); | 0 | ||||||||||||||||||
| 254 | - | |||||||||||||||||||
| 255 | initialize_traps (); | - | ||||||||||||||||||
| 256 | initialize_signals (1); | - | ||||||||||||||||||
| 257 | - | |||||||||||||||||||
| 258 | #if defined (JOB_CONTROL) | - | ||||||||||||||||||
| 259 | if (interactive_shell || job_control)
| 0-1 | ||||||||||||||||||
| 260 | restart_job_control (); never executed: restart_job_control (); | 0 | ||||||||||||||||||
| 261 | #endif /* JOB_CONTROL */ | - | ||||||||||||||||||
| 262 | - | |||||||||||||||||||
| 263 | return (exit_value); executed 1 time by 1 test: return (exit_value);Executed by:
| 1 | ||||||||||||||||||
| 264 | } | - | ||||||||||||||||||
| Source code | Switch to Preprocessed file |