diff --git a/kernel-src/include/kernel/tty.h b/kernel-src/include/kernel/tty.h index 324199a2..6e4ae649 100644 --- a/kernel-src/include/kernel/tty.h +++ b/kernel-src/include/kernel/tty.h @@ -12,6 +12,7 @@ typedef size_t (*ttydevicewritefn_t)(void *internal, char *str, size_t size); typedef void (*ttyinactivefn_t)(void *internal); +typedef int (*tty_hup_check_t)(void *internal); typedef void (*tty_termios_callback_t)(void *internal, termios_t *termios); typedef struct { @@ -27,6 +28,7 @@ typedef struct { ttydevicewritefn_t writetodevice; ttyinactivefn_t inactivedevice; tty_termios_callback_t termios_callback; + tty_hup_check_t hup_check; int minor; winsize_t winsize; vnode_t *mastervnode; @@ -35,7 +37,7 @@ typedef struct { } tty_t; void tty_init(); -tty_t *tty_create(char *name, ttydevicewritefn_t writefn, ttyinactivefn_t inactivefn, tty_termios_callback_t termios_callback, void *internal); +tty_t *tty_create(char *name, ttydevicewritefn_t writefn, ttyinactivefn_t inactivefn, tty_termios_callback_t termios_callback, tty_hup_check_t hup_check, void *internal); void tty_process(tty_t *tty, char c); void tty_unregister(tty_t *tty); int tty_ioctl(tty_t *tty, unsigned long req, void *arg, int *result, cred_t *cred); diff --git a/kernel-src/io/console.c b/kernel-src/io/console.c index 35b55f42..691305cd 100644 --- a/kernel-src/io/console.c +++ b/kernel-src/io/console.c @@ -115,7 +115,7 @@ void console_init() { __assert(thread); sched_queue(thread); - tty = tty_create("console", console_ttywrite, NULL, NULL, NULL); + tty = tty_create("console", console_ttywrite, NULL, NULL, NULL, NULL); __assert(tty); size_t x, y, fbx, fby; diff --git a/kernel-src/io/pty.c b/kernel-src/io/pty.c index 1bec027e..6800f5f3 100644 --- a/kernel-src/io/pty.c +++ b/kernel-src/io/pty.c @@ -81,6 +81,12 @@ static size_t writetopty(void *_pty, char *data, size_t size) { return written; } +// TODO: signal hup to the tty +static int hup_check(void *_pty) { + pty_t *pty = _pty; + return pty->hangup; +} + static void inactivepty(void *_pty) { pty_t *pty = _pty; freeptyminor(pty->minor); @@ -186,6 +192,7 @@ static int poll(int minor, polldata_t *data, int events) { return revents; } #define TIOCGPTN 0x80045430 +#define TIOCSPTLCK 0x13376167 static int ioctl(int minor, unsigned long request, void *_arg, int *result, cred_t *cred) { pty_t *pty = ptyget(minor); if (pty == NULL) @@ -195,6 +202,9 @@ static int ioctl(int minor, unsigned long request, void *_arg, int *result, cred case TIOCGPTN: { return USERCOPY_POSSIBLY_TO_USER(_arg, &pty->minor, sizeof(int)); } + case TIOCSPTLCK: { + break; // no-op + } default: return tty_ioctl(pty->tty, request, _arg, result, cred); } @@ -266,7 +276,7 @@ static int open(int oldminor, vnode_t **vnode, int flags) { // create a pairing slave device snprintf(tmpname, 20, "pts/%d", newminor); - pty->tty = tty_create(tmpname, writetopty, inactivepty, NULL, pty); + pty->tty = tty_create(tmpname, writetopty, inactivepty, NULL, hup_check, pty); if (pty->tty == NULL) { VOP_RELEASE(pty->mastervnode); return ENOMEM; diff --git a/kernel-src/io/serial/pc_com.c b/kernel-src/io/serial/pc_com.c index 289b2207..886d1493 100644 --- a/kernel-src/io/serial/pc_com.c +++ b/kernel-src/io/serial/pc_com.c @@ -266,7 +266,7 @@ static uacpi_iteration_decision init_com(void *, uacpi_namespace_node *node, uns char tty_name[10]; snprintf(tty_name, 10, "com%d", pc_com->id); - pc_com->tty = tty_create(tty_name, write_tty, NULL, termios_callback, pc_com); + pc_com->tty = tty_create(tty_name, write_tty, NULL, termios_callback, NULL, pc_com); if (pc_com->tty == NULL) { printf("%s: failed to create tty\n", tty_name); return UACPI_ITERATION_DECISION_NEXT_PEER; diff --git a/kernel-src/io/tty.c b/kernel-src/io/tty.c index 1f283898..a15a8597 100644 --- a/kernel-src/io/tty.c +++ b/kernel-src/io/tty.c @@ -168,6 +168,9 @@ static int internalpoll(tty_t *tty, polldata_t *data, int events) { MUTEX_ACQUIRE(&tty->readmutex); + if (tty->hup_check && tty->hup_check(tty->deviceinternal)) + revents |= POLLHUP | (events & POLLIN); + if ((events & POLLIN) && RINGBUFFER_DATACOUNT(&tty->readbuffer)) revents |= POLLIN; @@ -484,7 +487,7 @@ static devops_t devops = { .inactive = inactive }; -tty_t *tty_create(char *name, ttydevicewritefn_t writefn, ttyinactivefn_t inactivefn, tty_termios_callback_t termios_callback, void *internal) { +tty_t *tty_create(char *name, ttydevicewritefn_t writefn, ttyinactivefn_t inactivefn, tty_termios_callback_t termios_callback, tty_hup_check_t hup_check, void *internal) { tty_t *tty = alloc(sizeof(tty_t)); if (tty == NULL) return NULL; diff --git a/kernel-src/sys/syscalls/ioctl.c b/kernel-src/sys/syscalls/ioctl.c index b7b91f0c..6ff839d5 100644 --- a/kernel-src/sys/syscalls/ioctl.c +++ b/kernel-src/sys/syscalls/ioctl.c @@ -8,7 +8,10 @@ syscallret_t syscall_ioctl(context_t *, int fd, unsigned long request, void *arg .ret = -1 }; - if (IS_USER_ADDRESS(arg) == false) { + // arg could be null for, say, an ioctl that does not pass an argument + // this is safe as any accesses on ioctls are done through user copy, which + // returns EFAULT on a null access + if (arg != NULL && IS_USER_ADDRESS(arg) == false) { ret.errno = EFAULT; return ret; }