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();
-}