1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
| static int create_subprocess(JNIEnv* env, 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");
#ifdef LACKS_PTSNAME_R char* devname; #else char devname[64]; #endif if (grantpt(ptm) || unlockpt(ptm) || #ifdef LACKS_PTSNAME_R (devname = ptsname(ptm)) == NULL #else ptsname_r(ptm, devname, sizeof(devname)) #endif ) { return throw_runtime_exception(env, "Cannot grantpt()/unlockpt()/ptsname_r() on /dev/ptmx"); }
struct termios tios; tcgetattr(ptm, &tios); tios.c_iflag |= IUTF8; tios.c_iflag &= ~(IXON | IXOFF); tcsetattr(ptm, TCSANOW, &tios);
struct winsize sz = { .ws_row = (unsigned short) rows, .ws_col = (unsigned short) 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 { 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; if (asprintf(&error_message, "chdir(\"%s\")", cwd) == -1) error_message = "chdir()"; perror(error_message); fflush(stderr); } execvp(cmd, argv); char* error_message; if (asprintf(&error_message, "exec(\"%s\")", cmd) == -1) error_message = "exec()"; perror(error_message); _exit(1); } }
|