termux.c: Re-indent whole file with vim

This commit is contained in:
Fredrik Fornwall
2016-04-23 12:21:36 +02:00
parent 746dc750df
commit 46da1fc833

View File

@@ -17,203 +17,203 @@
static int throw_runtime_exception(JNIEnv* env, char const* message) static int throw_runtime_exception(JNIEnv* env, char const* message)
{ {
jclass exClass = (*env)->FindClass(env, "java/lang/RuntimeException"); jclass exClass = (*env)->FindClass(env, "java/lang/RuntimeException");
(*env)->ThrowNew(env, exClass, message); (*env)->ThrowNew(env, exClass, message);
return -1; return -1;
} }
static int create_subprocess(JNIEnv* env, static int create_subprocess(JNIEnv* env,
char const* cmd, char const* cmd,
char const* cwd, char const* cwd,
char* const argv[], char* const argv[],
char** envp, char** envp,
int* pProcessId, int* pProcessId,
jint rows, jint rows,
jint columns) jint columns)
{ {
int ptm = open("/dev/ptmx", O_RDWR | O_CLOEXEC); int ptm = open("/dev/ptmx", O_RDWR | O_CLOEXEC);
if (ptm < 0) return throw_runtime_exception(env, "Cannot open /dev/ptmx"); if (ptm < 0) return throw_runtime_exception(env, "Cannot open /dev/ptmx");
#ifdef LACKS_PTSNAME_R #ifdef LACKS_PTSNAME_R
char* devname; char* devname;
#else #else
char devname[64]; char devname[64];
#endif #endif
if (grantpt(ptm) || unlockpt(ptm) || if (grantpt(ptm) || unlockpt(ptm) ||
#ifdef LACKS_PTSNAME_R #ifdef LACKS_PTSNAME_R
(devname = ptsname(ptm)) == NULL (devname = ptsname(ptm)) == NULL
#else #else
ptsname_r(ptm, devname, sizeof(devname)) ptsname_r(ptm, devname, sizeof(devname))
#endif #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. clearenv();
struct termios tios; if (envp) for (; *envp; ++envp) putenv(*envp);
tcgetattr(ptm, &tios);
tios.c_iflag |= IUTF8;
tios.c_iflag &= ~(IXON | IXOFF);
tcsetattr(ptm, TCSANOW, &tios);
/** Set initial winsize. */ if (chdir(cwd) != 0) {
struct winsize sz = { .ws_row = rows, .ws_col = columns }; char* error_message;
ioctl(ptm, TIOCSWINSZ, &sz); // No need to free asprintf()-allocated memory since doing execvp() or exit() below.
if (asprintf(&error_message, "chdir(\"%s\")", cwd) == -1) error_message = "chdir()";
pid_t pid = fork(); perror(error_message);
if (pid < 0) { fflush(stderr);
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);
} }
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( JNIEXPORT jint JNICALL Java_com_termux_terminal_JNI_createSubprocess(
JNIEnv* env, JNIEnv* env,
jclass TERMUX_UNUSED(clazz), jclass TERMUX_UNUSED(clazz),
jstring cmd, jstring cmd,
jstring cwd, jstring cwd,
jobjectArray args, jobjectArray args,
jobjectArray envVars, jobjectArray envVars,
jintArray processIdArray, jintArray processIdArray,
jint rows, jint rows,
jint columns) jint columns)
{ {
jsize size = args ? (*env)->GetArrayLength(env, args) : 0; jsize size = args ? (*env)->GetArrayLength(env, args) : 0;
char** argv = NULL; char** argv = NULL;
if (size > 0) { if (size > 0) {
argv = (char**) malloc((size + 1) * sizeof(char*)); argv = (char**) malloc((size + 1) * sizeof(char*));
if (!argv) return throw_runtime_exception(env, "Couldn't allocate argv array"); if (!argv) return throw_runtime_exception(env, "Couldn't allocate argv array");
for (int i = 0; i < size; ++i) { for (int i = 0; i < size; ++i) {
jstring arg_java_string = (jstring) (*env)->GetObjectArrayElement(env, args, i); jstring arg_java_string = (jstring) (*env)->GetObjectArrayElement(env, args, i);
char const* arg_utf8 = (*env)->GetStringUTFChars(env, arg_java_string, NULL); char const* arg_utf8 = (*env)->GetStringUTFChars(env, arg_java_string, NULL);
if (!arg_utf8) return throw_runtime_exception(env, "GetStringUTFChars() failed for argv"); if (!arg_utf8) return throw_runtime_exception(env, "GetStringUTFChars() failed for argv");
argv[i] = strdup(arg_utf8); argv[i] = strdup(arg_utf8);
(*env)->ReleaseStringUTFChars(env, arg_java_string, arg_utf8); (*env)->ReleaseStringUTFChars(env, arg_java_string, arg_utf8);
}
argv[size] = NULL;
} }
argv[size] = NULL;
}
size = envVars ? (*env)->GetArrayLength(env, envVars) : 0; size = envVars ? (*env)->GetArrayLength(env, envVars) : 0;
char** envp = NULL; char** envp = NULL;
if (size > 0) { if (size > 0) {
envp = (char**) malloc((size + 1) * sizeof(char *)); envp = (char**) malloc((size + 1) * sizeof(char *));
if (!envp) return throw_runtime_exception(env, "malloc() for envp array failed"); if (!envp) return throw_runtime_exception(env, "malloc() for envp array failed");
for (int i = 0; i < size; ++i) { for (int i = 0; i < size; ++i) {
jstring env_java_string = (jstring) (*env)->GetObjectArrayElement(env, envVars, i); jstring env_java_string = (jstring) (*env)->GetObjectArrayElement(env, envVars, i);
char const* env_utf8 = (*env)->GetStringUTFChars(env, env_java_string, 0); char const* env_utf8 = (*env)->GetStringUTFChars(env, env_java_string, 0);
if (!env_utf8) return throw_runtime_exception(env, "GetStringUTFChars() failed for env"); if (!env_utf8) return throw_runtime_exception(env, "GetStringUTFChars() failed for env");
envp[i] = strdup(env_utf8); envp[i] = strdup(env_utf8);
(*env)->ReleaseStringUTFChars(env, env_java_string, env_utf8); (*env)->ReleaseStringUTFChars(env, env_java_string, env_utf8);
}
envp[size] = NULL;
} }
envp[size] = NULL;
}
int procId = 0; int procId = 0;
char const* cmd_cwd = (*env)->GetStringUTFChars(env, cwd, NULL); char const* cmd_cwd = (*env)->GetStringUTFChars(env, cwd, NULL);
char const* cmd_utf8 = (*env)->GetStringUTFChars(env, cmd, NULL); char const* cmd_utf8 = (*env)->GetStringUTFChars(env, cmd, NULL);
int ptm = create_subprocess(env, cmd_utf8, cmd_cwd, argv, envp, &procId, rows, columns); 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_utf8);
(*env)->ReleaseStringUTFChars(env, cmd, cmd_cwd); (*env)->ReleaseStringUTFChars(env, cmd, cmd_cwd);
if (argv) { if (argv) {
for (char** tmp = argv; *tmp; ++tmp) free(*tmp); for (char** tmp = argv; *tmp; ++tmp) free(*tmp);
free(argv); free(argv);
} }
if (envp) { if (envp) {
for (char** tmp = envp; *tmp; ++tmp) free(*tmp); for (char** tmp = envp; *tmp; ++tmp) free(*tmp);
free(envp); free(envp);
} }
int* pProcId = (int*) (*env)->GetPrimitiveArrayCritical(env, processIdArray, NULL); int* pProcId = (int*) (*env)->GetPrimitiveArrayCritical(env, processIdArray, NULL);
if (!pProcId) return throw_runtime_exception(env, "JNI call GetPrimitiveArrayCritical(processIdArray, &isCopy) failed"); if (!pProcId) return throw_runtime_exception(env, "JNI call GetPrimitiveArrayCritical(processIdArray, &isCopy) failed");
*pProcId = procId; *pProcId = procId;
(*env)->ReleasePrimitiveArrayCritical(env, processIdArray, pProcId, 0); (*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) 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 }; struct winsize sz = { .ws_row = rows, .ws_col = cols };
ioctl(fd, TIOCSWINSZ, &sz); ioctl(fd, TIOCSWINSZ, &sz);
} }
JNIEXPORT void JNICALL Java_com_termux_terminal_JNI_setPtyUTF8Mode(JNIEnv* TERMUX_UNUSED(env), jclass TERMUX_UNUSED(clazz), jint fd) JNIEXPORT void JNICALL Java_com_termux_terminal_JNI_setPtyUTF8Mode(JNIEnv* TERMUX_UNUSED(env), jclass TERMUX_UNUSED(clazz), jint fd)
{ {
struct termios tios; struct termios tios;
tcgetattr(fd, &tios); tcgetattr(fd, &tios);
if ((tios.c_iflag & IUTF8) == 0) { if ((tios.c_iflag & IUTF8) == 0) {
tios.c_iflag |= IUTF8; tios.c_iflag |= IUTF8;
tcsetattr(fd, TCSANOW, &tios); tcsetattr(fd, TCSANOW, &tios);
} }
} }
JNIEXPORT int JNICALL Java_com_termux_terminal_JNI_waitFor(JNIEnv* TERMUX_UNUSED(env), jclass TERMUX_UNUSED(clazz), jint pid) JNIEXPORT int JNICALL Java_com_termux_terminal_JNI_waitFor(JNIEnv* TERMUX_UNUSED(env), jclass TERMUX_UNUSED(clazz), jint pid)
{ {
int status; int status;
waitpid(pid, &status, 0); waitpid(pid, &status, 0);
if (WIFEXITED(status)) { if (WIFEXITED(status)) {
return WEXITSTATUS(status); return WEXITSTATUS(status);
} else if (WIFSIGNALED(status)) { } else if (WIFSIGNALED(status)) {
return -WTERMSIG(status); return -WTERMSIG(status);
} else { } else {
// Should never happen - waitpid(2) says "One of the first three macros will evaluate to a non-zero (true) value". // Should never happen - waitpid(2) says "One of the first three macros will evaluate to a non-zero (true) value".
return 0; return 0;
} }
} }
JNIEXPORT void JNICALL Java_com_termux_terminal_JNI_hangupProcessGroup(JNIEnv* TERMUX_UNUSED(env), jclass TERMUX_UNUSED(clazz), jint procId) 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) JNIEXPORT void JNICALL Java_com_termux_terminal_JNI_close(JNIEnv* TERMUX_UNUSED(env), jclass TERMUX_UNUSED(clazz), jint fileDescriptor)
{ {
close(fileDescriptor); close(fileDescriptor);
} }