#include #include #include #include #include #include #include #include #include #include #include #include #include #include #define unused __attribute__((__unused__)) #define DEFAULT_PREFIX "/data/data/me.sergiotarxz.openmg.x11/files/usr" #define DEFAULT_XDG_RUNTIME_DIR DEFAULT_PREFIX "/tmp" #define DEFAULT_SOCKET_NAME "wayland-0" static int socket_action(int* fd, char* path, int (*action)(int, const struct sockaddr *, socklen_t)) { if (!fd || !action) { errno = -EINVAL; return -1; } struct sockaddr_un local; size_t len; if((*fd = socket(PF_LOCAL, SOCK_STREAM, 0)) == -1) { perror("socket"); return *fd; } local.sun_family = AF_UNIX; strcpy(local.sun_path, path); len = strlen(local.sun_path) + sizeof(local.sun_family); return action(*fd, (struct sockaddr *)&local, len); } JNIEXPORT void JNICALL Java_me_sergiotarxz_openmg_x11_starter_Starter_checkXdgRuntimeDir(unused JNIEnv *env, unused jobject thiz) { char* XDG_RUNTIME_DIR = getenv("XDG_RUNTIME_DIR"); if (!XDG_RUNTIME_DIR || strlen(XDG_RUNTIME_DIR) == 0) { printf("$XDG_RUNTIME_DIR is unset.\n"); printf("Exporting default value (%s).\n", DEFAULT_XDG_RUNTIME_DIR); setenv("XDG_RUNTIME_DIR", DEFAULT_XDG_RUNTIME_DIR, true); } } static const char *getWaylandSocketPath() { static char* path = NULL; if (path != NULL) return path; path = malloc(256 * sizeof(char)); memset(path, 0, 256 * sizeof(char)); char* XDG_RUNTIME_DIR = getenv("XDG_RUNTIME_DIR"); if (!XDG_RUNTIME_DIR || strlen(XDG_RUNTIME_DIR) == 0) { printf("$XDG_RUNTIME_DIR is unset"); exit(1); } sprintf(path, "%s/%s", XDG_RUNTIME_DIR, DEFAULT_SOCKET_NAME); return path; } JNIEXPORT jboolean JNICALL Java_me_sergiotarxz_openmg_x11_starter_Starter_checkWaylandSocket(unused JNIEnv *env, unused jobject thiz) { int fd; errno = 0; if (socket_action(&fd, (char *) getWaylandSocketPath(), connect) != -1) { close(fd); return 1; } return 0; } JNIEXPORT jint JNICALL Java_me_sergiotarxz_openmg_x11_starter_Starter_createWaylandSocket(unused JNIEnv *env, unused jobject thiz) { int fd; errno = 0; unlink(getWaylandSocketPath()); if (socket_action(&fd, (char *) getWaylandSocketPath(), bind) < 0) { perror("socket"); return -1; } return fd; } #pragma clang diagnostic push #pragma ide diagnostic ignored "hicpp-signed-bitwise" JNIEXPORT jint JNICALL Java_me_sergiotarxz_openmg_x11_starter_Starter_openLogFD(unused JNIEnv *env, unused jobject thiz) { const char* TERMUX_X11_LOG_FILE = getenv("TERMUX_X11_LOG_FILE"); int sv[2]; /* the pair of socket descriptors */ if (TERMUX_X11_LOG_FILE == NULL || strlen(TERMUX_X11_LOG_FILE) == 0) return -1; int logfd = open(TERMUX_X11_LOG_FILE, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (logfd < 0) { perror("open logfile"); return -1; } if (pipe(sv) == -1) { perror("pipe"); return -1; } fchmod (sv[0], 0777); fchmod (sv[1], 0777); switch(fork()) { /* * Android do not allow another process to write to tty or pipe fd of our process. * We can not force allowing even using chmod. * That is a reason we are using pipe and cat here. */ case 0: { int new_stderr = dup(2); close(sv[1]); dup2(sv[0], 0); dup2(logfd, 1); dup2(logfd, 2); close(sv[0]); close(logfd); printf("cat started (%d)\n", getpid()); struct pollfd pfd = {0}; pfd.fd = 0; pfd.events = POLLIN | POLLHUP; poll(&pfd, 1, 10000); execl("/data/data/me.sergiotarxz.openmg.x11/files/usr/bin/cat", "cat", NULL); dprintf(new_stderr, "execl cat: %s\n", strerror(errno)); return -1; } case -1: return -1; default: close(sv[0]); close(logfd); return sv[1]; } } #pragma clang diagnostic pop