Commit: 9cfa730cbaf2d69ddb25dd22c2230b11fd36c151
Parent: b14e800a97c108805665b3a769d834a40463ea59
Author: Randy Palamar
Date: Wed, 4 Dec 2024 07:53:47 -0700
replace forkpty
Diffstat:
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 */