Add a BSD implementation

This commit is contained in:
Patrick Böker 2025-11-04 21:12:15 +01:00
parent 902cbf5760
commit 23657f7791
2 changed files with 68 additions and 40 deletions

View File

@ -38,6 +38,13 @@
#include <poll.h>
#include <termios.h>
#if defined(__DragonFly__) || \
defined(__FreeBSD__) || \
defined(__NetBSD__) || \
defined(__OpenBSD__)
#include <util.h>
#endif
#if defined(__APPLE__)
# include <spawn.h>
# include <paths.h>
@ -996,47 +1003,63 @@ int uv__pty_resize_fd(int pty_fd,
return 0;
}
/* The BSDs don't have ptsname_r. They do have ptsname, but that's not
* reentrant. The obvious alternative is openpty.
*/
#if defined(__DragonFly__) || \
defined(__FreeBSD__) || \
defined(__NetBSD__) || \
defined(__OpenBSD__)
int uv__spawn_make_pty(int* fd_pty, int* fd_tty, int cols, int rows) {
int ret;
int my_errno;
*fd_pty = posix_openpt(O_RDWR);
if (*fd_pty < 0)
return UV__ERR(errno);
if (grantpt(*fd_pty) < 0) {
SAVE_ERRNO(close(*fd_pty));
return UV__ERR(errno);
}
if (unlockpt(*fd_pty) < 0) {
SAVE_ERRNO(close(*fd_pty));
return UV__ERR(errno);
}
char path_tty[TTY_NAME_MAX + 1] = {0};
// Apple and linux both have ptsname_r.
// Use TIOCGPTPEER. (see man ioctl_tty) Where is that available?
// TODO(patrickbkr): There is no ptsname_r on OpenBSD.
if (ptsname_r(*fd_pty, path_tty, TTY_NAME_MAX + 1) != 0) {
SAVE_ERRNO(close(*fd_pty));
return UV__ERR(errno);
}
*fd_tty = open(path_tty, O_RDWR | O_NOCTTY);
if (*fd_tty < 0) {
SAVE_ERRNO(close(*fd_pty));
return UV__ERR(errno);
}
if ((my_errno = uv__pty_resize_fd(*fd_pty, cols, rows)) != 0) {
close(*fd_pty);
close(*fd_tty);
return my_errno;
}
return 0;
struct winsize winp;
memset(&winp, 0, sizeof(winp));
winp.ws_col = cols;
winp.ws_row = rows;
if (openpty(fd_pty, fd_tty, 0, 0, &winp) < 0) {
return UV__ERR(errno);
}
return 0;
}
#else
int uv__spawn_make_pty(int* fd_pty, int* fd_tty, int cols, int rows) {
int ret;
int my_errno;
*fd_pty = posix_openpt(O_RDWR);
if (*fd_pty < 0)
return UV__ERR(errno);
if (grantpt(*fd_pty) < 0) {
SAVE_ERRNO(close(*fd_pty));
return UV__ERR(errno);
}
if (unlockpt(*fd_pty) < 0) {
SAVE_ERRNO(close(*fd_pty));
return UV__ERR(errno);
}
char path_tty[TTY_NAME_MAX + 1] = {0};
if (ptsname_r(*fd_pty, path_tty, TTY_NAME_MAX + 1) != 0) {
SAVE_ERRNO(close(*fd_pty));
return UV__ERR(errno);
}
*fd_tty = open(path_tty, O_RDWR | O_NOCTTY);
if (*fd_tty < 0) {
SAVE_ERRNO(close(*fd_pty));
return UV__ERR(errno);
}
if ((my_errno = uv__pty_resize_fd(*fd_pty, cols, rows)) != 0) {
close(*fd_pty);
close(*fd_tty);
return my_errno;
}
return 0;
}
#endif
int uv_spawn(uv_loop_t* loop,
uv_process_t* process,

View File

@ -152,7 +152,12 @@ static void pty_on_read(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) {
if (nread > 0) {
output_used += nread;
} else if (nread < 0) {
#if defined(_WIN32) || defined(__APPLE__)
#if defined(_WIN32) || \
defined(__APPLE__) || \
defined(__DragonFly__) || \
defined(__FreeBSD__) || \
defined(__NetBSD__) || \
defined(__OpenBSD__)
ASSERT_EQ(nread, UV_EOF);
#elif defined(__ANDROID__)
ASSERT(nread == UV_EIO || nread == UV_EOF);