diff --git a/Makefile b/Makefile index 239c46b09..c10bec838 100644 --- a/Makefile +++ b/Makefile @@ -35,7 +35,8 @@ LIBBB_B_SRC = \ libbb/escape.seq.c \ libbb/messages.c \ libbb/bb.basename.c \ - libbb/mempcpy.c + libbb/mempcpy.c \ + libbb/get.exec.path.c LIBBB_C_SRC = \ libbb/perror.msg.c \ diff --git a/Makefile.gmake b/Makefile.gmake index 92195e2ff..2a0f3f761 100644 --- a/Makefile.gmake +++ b/Makefile.gmake @@ -50,7 +50,8 @@ SRCS = \ libbb/bb.basename.c \ libbb/mempcpy.c \ libbb/vfork.and.run.c \ - libbb/poll.c + libbb/poll.c \ + libbb/get.exec.path.c OBJS = $(SRCS:.c=.o) INCLUDES = -I include -I shell -I libbb diff --git a/include/autoconf.h b/include/autoconf.h index 89af5baba..be1a05f69 100644 --- a/include/autoconf.h +++ b/include/autoconf.h @@ -228,8 +228,6 @@ #define ENABLE_FEATURE_PREFER_APPLETS 0 #define IF_FEATURE_PREFER_APPLETS(x) #define IF_NOT_FEATURE_PREFER_APPLETS(x) x -#define CONFIG_BUSYBOX_EXEC_PATH "/proc/self/exe" -#define ENABLE_BUSYBOX_EXEC_PATH 1 #ifdef MAKE_SUID # define IF_BUSYBOX_EXEC_PATH(x) x "CONFIG_BUSYBOX_EXEC_PATH" #else diff --git a/include/libbb.h b/include/libbb.h index dadf543bb..1e75e470d 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1520,7 +1520,6 @@ extern const char bb_path_wtmp_file[] ALIGN1; #else # define bb_dev_null ".null" #endif -extern const char bb_busybox_exec_path[] ALIGN1; extern const int const_int_0; extern const int const_int_1; @@ -1639,6 +1638,8 @@ static ALWAYS_INLINE unsigned char bb_ascii_tolower(unsigned char a) */ int signal_parent_to_resume(void); +/* Get path of current executable */ +char *get_exec_path(void); /* Simple unit-testing framework */ diff --git a/libbb/get.exec.path.c b/libbb/get.exec.path.c new file mode 100644 index 000000000..a6bed3a04 --- /dev/null +++ b/libbb/get.exec.path.c @@ -0,0 +1,117 @@ +/* + * Code to get the full path of the currently-running executable on various platforms. + * + * By Stephen Heumann + */ + +#include +#include +#include +#include + +/* This should return a pointer that can be deallocated with free() when done, + * or NULL on failure. */ +char *get_exec_path(void); + + +#ifdef __appleiigs__ + +#include +#include + +/* Prefix 1 is set to the directory containing the executable at launch. + * We append the result of a GetName call to this to get the full pathname. + */ +char *get_exec_path(void) { + PrefixRecGS prefixRec; + GetNameRecGS nameRec; + ResultBuf255 *prefix, *name; + char *result; + + prefix = malloc(sizeof(ResultBuf255)); + if (prefix == NULL) + return NULL; + prefixRec.pCount = 2; + prefixRec.prefixNum = 1; /* Info for prefix 1 */ + prefixRec.buffer.getPrefix = prefix; + prefix->bufSize = sizeof(ResultBuf255); + + GetPrefixGS(&prefixRec); + if (toolerror()) { + free(prefix); + return NULL; + } + + name = malloc(sizeof(ResultBuf255)); + if (name == NULL) { + free(prefix); + return NULL; + } + nameRec.pCount = 1; + nameRec.dataBuffer = name; + name->bufSize = sizeof(ResultBuf255); + + GetNameGS(&nameRec); + if (toolerror()) { + free(prefix); + free(name); + return NULL; + } + + result = malloc(prefix->bufString.length + name->bufString.length + 1); + if (result == NULL) { + free(prefix); + free(name); + return NULL; + } + + memcpy(result, prefix->bufString.text, prefix->bufString.length); + memcpy(result + prefix->bufString.length, name->bufString.text, name->bufString.length); + result[prefix->bufString.length + name->bufString.length] = 0; + free(prefix); + free(name); + return result; +} + +#elif defined(__APPLE__) && defined(__MACH__) + +#include + +char *get_exec_path(void) { + char *buf; + uint32_t bufsize = 256; + int result; + + while (1) { + buf = malloc(bufsize); + if (buf == NULL) + return NULL; + + result = _NSGetExecutablePath(buf, &bufsize); + if (result == 0) + return buf; + + free(buf); + } +} + +#elif defined(__linux__) + +char *get_exec_path(void) { + return strdup("/proc/self/exe"); +} + +#elif defined(BSD) + +char *get_exec_path(void) { + /* Works on some BSDs but not all -- hope for the best! */ + return strdup("/proc/curproc/exe"); +} + +#else + +char *get_exec_path(void) { + return NULL; +} + +#endif \ No newline at end of file diff --git a/libbb/messages.c b/libbb/messages.c index 60ea049c8..0bdf53180 100644 --- a/libbb/messages.c +++ b/libbb/messages.c @@ -35,7 +35,6 @@ const char bb_msg_standard_output[] ALIGN1 = "standard output"; const char bb_hexdigits_upcase[] ALIGN1 = "0123456789ABCDEF"; -const char bb_busybox_exec_path[] ALIGN1 = CONFIG_BUSYBOX_EXEC_PATH; 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! */ diff --git a/shell/hush.c b/shell/hush.c index 219f2feb8..4b4c33298 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -859,6 +859,8 @@ static struct globals G; struct lineedit_statics; struct lineedit_statics *lineedit_ptr_to_statics; +static char *hush_exec_path; + /* Function prototypes for builtins */ static int builtin_cd(char **argv) FAST_FUNC; @@ -5874,7 +5876,7 @@ static void re_execute_shell(char ***to_free, const char *s, if (SPECIAL_JOBSTOP_SIGS != 0) switch_off_special_sigs(G.special_sig_mask & SPECIAL_JOBSTOP_SIGS); signal_parent_to_resume(); - execve(bb_busybox_exec_path, argv, pp); + execve(hush_exec_path, argv, pp); /* Fallback. Useful for init=/bin/hush usage etc */ if (argv[0][0] == '/') execve(argv[0], argv, pp); @@ -6738,7 +6740,7 @@ static NOINLINE void pseudo_exec_argv(nommu_save_t *nommu_save, /* Don't propagate SIG_IGN to the child */ if (SPECIAL_JOBSTOP_SIGS != 0) switch_off_special_sigs(G.special_sig_mask & SPECIAL_JOBSTOP_SIGS); - execv(bb_busybox_exec_path, argv); + execv(hush_exec_path, argv); /* If they called chroot or otherwise made the binary no longer * executable, fall through */ } @@ -8031,6 +8033,7 @@ int hush_main(int argc, char **argv) struct variable *shell_ver; INIT_G(); + hush_exec_path = get_exec_path(); if (EXIT_SUCCESS != 0) /* if EXIT_SUCCESS == 0, it is already done */ G.last_exitcode = EXIT_SUCCESS; #if ENABLE_HUSH_FAST