vtgl

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

Commit: a5a679470ba738a710e43b04dfc5de04f6361c1d
Parent: 9cfa730cbaf2d69ddb25dd22c2230b11fd36c151
Author: Randy Palamar
Date:   Wed,  4 Dec 2024 18:18:39 -0700

drop unnecessary fcntl call in fork_child

Since we are opening the file descriptor ourselves we can just set
the flags we want to begin with.

Diffstat:
Mos_unix.c | 47++---------------------------------------------
Mplatform_linux_common.c | 43+++++++++++++++++++++++++++++++++++++++++--
2 files changed, 43 insertions(+), 47 deletions(-)

diff --git a/os_unix.c b/os_unix.c @@ -1,10 +1,9 @@ /* See LICENSE for copyright details */ -#include <fcntl.h> -#include <pty.h> #include <pwd.h> #include <sys/select.h> #include <unistd.h> +__attribute__((noreturn)) static void execsh(char *defcmd) { @@ -28,47 +27,5 @@ execsh(char *defcmd) execvp(sh, argv); syscall1(SYS_exit_group, 1); -} - -static linux_platform_process -os_fork_child(char *cmd) -{ - 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")); - - 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); - - 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); - } - syscall1(SYS_close, s); - - /* 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(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 = m}; + __builtin_unreachable(); } diff --git a/platform_linux_common.c b/platform_linux_common.c @@ -37,8 +37,8 @@ #define TIOCSCTTY 0x540E #define TIOCSWINSZ 0x5414 -#define TIOCSPTLCK 0x145431 /* (un)lock pty */ -#define TIOCGPTN 0x245430 /* get pty number */ +#define TIOCSPTLCK 0x40045431 /* (un)lock pty */ +#define TIOCGPTN 0x80045430 /* get pty number */ #ifndef VERSION #define VERSION "unknown" @@ -289,6 +289,45 @@ os_child_exited(iptr pid) return r == pid && W_IF_EXITED(status); } +static void execsh(char *); +static linux_platform_process +os_fork_child(char *cmd) +{ + i32 n = 0; + + /* NOTE: we open in non-blocking mode so that we can try and fully drain the pipe + * before processing. Otherwise a single read will be limited to the page size */ + i64 m = syscall3(SYS_open, (iptr)"/dev/ptmx", O_RDWR|O_NOCTTY|O_NONBLOCK|O_CLOEXEC, 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")); + + 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); + + 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_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); + } + syscall1(SYS_close, s); + + return (linux_platform_process){.process_id = pid, .handle = m}; +} + static PLATFORM_SET_TERMINAL_SIZE_FN(os_set_terminal_size) { u16 win_size[4];