--- a/shell/ash.c
+++ b/shell/ash.c
@@ -7241,25 +7241,10 @@
static void
-tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
+tryexec(IF_FEATURE_SH_STANDALONE(int applet_no UNUSED_PARAM,) char *cmd, char **argv, char **envp)
{
int repeated = 0;
-#if ENABLE_FEATURE_SH_STANDALONE
- if (applet_no >= 0) {
- if (APPLET_IS_NOEXEC(applet_no)) {
- clearenv();
- while (*envp)
- putenv(*envp++);
- run_applet_no_and_exit(applet_no, argv);
- }
- /* re-exec ourselves with the new arguments */
- execve(bb_busybox_exec_path, argv, envp);
- /* If they called chroot or otherwise made the binary no longer
- * executable, fall through */
- }
-#endif
-
repeat:
#ifdef SYSV
do {
@@ -7309,14 +7294,14 @@
clearredir(/*drop:*/ 1);
envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
- if (strchr(argv[0], '/') != NULL
-#if ENABLE_FEATURE_SH_STANDALONE
- || (applet_no = find_applet_by_name(argv[0])) >= 0
-#endif
- ) {
+ if (strchr(argv[0], '/') != NULL) {
tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) argv[0], argv, envp);
e = errno;
} else {
+#if ENABLE_FEATURE_SH_STANDALONE
+ bb_execv_applet(argv[0], argv, envp);
+#endif
+
e = ENOENT;
while ((cmdname = path_advance(&path, argv[0])) != NULL) {
if (--idx < 0 && pathopt == NULL) {
--- a/libbb/execable.c
+++ b/libbb/execable.c
@@ -9,6 +9,9 @@
#include "libbb.h"
+#include <alloca.h>
+#include <stdarg.h>
+
/* check if path points to an executable file;
* return 1 if found;
* return 0 otherwise;
@@ -68,12 +71,60 @@
}
#if ENABLE_FEATURE_PREFER_APPLETS
+int FAST_FUNC bb_execv_applet(const char *name, char *const argv[], char *const envp[])
+{
+ const char **path = bb_busybox_exec_paths;
+
+ errno = ENOENT;
+
+ if (find_applet_by_name(name) < 0)
+ return -1;
+
+ for (; *path; ++path)
+ execve(*path, argv, envp);
+
+ return -1;
+}
+
/* just like the real execvp, but try to launch an applet named 'file' first
*/
int FAST_FUNC bb_execvp(const char *file, char *const argv[])
{
- return execvp(find_applet_by_name(file) >= 0 ? bb_busybox_exec_path : file,
- argv);
+ int ret = bb_execv_applet(file, argv, environ);
+ if (errno != ENOENT)
+ return ret;
+
+ return execvp(file, argv);
+}
+
+int FAST_FUNC bb_execlp(const char *file, const char *arg, ...)
+{
+#define INITIAL_ARGV_MAX 16
+ size_t argv_max = INITIAL_ARGV_MAX;
+ const char **argv = malloc(argv_max * sizeof (const char *));
+ va_list args;
+ unsigned int i = 0;
+ int ret;
+
+ va_start (args, arg);
+ while (argv[i++] != NULL) {
+ if (i == argv_max) {
+ const char **nptr;
+ argv_max *= 2;
+ nptr = realloc (argv, argv_max * sizeof (const char *));
+ if (nptr == NULL)
+ return -1;
+ argv = nptr;
+ }
+
+ argv[i] = va_arg (args, const char *);
+ }
+ va_end (args);
+
+ ret = bb_execvp(file, (char *const *)argv);
+ free(argv);
+
+ return ret;
}
#endif
--- a/libbb/messages.c
+++ b/libbb/messages.c
@@ -45,6 +45,15 @@
const char bb_path_motd_file[] ALIGN1 = "/etc/motd";
const char bb_dev_null[] ALIGN1 = "/dev/null";
const char bb_busybox_exec_path[] ALIGN1 = CONFIG_BUSYBOX_EXEC_PATH;
+const char *bb_busybox_exec_paths[] ALIGN1 = {
+#ifdef __linux__
+ "/proc/self/exe",
+#endif
+#ifdef CONFIG_BUSYBOX_EXEC_PATH
+ CONFIG_BUSYBOX_EXEC_PATH,
+#endif
+ NULL
+};
const char bb_default_login_shell[] ALIGN1 = LIBBB_DEFAULT_LOGIN_SHELL;
/* util-linux manpage says /sbin:/bin:/usr/sbin:/usr/bin,
* but I want to save a few bytes here. Check libbb.h before changing! */
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -830,11 +830,11 @@
* but it may exec busybox and call applet instead of searching PATH.
*/
#if ENABLE_FEATURE_PREFER_APPLETS
+int bb_execv_applet(const char *name, char *const argv[], char *const envp[]) FAST_FUNC;
int bb_execvp(const char *file, char *const argv[]) FAST_FUNC;
-#define BB_EXECVP(prog,cmd) bb_execvp(prog,cmd)
-#define BB_EXECLP(prog,cmd,...) \
- execlp((find_applet_by_name(prog) >= 0) ? CONFIG_BUSYBOX_EXEC_PATH : prog, \
- cmd, __VA_ARGS__)
+int bb_execlp(const char *file, const char *arg, ...) FAST_FUNC;
+#define BB_EXECVP(prog,cmd) bb_execvp(prog,cmd)
+#define BB_EXECLP(prog,cmd,...) bb_execlp(prog,cmd, __VA_ARGS__)
#else
#define BB_EXECVP(prog,cmd) execvp(prog,cmd)
#define BB_EXECLP(prog,cmd,...) execlp(prog,cmd, __VA_ARGS__)
@@ -1575,6 +1575,7 @@
extern const char bb_path_wtmp_file[];
extern const char bb_dev_null[];
extern const char bb_busybox_exec_path[];
+extern const char *bb_busybox_exec_paths[];
/* util-linux manpage says /sbin:/bin:/usr/sbin:/usr/bin,
* but I want to save a few bytes here */
extern const char bb_PATH_root_path[]; /* "PATH=/sbin:/usr/sbin:/bin:/usr/bin" */
--- a/Config.in
+++ b/Config.in
@@ -386,13 +386,10 @@
config BUSYBOX_EXEC_PATH
string "Path to BusyBox executable"
- default "/proc/self/exe"
+ default "/bin/busybox"
help
When Busybox applets need to run other busybox applets, BusyBox
- sometimes needs to exec() itself. When the /proc filesystem is
- mounted, /proc/self/exe always points to the currently running
- executable. If you haven't got /proc, set this to wherever you
- want to run BusyBox from.
+ sometimes needs to exec() itself.
# These are auto-selected by other options
--- a/coreutils/chroot.c
+++ b/coreutils/chroot.c
@@ -30,5 +30,7 @@
argv[1] = (char *) "-i";
}
- BB_EXECVP_or_die(argv);
+ execvp(argv[0], argv);
+ xfunc_error_retval = (errno == ENOENT) ? 127 : 126;
+ bb_perror_msg_and_die("can't execute '%s'", argv[0]);
}