From e6dabba58b8472f95e59c6a720793cc11c3b41fe Mon Sep 17 00:00:00 2001 From: David van Moolenbroek Date: Wed, 15 Feb 2017 19:27:45 +0000 Subject: [PATCH] PTY: add minimal support for TIOCPKT With TIOCPKT enabled, each piece of output is preceded by a zero byte on the PTY master. In addition, a non-zero byte is a flags field that conveys information about changes on the pseudoterminal. This patch implements the former, but not the latter. That is enough to get telnetd(8) going, however. TIOCPKT support may be extended later. Change-Id: I6ef9cc8cf1b4406147b088400fc8499684b62a30 --- minix/drivers/tty/pty/pty.c | 38 +++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/minix/drivers/tty/pty/pty.c b/minix/drivers/tty/pty/pty.c index 1a6b55696..9a1ec7a0e 100644 --- a/minix/drivers/tty/pty/pty.c +++ b/minix/drivers/tty/pty/pty.c @@ -82,6 +82,7 @@ typedef struct pty { #define TTY_CLOSED 0x04 /* tty side has closed down */ #define PTY_CLOSED 0x08 /* pty side has closed down */ #define PTY_UNIX98 0x10 /* pty pair is Unix98 */ +#define PTY_PKTMODE 0x20 /* pty side is in packet mode (TIOCPKT) */ static pty_t pty_table[NR_PTYS]; /* PTY bookkeeping */ @@ -347,6 +348,7 @@ static int pty_master_ioctl(devminor_t minor, unsigned long request, uid_t uid; struct ptmget pm; size_t len; + int r, val; if ((tp = line2tty(minor)) == NULL) return ENXIO; @@ -386,6 +388,18 @@ static int pty_master_ioctl(devminor_t minor, unsigned long request, return EINVAL; return sys_safecopyto(endpt, grant, 0, (vir_bytes)&pm, sizeof(pm)); + + case TIOCPKT: + r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes)&val, sizeof(val)); + if (r != OK) + return r; + + if (val) + pp->state |= PTY_PKTMODE; + else + pp->state &= ~PTY_PKTMODE; + + return OK; } /* TODO: historically, all IOCTLs on the master are processed as if issued on @@ -608,20 +622,36 @@ static void pty_start(pty_t *pp) { /* Transfer bytes written to the output buffer to the PTY reader. */ int count; + char c; /* While there are things to do. */ for (;;) { - int s; count = bufend(pp->obuf) - pp->otail; if (count > pp->ocount) count = pp->ocount; + if (count == 0 || pp->rdleft == 0) break; + + /* If there is output at all, and packet mode is enabled, then prepend + * the output with a zero byte. This is absolutely minimal "support" + * for the TIOCPKT receipt mode to get telnetd(8) going. Implementing + * full support for all the TIOCPKT bits will require more work. + */ + if (pp->rdcum == 0 && (pp->state & PTY_PKTMODE)) { + c = 0; + if (sys_safecopyto(pp->rdcaller, pp->rdgrant, 0, (vir_bytes)&c, + sizeof(c)) != OK) + break; + + pp->rdcum++; + pp->rdleft--; + } + if (count > pp->rdleft) count = pp->rdleft; if (count == 0) break; /* Copy from the output buffer to the readers address space. */ - if((s = sys_safecopyto(pp->rdcaller, pp->rdgrant, pp->rdcum, - (vir_bytes) pp->otail, count)) != OK) { + if (sys_safecopyto(pp->rdcaller, pp->rdgrant, pp->rdcum, + (vir_bytes)pp->otail, count) != OK) break; - } /* Bookkeeping. */ pp->ocount -= count; -- 2.44.0