/* exec.c, created from exec.def. */ #line 22 "./exec.def" #line 43 "./exec.def" #include #include "../bashtypes.h" #include "posixstat.h" #include #include #if defined (HAVE_UNISTD_H) # include #endif #include "../bashansi.h" #include "../bashintl.h" #include "../shell.h" #include "../execute_cmd.h" #include "../findcmd.h" #if defined (JOB_CONTROL) # include "../jobs.h" #endif #include "../flags.h" #include "../trap.h" #if defined (HISTORY) # include "../bashhist.h" #endif #include "common.h" #include "bashgetopt.h" /* Not all systems declare ERRNO in errno.h... and some systems #define it! */ #if !defined (errno) extern int errno; #endif /* !errno */ extern int subshell_environment; extern REDIRECT *redirection_undo_list; int no_exit_on_failed_exec; /* If the user wants this to look like a login shell, then prepend a `-' onto NAME and return the new name. */ static char * mkdashname (name) char *name; { char *ret; ret = (char *)xmalloc (2 + strlen (name)); ret[0] = '-'; strcpy (ret + 1, name); return ret; } int exec_builtin (list) WORD_LIST *list; { int exit_value = EXECUTION_FAILURE; int cleanenv, login, opt; char *argv0, *command, **args, **env, *newname, *com2; cleanenv = login = 0; argv0 = (char *)NULL; reset_internal_getopt (); while ((opt = internal_getopt (list, "cla:")) != -1) { switch (opt) { case 'c': cleanenv = 1; break; case 'l': login = 1; break; case 'a': argv0 = list_optarg; break; default: builtin_usage (); return (EX_USAGE); } } list = loptend; /* First, let the redirections remain. */ dispose_redirects (redirection_undo_list); redirection_undo_list = (REDIRECT *)NULL; if (list == 0) return (EXECUTION_SUCCESS); #if defined (RESTRICTED_SHELL) if (restricted) { sh_restricted ((char *)NULL); return (EXECUTION_FAILURE); } #endif /* RESTRICTED_SHELL */ args = strvec_from_word_list (list, 1, 0, (int *)NULL); /* A command with a slash anywhere in its name is not looked up in $PATH. */ command = absolute_program (args[0]) ? args[0] : search_for_command (args[0]); if (command == 0) { sh_notfound (args[0]); exit_value = EX_NOTFOUND; /* As per Posix.2, 3.14.6 */ goto failed_exec; } com2 = full_pathname (command); if (com2) { if (command != args[0]) free (command); command = com2; } if (argv0) { free (args[0]); args[0] = login ? mkdashname (argv0) : savestring (argv0); } else if (login) { newname = mkdashname (args[0]); free (args[0]); args[0] = newname; } /* Decrement SHLVL by 1 so a new shell started here has the same value, preserving the appearance. After we do that, we need to change the exported environment to include the new value. */ if (cleanenv == 0) adjust_shell_level (-1); if (cleanenv) env = (char **)NULL; else { maybe_make_export_env (); env = export_env; } #if defined (HISTORY) if (interactive_shell && subshell_environment == 0) maybe_save_shell_history (); #endif /* HISTORY */ restore_original_signals (); #if defined (JOB_CONTROL) if (subshell_environment == 0) end_job_control (); #endif /* JOB_CONTROL */ shell_execve (command, args, env); /* We have to set this to NULL because shell_execve has called realloc() to stuff more items at the front of the array, which may have caused the memory to be freed by realloc(). We don't want to free it twice. */ args = (char **)NULL; if (cleanenv == 0) adjust_shell_level (1); if (executable_file (command) == 0) { builtin_error (_("%s: cannot execute: %s"), command, strerror (errno)); exit_value = EX_NOEXEC; /* As per Posix.2, 3.14.6 */ } else file_error (command); failed_exec: FREE (command); if (subshell_environment || (interactive == 0 && no_exit_on_failed_exec == 0)) exit_shell (exit_value); if (args) strvec_dispose (args); initialize_traps (); initialize_signals (1); #if defined (JOB_CONTROL) if (interactive_shell || job_control) restart_job_control (); #endif /* JOB_CONTROL */ return (exit_value); }