mirror of
https://github.com/fankes/termux-app.git
synced 2025-09-04 17:55:36 +08:00
termux.c: Re-indent whole file with vim
This commit is contained in:
@@ -17,203 +17,203 @@
|
||||
|
||||
static int throw_runtime_exception(JNIEnv* env, char const* message)
|
||||
{
|
||||
jclass exClass = (*env)->FindClass(env, "java/lang/RuntimeException");
|
||||
(*env)->ThrowNew(env, exClass, message);
|
||||
return -1;
|
||||
jclass exClass = (*env)->FindClass(env, "java/lang/RuntimeException");
|
||||
(*env)->ThrowNew(env, exClass, message);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int create_subprocess(JNIEnv* env,
|
||||
char const* cmd,
|
||||
char const* cwd,
|
||||
char* const argv[],
|
||||
char** envp,
|
||||
int* pProcessId,
|
||||
jint rows,
|
||||
jint columns)
|
||||
char const* cmd,
|
||||
char const* cwd,
|
||||
char* const argv[],
|
||||
char** envp,
|
||||
int* pProcessId,
|
||||
jint rows,
|
||||
jint columns)
|
||||
{
|
||||
int ptm = open("/dev/ptmx", O_RDWR | O_CLOEXEC);
|
||||
if (ptm < 0) return throw_runtime_exception(env, "Cannot open /dev/ptmx");
|
||||
int ptm = open("/dev/ptmx", O_RDWR | O_CLOEXEC);
|
||||
if (ptm < 0) return throw_runtime_exception(env, "Cannot open /dev/ptmx");
|
||||
|
||||
#ifdef LACKS_PTSNAME_R
|
||||
char* devname;
|
||||
char* devname;
|
||||
#else
|
||||
char devname[64];
|
||||
char devname[64];
|
||||
#endif
|
||||
if (grantpt(ptm) || unlockpt(ptm) ||
|
||||
if (grantpt(ptm) || unlockpt(ptm) ||
|
||||
#ifdef LACKS_PTSNAME_R
|
||||
(devname = ptsname(ptm)) == NULL
|
||||
(devname = ptsname(ptm)) == NULL
|
||||
#else
|
||||
ptsname_r(ptm, devname, sizeof(devname))
|
||||
ptsname_r(ptm, devname, sizeof(devname))
|
||||
#endif
|
||||
) {
|
||||
return throw_runtime_exception(env, "Cannot grantpt()/unlockpt()/ptsname_r() on /dev/ptmx");
|
||||
) {
|
||||
return throw_runtime_exception(env, "Cannot grantpt()/unlockpt()/ptsname_r() on /dev/ptmx");
|
||||
}
|
||||
|
||||
// Enable UTF-8 mode and disable flow control to prevent Ctrl+S from locking up the display.
|
||||
struct termios tios;
|
||||
tcgetattr(ptm, &tios);
|
||||
tios.c_iflag |= IUTF8;
|
||||
tios.c_iflag &= ~(IXON | IXOFF);
|
||||
tcsetattr(ptm, TCSANOW, &tios);
|
||||
|
||||
/** Set initial winsize. */
|
||||
struct winsize sz = { .ws_row = rows, .ws_col = columns };
|
||||
ioctl(ptm, TIOCSWINSZ, &sz);
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
return throw_runtime_exception(env, "Fork failed");
|
||||
} else if (pid > 0) {
|
||||
*pProcessId = (int) pid;
|
||||
return ptm;
|
||||
} else {
|
||||
// Clear signals which the Android java process may have blocked:
|
||||
sigset_t signals_to_unblock;
|
||||
sigfillset(&signals_to_unblock);
|
||||
sigprocmask(SIG_UNBLOCK, &signals_to_unblock, 0);
|
||||
|
||||
close(ptm);
|
||||
setsid();
|
||||
|
||||
int pts = open(devname, O_RDWR);
|
||||
if (pts < 0) exit(-1);
|
||||
|
||||
dup2(pts, 0);
|
||||
dup2(pts, 1);
|
||||
dup2(pts, 2);
|
||||
|
||||
DIR* self_dir = opendir("/proc/self/fd");
|
||||
if (self_dir != NULL) {
|
||||
int self_dir_fd = dirfd(self_dir);
|
||||
struct dirent* entry;
|
||||
while ((entry = readdir(self_dir)) != NULL) {
|
||||
int fd = atoi(entry->d_name);
|
||||
if(fd > 2 && fd != self_dir_fd) close(fd);
|
||||
}
|
||||
closedir(self_dir);
|
||||
}
|
||||
|
||||
// Enable UTF-8 mode and disable flow control to prevent Ctrl+S from locking up the display.
|
||||
struct termios tios;
|
||||
tcgetattr(ptm, &tios);
|
||||
tios.c_iflag |= IUTF8;
|
||||
tios.c_iflag &= ~(IXON | IXOFF);
|
||||
tcsetattr(ptm, TCSANOW, &tios);
|
||||
clearenv();
|
||||
if (envp) for (; *envp; ++envp) putenv(*envp);
|
||||
|
||||
/** Set initial winsize. */
|
||||
struct winsize sz = { .ws_row = rows, .ws_col = columns };
|
||||
ioctl(ptm, TIOCSWINSZ, &sz);
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
return throw_runtime_exception(env, "Fork failed");
|
||||
} else if (pid > 0) {
|
||||
*pProcessId = (int) pid;
|
||||
return ptm;
|
||||
} else {
|
||||
// Clear signals which the Android java process may have blocked:
|
||||
sigset_t signals_to_unblock;
|
||||
sigfillset(&signals_to_unblock);
|
||||
sigprocmask(SIG_UNBLOCK, &signals_to_unblock, 0);
|
||||
|
||||
close(ptm);
|
||||
setsid();
|
||||
|
||||
int pts = open(devname, O_RDWR);
|
||||
if (pts < 0) exit(-1);
|
||||
|
||||
dup2(pts, 0);
|
||||
dup2(pts, 1);
|
||||
dup2(pts, 2);
|
||||
|
||||
DIR* self_dir = opendir("/proc/self/fd");
|
||||
if (self_dir != NULL) {
|
||||
int self_dir_fd = dirfd(self_dir);
|
||||
struct dirent* entry;
|
||||
while ((entry = readdir(self_dir)) != NULL) {
|
||||
int fd = atoi(entry->d_name);
|
||||
if(fd > 2 && fd != self_dir_fd) close(fd);
|
||||
}
|
||||
closedir(self_dir);
|
||||
}
|
||||
|
||||
clearenv();
|
||||
if (envp) for (; *envp; ++envp) putenv(*envp);
|
||||
|
||||
if (chdir(cwd) != 0) {
|
||||
char* error_message;
|
||||
// No need to free asprintf()-allocated memory since doing execvp() or exit() below.
|
||||
if (asprintf(&error_message, "chdir(\"%s\")", cwd) == -1) error_message = "chdir()";
|
||||
perror(error_message);
|
||||
fflush(stderr);
|
||||
}
|
||||
execvp(cmd, argv);
|
||||
// Show terminal output about failing exec() call:
|
||||
char* error_message;
|
||||
if (asprintf(&error_message, "exec(\"%s\")", cmd) == -1) error_message = "exec()";
|
||||
perror(error_message);
|
||||
_exit(1);
|
||||
if (chdir(cwd) != 0) {
|
||||
char* error_message;
|
||||
// No need to free asprintf()-allocated memory since doing execvp() or exit() below.
|
||||
if (asprintf(&error_message, "chdir(\"%s\")", cwd) == -1) error_message = "chdir()";
|
||||
perror(error_message);
|
||||
fflush(stderr);
|
||||
}
|
||||
execvp(cmd, argv);
|
||||
// Show terminal output about failing exec() call:
|
||||
char* error_message;
|
||||
if (asprintf(&error_message, "exec(\"%s\")", cmd) == -1) error_message = "exec()";
|
||||
perror(error_message);
|
||||
_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_com_termux_terminal_JNI_createSubprocess(
|
||||
JNIEnv* env,
|
||||
jclass TERMUX_UNUSED(clazz),
|
||||
jstring cmd,
|
||||
jstring cwd,
|
||||
jobjectArray args,
|
||||
jobjectArray envVars,
|
||||
jintArray processIdArray,
|
||||
jint rows,
|
||||
jint columns)
|
||||
JNIEnv* env,
|
||||
jclass TERMUX_UNUSED(clazz),
|
||||
jstring cmd,
|
||||
jstring cwd,
|
||||
jobjectArray args,
|
||||
jobjectArray envVars,
|
||||
jintArray processIdArray,
|
||||
jint rows,
|
||||
jint columns)
|
||||
{
|
||||
jsize size = args ? (*env)->GetArrayLength(env, args) : 0;
|
||||
char** argv = NULL;
|
||||
if (size > 0) {
|
||||
argv = (char**) malloc((size + 1) * sizeof(char*));
|
||||
if (!argv) return throw_runtime_exception(env, "Couldn't allocate argv array");
|
||||
for (int i = 0; i < size; ++i) {
|
||||
jstring arg_java_string = (jstring) (*env)->GetObjectArrayElement(env, args, i);
|
||||
char const* arg_utf8 = (*env)->GetStringUTFChars(env, arg_java_string, NULL);
|
||||
if (!arg_utf8) return throw_runtime_exception(env, "GetStringUTFChars() failed for argv");
|
||||
argv[i] = strdup(arg_utf8);
|
||||
(*env)->ReleaseStringUTFChars(env, arg_java_string, arg_utf8);
|
||||
}
|
||||
argv[size] = NULL;
|
||||
jsize size = args ? (*env)->GetArrayLength(env, args) : 0;
|
||||
char** argv = NULL;
|
||||
if (size > 0) {
|
||||
argv = (char**) malloc((size + 1) * sizeof(char*));
|
||||
if (!argv) return throw_runtime_exception(env, "Couldn't allocate argv array");
|
||||
for (int i = 0; i < size; ++i) {
|
||||
jstring arg_java_string = (jstring) (*env)->GetObjectArrayElement(env, args, i);
|
||||
char const* arg_utf8 = (*env)->GetStringUTFChars(env, arg_java_string, NULL);
|
||||
if (!arg_utf8) return throw_runtime_exception(env, "GetStringUTFChars() failed for argv");
|
||||
argv[i] = strdup(arg_utf8);
|
||||
(*env)->ReleaseStringUTFChars(env, arg_java_string, arg_utf8);
|
||||
}
|
||||
argv[size] = NULL;
|
||||
}
|
||||
|
||||
size = envVars ? (*env)->GetArrayLength(env, envVars) : 0;
|
||||
char** envp = NULL;
|
||||
if (size > 0) {
|
||||
envp = (char**) malloc((size + 1) * sizeof(char *));
|
||||
if (!envp) return throw_runtime_exception(env, "malloc() for envp array failed");
|
||||
for (int i = 0; i < size; ++i) {
|
||||
jstring env_java_string = (jstring) (*env)->GetObjectArrayElement(env, envVars, i);
|
||||
char const* env_utf8 = (*env)->GetStringUTFChars(env, env_java_string, 0);
|
||||
if (!env_utf8) return throw_runtime_exception(env, "GetStringUTFChars() failed for env");
|
||||
envp[i] = strdup(env_utf8);
|
||||
(*env)->ReleaseStringUTFChars(env, env_java_string, env_utf8);
|
||||
}
|
||||
envp[size] = NULL;
|
||||
size = envVars ? (*env)->GetArrayLength(env, envVars) : 0;
|
||||
char** envp = NULL;
|
||||
if (size > 0) {
|
||||
envp = (char**) malloc((size + 1) * sizeof(char *));
|
||||
if (!envp) return throw_runtime_exception(env, "malloc() for envp array failed");
|
||||
for (int i = 0; i < size; ++i) {
|
||||
jstring env_java_string = (jstring) (*env)->GetObjectArrayElement(env, envVars, i);
|
||||
char const* env_utf8 = (*env)->GetStringUTFChars(env, env_java_string, 0);
|
||||
if (!env_utf8) return throw_runtime_exception(env, "GetStringUTFChars() failed for env");
|
||||
envp[i] = strdup(env_utf8);
|
||||
(*env)->ReleaseStringUTFChars(env, env_java_string, env_utf8);
|
||||
}
|
||||
envp[size] = NULL;
|
||||
}
|
||||
|
||||
int procId = 0;
|
||||
char const* cmd_cwd = (*env)->GetStringUTFChars(env, cwd, NULL);
|
||||
char const* cmd_utf8 = (*env)->GetStringUTFChars(env, cmd, NULL);
|
||||
int ptm = create_subprocess(env, cmd_utf8, cmd_cwd, argv, envp, &procId, rows, columns);
|
||||
(*env)->ReleaseStringUTFChars(env, cmd, cmd_utf8);
|
||||
(*env)->ReleaseStringUTFChars(env, cmd, cmd_cwd);
|
||||
int procId = 0;
|
||||
char const* cmd_cwd = (*env)->GetStringUTFChars(env, cwd, NULL);
|
||||
char const* cmd_utf8 = (*env)->GetStringUTFChars(env, cmd, NULL);
|
||||
int ptm = create_subprocess(env, cmd_utf8, cmd_cwd, argv, envp, &procId, rows, columns);
|
||||
(*env)->ReleaseStringUTFChars(env, cmd, cmd_utf8);
|
||||
(*env)->ReleaseStringUTFChars(env, cmd, cmd_cwd);
|
||||
|
||||
if (argv) {
|
||||
for (char** tmp = argv; *tmp; ++tmp) free(*tmp);
|
||||
free(argv);
|
||||
}
|
||||
if (envp) {
|
||||
for (char** tmp = envp; *tmp; ++tmp) free(*tmp);
|
||||
free(envp);
|
||||
}
|
||||
if (argv) {
|
||||
for (char** tmp = argv; *tmp; ++tmp) free(*tmp);
|
||||
free(argv);
|
||||
}
|
||||
if (envp) {
|
||||
for (char** tmp = envp; *tmp; ++tmp) free(*tmp);
|
||||
free(envp);
|
||||
}
|
||||
|
||||
int* pProcId = (int*) (*env)->GetPrimitiveArrayCritical(env, processIdArray, NULL);
|
||||
if (!pProcId) return throw_runtime_exception(env, "JNI call GetPrimitiveArrayCritical(processIdArray, &isCopy) failed");
|
||||
int* pProcId = (int*) (*env)->GetPrimitiveArrayCritical(env, processIdArray, NULL);
|
||||
if (!pProcId) return throw_runtime_exception(env, "JNI call GetPrimitiveArrayCritical(processIdArray, &isCopy) failed");
|
||||
|
||||
*pProcId = procId;
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, processIdArray, pProcId, 0);
|
||||
*pProcId = procId;
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, processIdArray, pProcId, 0);
|
||||
|
||||
return ptm;
|
||||
return ptm;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_termux_terminal_JNI_setPtyWindowSize(JNIEnv* TERMUX_UNUSED(env), jclass TERMUX_UNUSED(clazz), jint fd, jint rows, jint cols)
|
||||
{
|
||||
struct winsize sz = { .ws_row = rows, .ws_col = cols };
|
||||
ioctl(fd, TIOCSWINSZ, &sz);
|
||||
struct winsize sz = { .ws_row = rows, .ws_col = cols };
|
||||
ioctl(fd, TIOCSWINSZ, &sz);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_termux_terminal_JNI_setPtyUTF8Mode(JNIEnv* TERMUX_UNUSED(env), jclass TERMUX_UNUSED(clazz), jint fd)
|
||||
{
|
||||
struct termios tios;
|
||||
tcgetattr(fd, &tios);
|
||||
if ((tios.c_iflag & IUTF8) == 0) {
|
||||
tios.c_iflag |= IUTF8;
|
||||
tcsetattr(fd, TCSANOW, &tios);
|
||||
}
|
||||
struct termios tios;
|
||||
tcgetattr(fd, &tios);
|
||||
if ((tios.c_iflag & IUTF8) == 0) {
|
||||
tios.c_iflag |= IUTF8;
|
||||
tcsetattr(fd, TCSANOW, &tios);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT int JNICALL Java_com_termux_terminal_JNI_waitFor(JNIEnv* TERMUX_UNUSED(env), jclass TERMUX_UNUSED(clazz), jint pid)
|
||||
{
|
||||
int status;
|
||||
waitpid(pid, &status, 0);
|
||||
if (WIFEXITED(status)) {
|
||||
return WEXITSTATUS(status);
|
||||
} else if (WIFSIGNALED(status)) {
|
||||
return -WTERMSIG(status);
|
||||
} else {
|
||||
// Should never happen - waitpid(2) says "One of the first three macros will evaluate to a non-zero (true) value".
|
||||
return 0;
|
||||
}
|
||||
int status;
|
||||
waitpid(pid, &status, 0);
|
||||
if (WIFEXITED(status)) {
|
||||
return WEXITSTATUS(status);
|
||||
} else if (WIFSIGNALED(status)) {
|
||||
return -WTERMSIG(status);
|
||||
} else {
|
||||
// Should never happen - waitpid(2) says "One of the first three macros will evaluate to a non-zero (true) value".
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_termux_terminal_JNI_hangupProcessGroup(JNIEnv* TERMUX_UNUSED(env), jclass TERMUX_UNUSED(clazz), jint procId)
|
||||
{
|
||||
killpg(procId, SIGHUP);
|
||||
killpg(procId, SIGHUP);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_termux_terminal_JNI_close(JNIEnv* TERMUX_UNUSED(env), jclass TERMUX_UNUSED(clazz), jint fileDescriptor)
|
||||
{
|
||||
close(fileDescriptor);
|
||||
close(fileDescriptor);
|
||||
}
|
||||
|
Reference in New Issue
Block a user