vtgl

terminal emulator implemented in OpenGL
git clone anongit@rnpnr.xyz:vtgl.git
Log | Files | Refs | Feed | LICENSE

Commit: 9cfa730cbaf2d69ddb25dd22c2230b11fd36c151
Parent: b14e800a97c108805665b3a769d834a40463ea59
Author: Randy Palamar
Date:   Wed,  4 Dec 2024 07:53:47 -0700

replace forkpty

Diffstat:
Mos_unix.c | 43++++++++++++++++++++++++++++++-------------
Mplatform_linux_amd64.c | 3+++
Mplatform_linux_common.c | 1+
3 files changed, 34 insertions(+), 13 deletions(-)

diff --git a/os_unix.c b/os_unix.c @@ -27,31 +27,48 @@ execsh(char *defcmd) execvp(sh, argv); - _exit(1); + syscall1(SYS_exit_group, 1); } static linux_platform_process os_fork_child(char *cmd) { - i32 cfd; + i32 n = 0; + i64 m = syscall3(SYS_open, (iptr)"/dev/ptmx", O_RDWR|O_NOCTTY, 0); + if (m > -4096UL) os_fatal(s8("os_fork_child: failed to open master terminal\n")); + /* NOTE: first unlock the tty, then get a valid pty number */ + if (syscall3(SYS_ioctl, m, TIOCSPTLCK, (iptr)&n) || syscall3(SYS_ioctl, m, TIOCGPTN, (iptr)&n)) + os_fatal(s8("os_fork_child: failed to get a pty number\n")); - pid_t pid = forkpty(&cfd, NULL, NULL, NULL); + u8 buffer[20] = {"/dev/pts/"}; + Stream sbuf = {.buf = buffer, .cap = 20, .widx = sizeof("/dev/pts/") - 1}; + stream_push_i64(&sbuf, n); + stream_push_byte(&sbuf, 0); - switch (pid) { - case -1: - os_write_err_msg(s8("os_fork_child: failed to spawn child: ")); - os_write_err_msg(c_str_to_s8(cmd)); - os_fatal(s8("\n")); - case 0: /* child */ + i64 s = syscall3(SYS_open, (iptr)sbuf.buf, O_RDWR|O_NOCTTY, 0); + if (s > -4096UL) os_fatal(s8("os_fork_child: failed to open slave terminal\n")); + + i64 pid = syscall1(SYS_fork, 0); + if (pid > -4096UL) os_fatal(s8("os_fork_child: failed to fork a child\n")); + + if (pid == 0) { + syscall1(SYS_close, m); + syscall1(SYS_setsid, 0); + syscall2(SYS_dup2, s, 0); + syscall2(SYS_dup2, s, 1); + syscall2(SYS_dup2, s, 2); + syscall3(SYS_ioctl, s, TIOCSCTTY, 0); + if (s > 2) syscall1(SYS_close, s); execsh(cmd); - break; } + syscall1(SYS_close, s); - i32 flags = fcntl(cfd, F_GETFL); + /* TODO: why is this needed? are we blocking on write? */ + i32 flags = fcntl(m, F_GETFL); if (flags == -1) os_fatal(s8("os_fork_child: fcntl: F_GETFL\n")); - if (fcntl(cfd, F_SETFL, flags | O_NONBLOCK) == -1) + if (fcntl(m, F_SETFL, flags | O_NONBLOCK) == -1) os_fatal(s8("os_fork_child: fcntl: F_SETFL\n")); - return (linux_platform_process){.process_id = pid, .handle = cfd}; + return (linux_platform_process){.process_id = pid, .handle = m}; } diff --git a/platform_linux_amd64.c b/platform_linux_amd64.c @@ -19,9 +19,12 @@ #define SYS_ioctl 16 #define SYS_pwrite 18 #define SYS_madvise 28 +#define SYS_dup2 33 #define SYS_clone 56 +#define SYS_fork 57 #define SYS_wait4 61 #define SYS_ftruncate 77 +#define SYS_setsid 112 #define SYS_prctl 157 #define SYS_futex 202 #define SYS_getdents64 217 diff --git a/platform_linux_common.c b/platform_linux_common.c @@ -35,6 +35,7 @@ #define WNOHANG 1 #define W_IF_EXITED(s) (!((s) & 0x7F)) +#define TIOCSCTTY 0x540E #define TIOCSWINSZ 0x5414 #define TIOCSPTLCK 0x145431 /* (un)lock pty */ #define TIOCGPTN 0x245430 /* get pty number */