diff --git a/Makefile b/Makefile index 416dc2e..3382ee1 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,16 @@ -libtermux-exec.so: termux-exec.c - $(CC) $(CFLAGS) -Wall -Wextra -Oz termux-exec.c -shared -fPIC -o libtermux-exec.so +UNAME_S := $(shell uname -s) + +ifeq ($(UNAME_S),Darwin) + CFLAGS += -Oz +else + CFLAGS += -Os +endif + +libtermux-exec.so: termux-exec.c termux_rewrite_executable.c + $(CC) $(CFLAGS) $^ -shared -fPIC -o $@ + +termux-rewrite-exe: termux-rewrite-exe.c termux_rewrite_executable.c + $(CC) $(CFLAGS) $^ -o $@ install: libtermux-exec.so install libtermux-exec.so $(PREFIX)/lib/libtermux-exec.so @@ -11,6 +22,6 @@ test: libtermux-exec.so @LD_PRELOAD=${CURDIR}/libtermux-exec.so ./run-tests.sh clean: - rm -f libtermux-exec.so tests/*-actual + rm -f libtermux-exec.so termux-rewrite-exe tests/*-actual .PHONY: clean install test uninstall diff --git a/termux-exec.c b/termux-exec.c index 51fcb22..3b0925a 100644 --- a/termux-exec.c +++ b/termux-exec.c @@ -1,22 +1,20 @@ +#define _GNU_SOURCE +// for RTLD_NEXT +// ref: http://comments.gmane.org/gmane.linux.man/5208 + +#include "termux_rewrite_executable.h" + #include + #include #include #include #include #include -static const char* termux_rewrite_executable(const char* filename, char* buffer, int buffer_len) -{ - strcpy(buffer, "/data/data/com.termux/files/usr/bin/"); - char* bin_match = strstr(filename, "/bin/"); - if (bin_match == filename || bin_match == (filename + 4)) { - // We have either found "/bin/" at the start of the string or at - // "/xxx/bin/". Take the path after that. - strncpy(buffer + 36, bin_match + 5, buffer_len - 37); - filename = buffer; - } - return filename; -} +#include +#include +#include int execve(const char* filename, char* const* argv, char *const envp[]) { @@ -24,7 +22,7 @@ int execve(const char* filename, char* const* argv, char *const envp[]) const char** new_argv = NULL; char filename_buffer[512]; - filename = termux_rewrite_executable(filename, filename_buffer, sizeof(filename_buffer)); + filename = termux_rewrite_executable(filename_buffer, sizeof(filename_buffer), filename); // Error out if the file is not executable: if (access(filename, X_OK) != 0) goto final; @@ -69,7 +67,8 @@ int execve(const char* filename, char* const* argv, char *const envp[]) } char interp_buf[512]; - const char* new_interpreter = termux_rewrite_executable(interpreter, interp_buf, sizeof(interp_buf)); + const char* new_interpreter = + termux_rewrite_executable(interp_buf, sizeof(interp_buf), interpreter); if (new_interpreter == interpreter) goto final; int orig_argv_count = 0; diff --git a/termux-rewrite-exe.c b/termux-rewrite-exe.c new file mode 100644 index 0000000..e2b03f0 --- /dev/null +++ b/termux-rewrite-exe.c @@ -0,0 +1,49 @@ +/* + command line test driver + + ## command ## + $ ./termux-rewrite-exe /bin/sh /usr/bin/env + ## output ## + /data/data/com.termux/files/usr/bin/sh + /data/data/com.termux/files/usr/bin/env +*/ + +#include "termux_rewrite_executable.h" + +#include +#include +#include + +int main(int argc, char** argv) { + int verbose = 0; + size_t idx = 1; + for ( ; idx < argc; ++idx ) { + if (strcmp("-v", argv[idx]) == 0) { + verbose = 1; + continue; + } + if (strcmp("--", argv[idx]) == 0) { + ++idx; + break; + } + if (strncmp("-", argv[idx], 1) == 0) { + fprintf(stderr, "unrecognized option '%s'", argv[idx]); + return 1; + } + + break; + } + const char* fmt[]={ + "%.0s%s\n", + "'%s' -> '%s'\n" + }; + + char rewritten[512]; + for( ; idx < argc; ++idx ) { + printf( + fmt[verbose], + argv[idx], + termux_rewrite_executable(rewritten, sizeof(rewritten), argv[idx])); + } + return 0; +} diff --git a/termux_rewrite_executable.c b/termux_rewrite_executable.c new file mode 100644 index 0000000..f42bcb5 --- /dev/null +++ b/termux_rewrite_executable.c @@ -0,0 +1,20 @@ +#include "termux_rewrite_executable.h" + +#include +#include + +const char* termux_rewrite_executable( + char* rewritten, size_t rewritten_size, const char* original) +{ + const char* bin_match = strstr(original, "/bin/"); + // We have either found "/bin/" at the start of the string or at + // "/xxx/bin/". Take the path after that. + if (bin_match != original && bin_match != (original + 4)) { + snprintf(rewritten, rewritten_size, "%s", original); + return rewritten; + } + + const char termux_usr_bin[]="/data/data/com.termux/files/usr/bin"; + snprintf(rewritten, rewritten_size, "%s/%s", termux_usr_bin, bin_match + 5); + return rewritten; +} diff --git a/termux_rewrite_executable.h b/termux_rewrite_executable.h new file mode 100644 index 0000000..e01dd6c --- /dev/null +++ b/termux_rewrite_executable.h @@ -0,0 +1,11 @@ +#ifndef TERMUX_REWRITE_EXECUTABLE__INCLUDED +#define TERMUX_REWRITE_EXECUTABLE__INCLUDED + +#include + +const char* termux_rewrite_executable( + char* rewritten, + size_t rewritten_size, + const char* original); + +#endif // TERMUX_REWRITE_EXECUTABLE__INCLUDED