From b5b2bc77b7c992817fa1e5de482f1fef07f87ae8 Mon Sep 17 00:00:00 2001 From: perezcimamarcoantonio-dotcom Date: Mon, 1 Jun 2026 20:04:22 -0500 Subject: [PATCH] Delete rish directory rish/README.md --- rish/.gitignore | 1 - rish/README.md | 47 --- rish/build.gradle | 45 --- rish/src/main/AndroidManifest.xml | 2 - rish/src/main/cpp/CMakeLists.txt | 33 -- rish/src/main/cpp/logging.h | 31 -- rish/src/main/cpp/main.cpp | 17 -- rish/src/main/cpp/pts.cpp | 110 ------- rish/src/main/cpp/pts.h | 19 -- rish/src/main/cpp/rikka_rish_RishHost.cpp | 289 ------------------ rish/src/main/cpp/rikka_rish_RishHost.h | 8 - rish/src/main/cpp/rikka_rish_RishTerminal.cpp | 140 --------- rish/src/main/cpp/rikka_rish_RishTerminal.h | 8 - .../main/java/rikka/rish/FileDescriptors.java | 56 ---- rish/src/main/java/rikka/rish/Rish.java | 42 --- rish/src/main/java/rikka/rish/RishConfig.java | 59 ---- .../main/java/rikka/rish/RishConstants.java | 8 - rish/src/main/java/rikka/rish/RishHost.java | 125 -------- .../src/main/java/rikka/rish/RishService.java | 139 --------- .../main/java/rikka/rish/RishTerminal.java | 166 ---------- 20 files changed, 1345 deletions(-) delete mode 100644 rish/.gitignore delete mode 100644 rish/README.md delete mode 100644 rish/build.gradle delete mode 100644 rish/src/main/AndroidManifest.xml delete mode 100644 rish/src/main/cpp/CMakeLists.txt delete mode 100644 rish/src/main/cpp/logging.h delete mode 100644 rish/src/main/cpp/main.cpp delete mode 100644 rish/src/main/cpp/pts.cpp delete mode 100644 rish/src/main/cpp/pts.h delete mode 100644 rish/src/main/cpp/rikka_rish_RishHost.cpp delete mode 100644 rish/src/main/cpp/rikka_rish_RishHost.h delete mode 100644 rish/src/main/cpp/rikka_rish_RishTerminal.cpp delete mode 100644 rish/src/main/cpp/rikka_rish_RishTerminal.h delete mode 100644 rish/src/main/java/rikka/rish/FileDescriptors.java delete mode 100644 rish/src/main/java/rikka/rish/Rish.java delete mode 100644 rish/src/main/java/rikka/rish/RishConfig.java delete mode 100644 rish/src/main/java/rikka/rish/RishConstants.java delete mode 100644 rish/src/main/java/rikka/rish/RishHost.java delete mode 100644 rish/src/main/java/rikka/rish/RishService.java delete mode 100644 rish/src/main/java/rikka/rish/RishTerminal.java diff --git a/rish/.gitignore b/rish/.gitignore deleted file mode 100644 index 42afabf..0000000 --- a/rish/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/rish/README.md b/rish/README.md deleted file mode 100644 index d790b03..0000000 --- a/rish/README.md +++ /dev/null @@ -1,47 +0,0 @@ -# RISH - -Rish is an Interactive SHell for android - -## Description - -`rish` is an Android program for interacting with a shell that runs on a high-privileged daemon process. - -Currently, Shizuku and Sui are two available backends. - -## Usage - -First of all, follow the guide from Shizuku or Sui to create the files of `rish`. - -The remain is very simple, you only need to replace `sh` with `rish` in the command you want to run, `rish` will pass arguments directly to the remote shell. - -Here is an example. - -``` -rish -c 'ls' -``` - -This is what will be executed at remote: - -``` -/system/bin/sh -c 'ls' -``` - -If you want to use other shells rather than `/system/bin/sh`, use `rish exec /path/to/other/shell`. - -## Options - -Since `rish` passes arguments directly to the remote, `rish` uses environment variable for options. - -### RISH_PRESERVE_ENV - -| Value | Description | -|-------|----------------------------------------------------------------------| -| `0` | Do not change environment variables of the remote process | -| `1` | Replace the environment variables of the remote process with local's | - -Termux app set `PATH` and `LD_PRELOAD` to Termux's internal path. -Adb (Shizuku can run under adb) does not have sufficient permissions to access such places, making users can even not using commands like `cd`. - -If the backend runs under adb, `RISH_PRESERVE_ENV` will be treated as `0` when not set. - -If the backend runs under root, `RISH_PRESERVE_ENV` will be treated as `1` when not set. \ No newline at end of file diff --git a/rish/build.gradle b/rish/build.gradle deleted file mode 100644 index e3084eb..0000000 --- a/rish/build.gradle +++ /dev/null @@ -1,45 +0,0 @@ -plugins { - id('com.android.library') -} - -android { - namespace 'rikka.rish' - defaultConfig { - externalNativeBuild { - cmake { - arguments '-DANDROID_STL=none' - } - } - } - buildFeatures { - prefab true - } - buildTypes { - release { - minifyEnabled false - } - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_21 - targetCompatibility JavaVersion.VERSION_21 - } - externalNativeBuild { - cmake { - path 'src/main/cpp/CMakeLists.txt' - version "3.31.0+" - } - } -} - -dependencies { - implementation project(':api') - - implementation 'androidx.annotation:annotation:1.3.0' - implementation 'org.lsposed.libcxx:libcxx:27.0.12077973' -} - -ext { - publishLibrary = false - POM_NAME = "RISH" - POM_DESCRIPTION = "RISH" -} diff --git a/rish/src/main/AndroidManifest.xml b/rish/src/main/AndroidManifest.xml deleted file mode 100644 index 8072ee0..0000000 --- a/rish/src/main/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/rish/src/main/cpp/CMakeLists.txt b/rish/src/main/cpp/CMakeLists.txt deleted file mode 100644 index f015c8d..0000000 --- a/rish/src/main/cpp/CMakeLists.txt +++ /dev/null @@ -1,33 +0,0 @@ -cmake_minimum_required(VERSION 3.31) - -project("rish") - -set(CMAKE_CXX_STANDARD 17) - -add_compile_options(-Werror=format -fdata-sections -ffunction-sections -fno-exceptions -fno-rtti -fno-threadsafe-statics) - -if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug") - message("Builing Release...") - - add_compile_options(-Os -flto -fvisibility=hidden -fvisibility-inlines-hidden) - add_link_options(-flto -Wl,--exclude-libs,ALL -Wl,--gc-sections -Wl,--strip-all) -else () - message("Builing Debug...") - - add_definitions(-DDEBUG) -endif () - -find_package(cxx REQUIRED CONFIG) - -add_library(rish SHARED - main.cpp - pts.cpp - rikka_rish_RishTerminal.cpp - rikka_rish_RishHost.cpp) - -target_link_libraries(rish log cxx::cxx) - -if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug") - add_custom_command(TARGET rish POST_BUILD - COMMAND ${CMAKE_STRIP} --remove-section=.comment "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/librish.so") -endif () diff --git a/rish/src/main/cpp/logging.h b/rish/src/main/cpp/logging.h deleted file mode 100644 index ef1a7a3..0000000 --- a/rish/src/main/cpp/logging.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef _LOGGING_H -#define _LOGGING_H - -#include -#include -#include - -#ifndef LOG_TAG -#define LOG_TAG "RISH" -#endif - -#ifndef NO_LOG -#ifndef NO_DEBUG_LOG -#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) -#else -#define LOGD(...) -#endif -#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__) -#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) -#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__) -#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) -#define PLOGE(fmt, args...) LOGE(fmt " failed with %d: %s", ##args, errno, strerror(errno)) -#else -#define LOGD(...) -#define LOGV(...) -#define LOGI(...) -#define LOGW(...) -#define LOGE(...) -#define PLOGE(fmt, args...) -#endif -#endif // _LOGGING_H diff --git a/rish/src/main/cpp/main.cpp b/rish/src/main/cpp/main.cpp deleted file mode 100644 index 6ba06b7..0000000 --- a/rish/src/main/cpp/main.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include -#include "rikka_rish_RishTerminal.h" -#include "rikka_rish_RishHost.h" - -JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { - JNIEnv *env = nullptr; - - if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) - return -1; - - if (rikka_rish_RishHost_registerNatives(env) != JNI_OK - || rikka_rish_RishTerminal_registerNatives(env) != JNI_OK) { - return JNI_ERR; - } - - return JNI_VERSION_1_6; -} diff --git a/rish/src/main/cpp/pts.cpp b/rish/src/main/cpp/pts.cpp deleted file mode 100644 index 2122bec..0000000 --- a/rish/src/main/cpp/pts.cpp +++ /dev/null @@ -1,110 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "logging.h" - -int make_tty_raw(int fd, termios &old_termios) { - struct termios termios{}; - - if (tcgetattr(fd, &termios) < 0) { - PLOGE("tcgetattr"); - return -1; - } - - old_termios = termios; - - cfmakeraw(&termios); - - if (tcsetattr(fd, TCSANOW, &termios) < 0) { - PLOGE("tcsetattr"); - return -1; - } - return 0; -} - -int restore_fd(int fd, const termios &old_termios) { - if (tcsetattr(fd, TCSANOW, &old_termios) < 0) { - PLOGE("tcsetattr"); - return -1; - } - return 0; -} - -static int write_full(int fd, const void *buf, size_t count) { - while (count > 0) { - ssize_t size = write(fd, buf, count < SSIZE_MAX ? count : SSIZE_MAX); - if (size <= 0) { - if (errno == EINTR) - continue; - else - return -1; - } - buf = (const void *) ((uintptr_t) buf + size); - count -= size; - } - return 0; -} - -struct transfer_thread_data { - int in; - int out; - bool close_in; - bool close_out; - std::function function; -}; - -void transfer(int in, int out, bool close_in, bool close_out, const std::function &function) { - char buf[8192]; - int len; - while ((len = TEMP_FAILURE_RETRY(read(in, buf, 8192))) > 0) { - if (write_full(out, buf, len) == -1) { - //PLOGE("write"); - break; - } - } - //PLOGE("read"); - - if (close_in) close(in); - if (close_out) close(out); - if (function) function(); -} - -static void *transfer_thread(void *_data) { - auto data = (transfer_thread_data *) _data; - transfer(data->in, data->out, data->close_in, data->close_out, data->function); - delete data; - return nullptr; -} - -void transfer_async(int in, int out, const std::function &function, bool close_in, bool close_out) { - pthread_t pthread; - auto *data = new transfer_thread_data{in, out, close_in, close_out, function}; - pthread_create(&pthread, nullptr, transfer_thread, data); -} - -int open_ptmx() { - int fd = open("/dev/ptmx", O_RDWR); - if (fd == -1) { - return -1; - } - - if (grantpt(fd) == -1) { - PLOGE("grantpt"); - close(fd); - return -1; - } - - if (unlockpt(fd) == -1) { - PLOGE("unlockpt"); - close(fd); - return -1; - } - - return fd; -} diff --git a/rish/src/main/cpp/pts.h b/rish/src/main/cpp/pts.h deleted file mode 100644 index e295f37..0000000 --- a/rish/src/main/cpp/pts.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef PTS_H -#define PTS_H - -#include - -#define ATTY_IN (1 << 0) -#define ATTY_OUT (1 << 1) -#define ATTY_ERR (1 << 2) -#define ATTY_ALL (ATTY_IN | ATTY_OUT | ATTY_ERR) - -int make_tty_raw(int fd, termios &old_termios); - -int restore_fd(int fd, const termios &old_termios); - -void transfer_async(int in, int out, const std::function &function = nullptr, bool close_in = true, bool close_out = true); - -int open_ptmx(); - -#endif //PTS_H diff --git a/rish/src/main/cpp/rikka_rish_RishHost.cpp b/rish/src/main/cpp/rikka_rish_RishHost.cpp deleted file mode 100644 index e742fcc..0000000 --- a/rish/src/main/cpp/rikka_rish_RishHost.cpp +++ /dev/null @@ -1,289 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include "logging.h" -#include "pts.h" - -static int setWindowSize(int ptmx, jlong size) { - static_assert(sizeof(jlong) == sizeof(winsize)); - winsize w = *((winsize *) &size); - - LOGD("setWindowSize %d %d %d %d", w.ws_row, w.ws_col, w.ws_xpixel, w.ws_ypixel); - - if (ioctl(ptmx, TIOCSWINSZ, &w) == -1) { - PLOGE("ioctl TIOCGWINSZ"); - return -1; - } - return 0; -} - -// libcore/ojluni/src/main/native/UNIXProcess_md.c - -static void *xmalloc(JNIEnv *env, size_t size) { - void *p = malloc(size); - if (p == nullptr) - env->ThrowNew(env->FindClass("java/lang/OutOfMemoryError"), nullptr); - else - memset(p, 0, size); - return p; -} - -#define NEW(type, n) ((type *) xmalloc(env, (n) * sizeof(type))) - -static const char *getBytes(JNIEnv *env, jbyteArray arr) { - return arr == nullptr ? nullptr : (const char *) env->GetByteArrayElements(arr, nullptr); -} - -static void releaseBytes(JNIEnv *env, jbyteArray arr, const char *parr) { - if (parr != nullptr) - env->ReleaseByteArrayElements(arr, (jbyte *) parr, JNI_ABORT); -} - -static void initVectorFromBlock(const char **vector, const char *block, int count) { - int i; - const char *p; - for (i = 0, p = block; i < count; i++) { - /* Invariant: p always points to the start of a C string. */ - vector[i] = p; - while (*(p++)); - } - vector[count] = nullptr; -} - -static jintArray RishHost_startHost( - JNIEnv *env, jclass clazz, - jbyteArray argBlock, jint argc, - jbyteArray envBlock, jint envc, - jbyteArray dirBlock, - jbyte tty, - jint stdin_read, jint stdout_write, jint stderr_write) { - - bool in_tty = tty & ATTY_IN; - bool out_tty = tty & ATTY_OUT; - bool err_tty = tty & ATTY_ERR; - - int ptmx = -1; - if (tty) { - ptmx = open_ptmx(); - if (ptmx == -1) { - env->ThrowNew(env->FindClass("java/lang/IllegalStateException"), "Unable to open ptmx"); - return nullptr; - } - LOGD("ptmx %d", ptmx); - } - - int stdin_pipe[2]{-1}, stdout_pipe[2]{-1}, stderr_pipe[2]{-1}; - - LOGD("istty stdin %d stdout %d stderr %d", (tty & ATTY_IN) ? 1 : 0, (tty & ATTY_OUT) ? 1 : 0, (tty & ATTY_ERR) ? 1 : 0); - - if (!in_tty) { - pipe2(stdin_pipe, 0); - } - if (!out_tty) { - pipe2(stdout_pipe, 0); - } - if (!err_tty) { - pipe2(stderr_pipe, 0); - } - - const char *pargBlock = getBytes(env, argBlock); - const char **argv = NEW(const char *, argc + 2); - argv[0] = "/system/bin/sh"; - initVectorFromBlock(argv + 1, pargBlock, argc); - - for (int i = 0; i < argc + 2; ++i) { - LOGD("arg%d=%s", i, argv[i]); - } - - const char **envv = nullptr; - const char *penvBlock = nullptr; - if (envc > 0) { - penvBlock = getBytes(env, envBlock); - envv = NEW(const char *, envc + 1); - - initVectorFromBlock(envv, penvBlock, envc); - } - - const char *pdir = nullptr; - if (dirBlock) { - pdir = getBytes(env, dirBlock); - } - - auto pid = fork(); - if (pid == -1) { - releaseBytes(env, argBlock, pargBlock); - releaseBytes(env, envBlock, penvBlock); - releaseBytes(env, dirBlock, pdir); - - env->ThrowNew(env->FindClass("java/lang/IllegalStateException"), "Unable to fork"); - return nullptr; - } - - if (pid > 0) { - releaseBytes(env, argBlock, pargBlock); - releaseBytes(env, envBlock, penvBlock); - releaseBytes(env, dirBlock, pdir); - - auto called = std::make_shared(false); - auto func = [pid, called]() { - if (called->exchange(true)) { - return; - } - - LOGW("client dead, kill forked process"); - kill(pid, SIGKILL); - }; - - if (in_tty) { - transfer_async(stdin_read, ptmx/*, func*/); - } else { - transfer_async(stdin_read, stdin_pipe[1]/*, func*/); - close(stdin_pipe[0]); - } - - if (out_tty) { - transfer_async(ptmx, stdout_write, func); - } else { - transfer_async(stdout_pipe[0], stdout_write, func); - close(stdout_pipe[1]); - } - - if (!err_tty) { - transfer_async(stderr_pipe[0], stderr_write/*, func*/); - close(stderr_pipe[1]); - } - - auto result = env->NewIntArray(2); - env->SetIntArrayRegion(result, 0, 1, &pid); - env->SetIntArrayRegion(result, 1, 1, &ptmx); - return result; - } else { - if (setsid() < 0) { - PLOGE("setsid"); - exit(1); - } - - if (pdir) { - LOGD("attempt to chdir %s", pdir); - - if (access(pdir, X_OK) == 0) { - if (chdir(pdir) == -1) { - PLOGE("chdir %s", pdir); - } else { - LOGD("chdir %s", pdir); - } - } else { - PLOGE("access %s", pdir); - } - } - - int pts = -1; - if (tty) { - char pts_slave[PATH_MAX]{0}; - if (ptsname_r(ptmx, pts_slave, PATH_MAX - 1) == -1) { - PLOGE("ptsname_r"); - exit(1); - } - - if ((pts = open(pts_slave, O_RDWR)) == -1) { - PLOGE("open %s", pts_slave); - } - LOGD("pts %d", pts); - } else { - LOGD("no need pts"); - } - - if (in_tty) { - dup2(pts, STDIN_FILENO); - LOGD("pts -> in"); - } else { - dup2(stdin_pipe[0], STDIN_FILENO); - close(stdin_pipe[1]); - LOGD("pipe -> in"); - } - - if (out_tty) { - dup2(pts, STDOUT_FILENO); - LOGD("pts -> out"); - } else { - dup2(stdout_pipe[1], STDOUT_FILENO); - close(stdout_pipe[0]); - LOGD("pipe -> out"); - } - - if (err_tty) { - dup2(pts, STDERR_FILENO); - LOGD("pts -> err"); - } else { - dup2(stderr_pipe[1], STDERR_FILENO); - close(stderr_pipe[0]); - LOGD("pipe -> err"); - } - - LOGD("istty stdin %d stdout %d stderr %d", isatty(STDIN_FILENO), isatty(STDOUT_FILENO), isatty(STDERR_FILENO)); - - if (pts != -1) { - close(pts); - } - - if (envv) { - if (execvpe("/system/bin/sh", (char *const *) argv, (char *const *) envv) == -1) { - PLOGE("execv"); - exit(1); - } - } else { - if (execvp("/system/bin/sh", (char *const *) argv) == -1) { - PLOGE("execv"); - exit(1); - } - } - exit(0); - } -} - -static void RishHost_setWindowSize(JNIEnv *env, jclass clazz, jint ptmx, jlong size) { - setWindowSize(ptmx, size); -} - -static jint RishHost_waitFor(JNIEnv *env, jclass clazz, jint pid) { - if (pid < 0) - return -1; - - int status; - int w; - do { - w = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0)); - if (w == -1) { - if (errno == ECHILD) { - return 0; - } - PLOGE("waitpid"); - return -1; - } - - if (WIFEXITED(status)) { - LOGD("exited with %d", WEXITSTATUS(status)); - return WEXITSTATUS(status); - } else if (WIFSIGNALED(status)) { - LOGD("killed by signal %d", WTERMSIG(status)); - return 0; - } - } while (!WIFEXITED(status) && !WIFSIGNALED(status)); - - return -1; -} - -int rikka_rish_RishHost_registerNatives(JNIEnv *env) { - auto clazz = env->FindClass("rikka/rish/RishHost"); - JNINativeMethod methods[] = { - {"start", "([BI[BI[BBIII)[I", (void *) RishHost_startHost}, - {"setWindowSize", "(IJ)V", (void *) RishHost_setWindowSize}, - {"waitFor", "(I)I", (void *) RishHost_waitFor}, - }; - return env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0])); -} diff --git a/rish/src/main/cpp/rikka_rish_RishHost.h b/rish/src/main/cpp/rikka_rish_RishHost.h deleted file mode 100644 index 6bbccc4..0000000 --- a/rish/src/main/cpp/rikka_rish_RishHost.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef RIKKA_RISH_RISHHOST_H -#define RIKKA_RISH_RISHHOST_H - -#include - -int rikka_rish_RishHost_registerNatives(JNIEnv *env); - -#endif //RIKKA_RISH_RISHHost_H diff --git a/rish/src/main/cpp/rikka_rish_RishTerminal.cpp b/rish/src/main/cpp/rikka_rish_RishTerminal.cpp deleted file mode 100644 index 217f907..0000000 --- a/rish/src/main/cpp/rikka_rish_RishTerminal.cpp +++ /dev/null @@ -1,140 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include "logging.h" -#include "pts.h" - -static pthread_mutex_t mutex, winch_mutex; -static struct termios old_stdin{}; -static int tty_in_raw = 0; - -static int64_t getWindowSize(int fd) { - static_assert(sizeof(jlong) == sizeof(winsize)); - jlong screen_size; - - if (ioctl(fd, TIOCGWINSZ, &screen_size) == -1) { - PLOGE("ioctl TIOCGWINSZ"); - return 0; - } - - return screen_size; -} - -static jbyte RishTerminal_prepare(JNIEnv *env, jclass clazz) { - jbyte atty = 0; - if (isatty(STDIN_FILENO)) atty |= ATTY_IN; - if (isatty(STDOUT_FILENO)) atty |= ATTY_OUT; - if (isatty(STDERR_FILENO)) atty |= ATTY_ERR; - - LOGD("istty stdin %d stdout %d stderr %d", (atty & ATTY_IN) ? 1 : 0, (atty & ATTY_OUT) ? 1 : 0, - (atty & ATTY_ERR) ? 1 : 0); - - if (atty & ATTY_OUT) { - sigset_t winch; - sigemptyset(&winch); - sigaddset(&winch, SIGWINCH); - pthread_sigmask(SIG_BLOCK, &winch, nullptr); - } - - return atty; -} - -static jint RishTerminal_start( - JNIEnv *env, jclass clazz, jbyte tty, - jint stdin_pipe, jint stdout_pipe, jint stderr_pipe) { - - int tty_fd; - bool in_tty = tty & ATTY_IN; - bool out_tty = tty & ATTY_OUT; - bool err_tty = tty & ATTY_ERR; - if (in_tty) { - tty_fd = STDIN_FILENO; - } else if (out_tty) { - tty_fd = STDOUT_FILENO; - } else if (err_tty) { - tty_fd = STDERR_FILENO; - } else { - tty_fd = -1; - } - - if (tty == ATTY_ALL) { - if (make_tty_raw(tty_fd, old_stdin) == 0) { - tty_in_raw = 1; - } - } - - if (pthread_mutex_lock(&mutex) != 0) { - PLOGE("pthread_mutex_lock"); - } - - auto called = std::make_shared(false); - auto func = [=]() { - if (called->exchange(true)) { - return; - } - - LOGI("remote exit"); - - if (tty_in_raw) { - if (restore_fd(tty_fd, old_stdin) == 0) { - tty_in_raw = 0; - } - } - - if (pthread_mutex_unlock(&mutex) != 0) { - PLOGE("pthread_mutex_unlock"); - } - }; - - transfer_async(STDIN_FILENO, stdin_pipe/*, func*/); - transfer_async(stdout_pipe, STDOUT_FILENO, func); - if (!err_tty) { - transfer_async(stderr_pipe, STDERR_FILENO/*, func*/); - } - - auto sigwinch_handler = [](int sig) { - if (pthread_mutex_unlock(&winch_mutex) != 0) { - PLOGE("pthread_mutex_unlock"); - } - }; - - signal(SIGWINCH, sigwinch_handler); - - return tty_fd; -} - -static jlong RishTerminal_waitForWindowSizeChange(JNIEnv *env, jclass clazz, jint fd) { - if (pthread_mutex_lock(&winch_mutex) != 0) { - PLOGE("pthread_mutex_lock"); - } - - return (jlong) getWindowSize(fd); -} - -static void RishTerminal_waitForProcessExit(JNIEnv *env, jclass clazz) { - if (pthread_mutex_lock(&mutex) != 0) { - PLOGE("pthread_mutex_lock"); - } - - if (pthread_mutex_unlock(&mutex) != 0) { - PLOGE("pthread_mutex_unlock"); - } -} - -int rikka_rish_RishTerminal_registerNatives(JNIEnv *env) { - pthread_mutex_init(&mutex, nullptr); - pthread_mutex_init(&winch_mutex, nullptr); - - auto clazz = env->FindClass("rikka/rish/RishTerminal"); - JNINativeMethod methods[] = { - {"prepare", "()B", (void *) RishTerminal_prepare}, - {"start", "(BIII)I", (void *) RishTerminal_start}, - {"waitForWindowSizeChange", "(I)J", (void *) RishTerminal_waitForWindowSizeChange}, - {"waitForProcessExit", "()V", (void *) RishTerminal_waitForProcessExit}, - }; - return env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0])); -} diff --git a/rish/src/main/cpp/rikka_rish_RishTerminal.h b/rish/src/main/cpp/rikka_rish_RishTerminal.h deleted file mode 100644 index 4aa1676..0000000 --- a/rish/src/main/cpp/rikka_rish_RishTerminal.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef RIKKA_RISH_RISHTERMINAL_H -#define RIKKA_RISH_RISHTERMINAL_H - -#include - -int rikka_rish_RishTerminal_registerNatives(JNIEnv *env); - -#endif //RIKKA_RISH_RISH_H diff --git a/rish/src/main/java/rikka/rish/FileDescriptors.java b/rish/src/main/java/rikka/rish/FileDescriptors.java deleted file mode 100644 index 7f17609..0000000 --- a/rish/src/main/java/rikka/rish/FileDescriptors.java +++ /dev/null @@ -1,56 +0,0 @@ -package rikka.rish; - -import android.annotation.SuppressLint; -import android.system.ErrnoException; -import android.system.Os; - -import java.io.FileDescriptor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -@SuppressLint("DiscouragedPrivateApi") -@SuppressWarnings("JavaReflectionMemberAccess") -class FileDescriptors { - - private static Method getInt; - private static Method setInt; - - static { - try { - getInt = FileDescriptor.class.getDeclaredMethod("getInt$"); - getInt.setAccessible(true); - setInt = FileDescriptor.class.getDeclaredMethod("setInt$", int.class); - setInt.setAccessible(true); - } catch (ReflectiveOperationException ignored) { - } - } - - public static FileDescriptor fromFd(int fd) { - FileDescriptor fileDescriptor = new FileDescriptor(); - try { - setInt.invoke(fileDescriptor, fd); - } catch (IllegalAccessException | InvocationTargetException ignored) { - } - return fileDescriptor; - } - - public static int getFd(FileDescriptor fileDescriptor) { - try { - //noinspection ConstantConditions - return (int) getInt.invoke(fileDescriptor); - } catch (IllegalAccessException | InvocationTargetException ignored) { - return -1; - } - } - - public static void closeSilently(FileDescriptor fileDescriptor) { - if (fileDescriptor == null) { - return; - } - - try { - Os.close(fileDescriptor); - } catch (ErrnoException ignored) { - } - } -} diff --git a/rish/src/main/java/rikka/rish/Rish.java b/rish/src/main/java/rikka/rish/Rish.java deleted file mode 100644 index edd7612..0000000 --- a/rish/src/main/java/rikka/rish/Rish.java +++ /dev/null @@ -1,42 +0,0 @@ -package rikka.rish; - -import android.util.Log; - -import java.util.Arrays; - -public class Rish { - - private static final String TAG = "RISH"; - - public void requestPermission(Runnable onGrantedRunnable) { - - } - - private void startShell(String[] args, boolean permissionGranted) { - if (!permissionGranted) { - requestPermission(() -> startShell(args, true)); - return; - } - - startShell(args); - } - - private void startShell(String[] args) { - try { - RishTerminal terminal = new RishTerminal(args); - terminal.start(); - int exitCode = terminal.waitFor(); - System.exit(exitCode); - } catch (Throwable e) { - System.err.println(e.getMessage()); - System.err.flush(); - System.exit(1); - //abort(e.getMessage()); - } - } - - public void start(String[] args) { - Log.d(TAG, "args: " + Arrays.toString(args)); - startShell(args, false); - } -} diff --git a/rish/src/main/java/rikka/rish/RishConfig.java b/rish/src/main/java/rikka/rish/RishConfig.java deleted file mode 100644 index 91d90ce..0000000 --- a/rish/src/main/java/rikka/rish/RishConfig.java +++ /dev/null @@ -1,59 +0,0 @@ -package rikka.rish; - -import android.annotation.SuppressLint; -import android.os.IBinder; -import android.util.Log; - -public class RishConfig { - - private static final String TAG = "RISHConfig"; - - static final int TRANSACTION_createHost = 0; - static final int TRANSACTION_setWindowSize = 1; - static final int TRANSACTION_getExitCode = 2; - - private static IBinder binder; - private static String interfaceToken; - private static int transactionCodeStart; - private static String libraryPath; - - static IBinder getBinder() { - return binder; - } - - static String getInterfaceToken() { - return interfaceToken; - } - - static int getTransactionCode(int code) { - return transactionCodeStart + code; - } - - public static void setLibraryPath(String path) { - libraryPath = path; - } - - @SuppressLint("UnsafeDynamicallyLoadedCode") - private static void loadLibrary() { - if (libraryPath == null) { - System.loadLibrary("rish"); - } else { - System.load(libraryPath + "/librish.so"); - } - } - - public static void init(String interfaceToken, int transactionCodeStart) { - Log.d(TAG, "init (server) " + interfaceToken + " " + transactionCodeStart); - RishConfig.interfaceToken = interfaceToken; - RishConfig.transactionCodeStart = transactionCodeStart; - loadLibrary(); - } - - public static void init(IBinder binder, String interfaceToken, int transactionCodeStart) { - Log.d(TAG, "init (client) " + binder + " " + interfaceToken + " " + transactionCodeStart); - RishConfig.binder = binder; - RishConfig.interfaceToken = interfaceToken; - RishConfig.transactionCodeStart = transactionCodeStart; - loadLibrary(); - } -} diff --git a/rish/src/main/java/rikka/rish/RishConstants.java b/rish/src/main/java/rikka/rish/RishConstants.java deleted file mode 100644 index 5c1657b..0000000 --- a/rish/src/main/java/rikka/rish/RishConstants.java +++ /dev/null @@ -1,8 +0,0 @@ -package rikka.rish; - -class RishConstants { - - public static final int ATTY_IN = (1); - public static final int ATTY_OUT = (1 << 1); - public static final int ATTY_ERR = (1 << 2); -} diff --git a/rish/src/main/java/rikka/rish/RishHost.java b/rish/src/main/java/rikka/rish/RishHost.java deleted file mode 100644 index 4577a78..0000000 --- a/rish/src/main/java/rikka/rish/RishHost.java +++ /dev/null @@ -1,125 +0,0 @@ -package rikka.rish; - -import android.os.ParcelFileDescriptor; -import android.util.Log; - -public class RishHost { - - private static final String TAG = "RishHost"; - - // libcore/ojluni/src/main/java/java/lang/ProcessImpl.java - - private static byte[] createCBytesForStringArray(String[] array) { - if (array == null) { - return null; - } - - byte[][] bytes = new byte[array.length][]; - int count = bytes.length; // For added NUL bytes - for (int i = 0; i < bytes.length; i++) { - bytes[i] = array[i].getBytes(); - count += bytes[i].length; - } - byte[] block = new byte[count]; - int i = 0; - for (byte[] arg : bytes) { - System.arraycopy(arg, 0, block, i, arg.length); - i += arg.length + 1; - // No need to write NUL bytes explicitly - } - return block; - } - - private static byte[] createCBytesForString(String s) { - if (s == null) { - return null; - } - - byte[] bytes = s.getBytes(); - byte[] result = new byte[bytes.length + 1]; - System.arraycopy(bytes, 0, - result, 0, - bytes.length); - result[result.length - 1] = (byte) 0; - return result; - } - - private static int detachFd(ParcelFileDescriptor pfd) { - if (pfd == null) { - return -1; - } - return pfd.detachFd(); - } - - private final String[] args; - private final String[] env; - private final String dir; - private final byte tty; - private final int stdin; - private final int stdout; - private final int stderr; - private int pid; - private int ptmx; - private int exitCode = Integer.MAX_VALUE; - - public RishHost( - String[] args, String[] env, String dir, - byte tty, - ParcelFileDescriptor stdin, ParcelFileDescriptor stdout, ParcelFileDescriptor stderr) { - - this.args = args; - this.env = env; - this.dir = dir; - this.tty = tty; - this.stdin = detachFd(stdin); - this.stdout = detachFd(stdout); - this.stderr = detachFd(stderr); - } - - /** - * Fork and execute, start transfer threads. - */ - public void start() { - Log.d(TAG, "start"); - - - byte[] argBlock = createCBytesForStringArray(args); - byte[] envBlock = createCBytesForStringArray(env); - byte[] dirBlock = createCBytesForString(dir); - - int[] result = start( - argBlock, args.length, - envBlock, env != null ? env.length : -1, - dirBlock, - tty, stdin, stdout, stderr); - - pid = result[0]; - ptmx = result[1]; - - new Thread(() -> exitCode = waitFor(pid)).start(); - } - - public int getPid() { - return pid; - } - - public int getExitCode() { - return exitCode; - } - - public void setWindowSize(long size) { - Log.d(TAG, "setWindowSize"); - - setWindowSize(ptmx, size); - } - - private static native int[] start( - byte[] argBlock, int argc, - byte[] envBlock, int envc, - byte[] dirBlock, - byte tty, int stdin, int stdout, int stderr); - - private static native void setWindowSize(int ptmx, long size); - - private static native int waitFor(int pid); -} diff --git a/rish/src/main/java/rikka/rish/RishService.java b/rish/src/main/java/rikka/rish/RishService.java deleted file mode 100644 index 59de151..0000000 --- a/rish/src/main/java/rikka/rish/RishService.java +++ /dev/null @@ -1,139 +0,0 @@ -package rikka.rish; - -import android.os.Binder; -import android.os.IBinder; -import android.os.Parcel; -import android.os.ParcelFileDescriptor; -import android.system.Os; -import android.util.Log; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import java.util.HashMap; -import java.util.Map; - -public abstract class RishService { - - private static final String TAG = "RishService"; - - private static final Map HOSTS = new HashMap<>(); - - private static final boolean IS_ROOT = Os.getuid() == 0; - - private void createHost( - String[] args, String[] env, String dir, - byte tty, - ParcelFileDescriptor stdin, ParcelFileDescriptor stdout, ParcelFileDescriptor stderr) { - - int callingPid = Binder.getCallingPid(); - - // Termux app set PATH and LD_PRELOAD to Termux's internal path. - // Adb does not have sufficient permissions to access such places. - - // Under adb, users need to set RISH_PRESERVE_ENV=1 to preserve env. - // Under root, keep env unless RISH_PRESERVE_ENV=0 is set. - - boolean allowEnv = IS_ROOT; - for (String e : env) { - if ("RISH_PRESERVE_ENV=1".equals(e)) { - allowEnv = true; - break; - } else if ("RISH_PRESERVE_ENV=0".equals(e)) { - allowEnv = false; - break; - } - } - if (!allowEnv) { - env = null; - } - - RishHost host = new RishHost(args, env, dir, tty, stdin, stdout, stderr); - host.start(); - Log.d(TAG, "Forked " + host.getPid()); - - HOSTS.put(callingPid, host); - } - - private void setWindowSize(long size) { - int callingPid = Binder.getCallingPid(); - - RishHost host = HOSTS.get(callingPid); - if (host == null) { - Log.d(TAG, "Not existing host created by " + callingPid); - return; - } - - host.setWindowSize(size); - } - - private int getExitCode() { - int callingPid = Binder.getCallingPid(); - - RishHost host = HOSTS.get(callingPid); - if (host == null) { - Log.d(TAG, "Not existing host created by " + callingPid); - return -1; - } - - return host.getExitCode(); - } - - public abstract void enforceCallingPermission(String func); - - public boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) { - if (code == RishConfig.getTransactionCode(RishConfig.TRANSACTION_createHost)) { - Log.d(TAG, "TRANSACTION_createHost"); - - enforceCallingPermission("createHost"); - - if (reply == null || (flags & IBinder.FLAG_ONEWAY) != 0) { - return true; - } - - ParcelFileDescriptor stdin; - ParcelFileDescriptor stdout; - ParcelFileDescriptor stderr = null; - - data.enforceInterface(RishConfig.getInterfaceToken()); - byte tty = data.readByte(); - stdin = data.readFileDescriptor(); - stdout = data.readFileDescriptor(); - if ((tty & RishConstants.ATTY_ERR) == 0) { - stderr = data.readFileDescriptor(); - } - String[] args = data.createStringArray(); - String[] env = data.createStringArray(); - String dir = data.readString(); - createHost(args, env, dir, tty, stdin, stdout, stderr); - reply.writeNoException(); - return true; - } else if (code == RishConfig.getTransactionCode(RishConfig.TRANSACTION_setWindowSize)) { - Log.d(TAG, "TRANSACTION_setWindowSize"); - - enforceCallingPermission("setWindowSize"); - - data.enforceInterface(RishConfig.getInterfaceToken()); - long size = data.readLong(); - setWindowSize(size); - if (reply != null) { - reply.writeNoException(); - } - return true; - } else if (code == RishConfig.getTransactionCode(RishConfig.TRANSACTION_getExitCode)) { - Log.d(TAG, "TRANSACTION_getExitCode"); - - enforceCallingPermission("getExitCode"); - - data.enforceInterface(RishConfig.getInterfaceToken()); - int exitCode = getExitCode(); - if (reply != null) { - reply.writeNoException(); - reply.writeInt(exitCode); - } - return true; - } - return false; - } - -} diff --git a/rish/src/main/java/rikka/rish/RishTerminal.java b/rish/src/main/java/rikka/rish/RishTerminal.java deleted file mode 100644 index b8a601d..0000000 --- a/rish/src/main/java/rikka/rish/RishTerminal.java +++ /dev/null @@ -1,166 +0,0 @@ -package rikka.rish; - -import android.os.Parcel; -import android.os.RemoteException; -import android.system.ErrnoException; -import android.system.Os; -import android.util.Log; - -import java.io.File; -import java.io.FileDescriptor; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -public class RishTerminal { - - private static final String TAG = "RishTerminal"; - - public static int getFd(FileDescriptor[] fileDescriptor, int i) { - if (fileDescriptor == null) { - return -1; - } - return FileDescriptors.getFd(fileDescriptor[i]); - } - - public static void closeFd(FileDescriptor[] fileDescriptor, int i) { - if (fileDescriptor == null) { - return; - } - FileDescriptors.closeSilently(fileDescriptor[i]); - } - - private final String[] argv; - private final byte tty; - private FileDescriptor[] stdin; - private FileDescriptor[] stdout; - private FileDescriptor[] stderr; - private int ttyFd = -1; - private int exitCode; - - public RishTerminal(String[] argv) throws ErrnoException, RemoteException { - this.argv = argv; - this.tty = prepare(); - - createHost(); - } - - private void createHost() throws ErrnoException, RemoteException { - Log.d(TAG, "createHost"); - Parcel data = Parcel.obtain(); - Parcel reply = Parcel.obtain(); - - List list = new ArrayList<>(); - for (Map.Entry entry : System.getenv().entrySet()) { - list.add(entry.getKey() + "=" + entry.getValue()); - } - String[] env = list.toArray(new String[0]); - - String dir = new File("").getAbsolutePath(); - - try { - data.writeInterfaceToken(RishConfig.getInterfaceToken()); - data.writeByte(tty); - stdin = Os.pipe(); - data.writeFileDescriptor(stdin[0]); - stdout = Os.pipe(); - data.writeFileDescriptor(stdout[1]); - if ((tty & RishConstants.ATTY_ERR) == 0) { - stderr = Os.pipe(); - data.writeFileDescriptor(stderr[1]); - } - data.writeStringArray(argv); - data.writeStringArray(env); - data.writeString(dir); - RishConfig.getBinder().transact(RishConfig.getTransactionCode(RishConfig.TRANSACTION_createHost), data, reply, 0); - reply.readException(); - } finally { - data.recycle(); - reply.recycle(); - - closeFd(stdin, 0); - closeFd(stdout, 1); - closeFd(stderr, 1); - } - } - - public void start() { - Log.d(TAG, "start"); - - ttyFd = start(tty, getFd(stdin, 1), getFd(stdout, 0), getFd(stdout, 0)); - - if (ttyFd != -1) { - new Thread(() -> { - while (true) { - Log.d(TAG, "waitForWindowSizeChange"); - - try { - long size = waitForWindowSizeChange(ttyFd); - setWindowSize(size); - } catch (Throwable e) { - Log.w(TAG, Log.getStackTraceString(e)); - } - } - }).start(); - } - } - - private void setWindowSize(long size) throws RemoteException { - Log.d(TAG, "setWindowSize"); - - Parcel data = Parcel.obtain(); - Parcel reply = Parcel.obtain(); - - try { - data.writeInterfaceToken(RishConfig.getInterfaceToken()); - data.writeLong(size); - RishConfig.getBinder().transact(RishConfig.getTransactionCode(RishConfig.TRANSACTION_setWindowSize), data, null, 0); - reply.readException(); - } finally { - data.recycle(); - reply.recycle(); - } - } - - private int requestExitCode() throws RemoteException { - Log.d(TAG, "requestExitCode"); - - Parcel data = Parcel.obtain(); - Parcel reply = Parcel.obtain(); - - try { - data.writeInterfaceToken(RishConfig.getInterfaceToken()); - RishConfig.getBinder().transact(RishConfig.getTransactionCode(RishConfig.TRANSACTION_getExitCode), data, null, 0); - reply.readException(); - return reply.readInt(); - } finally { - data.recycle(); - reply.recycle(); - } - } - - public int waitFor() { - Log.d(TAG, "waitFor"); - - waitForProcessExit(); - try { - exitCode = requestExitCode(); - } catch (Throwable e) { - Log.w(TAG, Log.getStackTraceString(e)); - exitCode = -1; - } - return exitCode; - } - - public int getExitCode() { - return exitCode; - } - - private static native byte prepare(); - - private static native int start(byte tty, int stdin, int stdout, int stderr); - - private static native long waitForWindowSizeChange(int fd); - - private static native void waitForProcessExit(); -}