Add code to get the path of the current executable, which we need to re-execute the shell.

On the GS, this uses GS/OS calls. Versions for OS X and Linux are also included.
This commit is contained in:
Stephen Heumann 2014-11-07 23:06:34 -06:00
parent 6bd3b140ea
commit bff0844d44
7 changed files with 128 additions and 8 deletions

View File

@ -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 \

View File

@ -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

View File

@ -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

View File

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

117
libbb/get.exec.path.c Normal file
View File

@ -0,0 +1,117 @@
/*
* Code to get the full path of the currently-running executable on various platforms.
*
* By Stephen Heumann
*/
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include <sys/param.h>
/* 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 <gsos.h>
#include <orca.h>
/* 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 <mach-o/dyld.h>
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

View File

@ -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! */

View File

@ -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