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
This commit is contained in:
David van Moolenbroek 2017-02-15 19:27:45 +00:00
parent d7c7182ad4
commit e6dabba58b

View File

@ -82,6 +82,7 @@ typedef struct pty {
#define TTY_CLOSED 0x04 /* tty side has closed down */ #define TTY_CLOSED 0x04 /* tty side has closed down */
#define PTY_CLOSED 0x08 /* pty side has closed down */ #define PTY_CLOSED 0x08 /* pty side has closed down */
#define PTY_UNIX98 0x10 /* pty pair is Unix98 */ #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 */ 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; uid_t uid;
struct ptmget pm; struct ptmget pm;
size_t len; size_t len;
int r, val;
if ((tp = line2tty(minor)) == NULL) if ((tp = line2tty(minor)) == NULL)
return ENXIO; return ENXIO;
@ -386,6 +388,18 @@ static int pty_master_ioctl(devminor_t minor, unsigned long request,
return EINVAL; return EINVAL;
return sys_safecopyto(endpt, grant, 0, (vir_bytes)&pm, sizeof(pm)); 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 /* 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. */ /* Transfer bytes written to the output buffer to the PTY reader. */
int count; int count;
char c;
/* While there are things to do. */ /* While there are things to do. */
for (;;) { for (;;) {
int s;
count = bufend(pp->obuf) - pp->otail; count = bufend(pp->obuf) - pp->otail;
if (count > pp->ocount) count = pp->ocount; 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 > pp->rdleft) count = pp->rdleft;
if (count == 0) break; if (count == 0) break;
/* Copy from the output buffer to the readers address space. */ /* Copy from the output buffer to the readers address space. */
if((s = sys_safecopyto(pp->rdcaller, pp->rdgrant, pp->rdcum, if (sys_safecopyto(pp->rdcaller, pp->rdgrant, pp->rdcum,
(vir_bytes) pp->otail, count)) != OK) { (vir_bytes)pp->otail, count) != OK)
break; break;
}
/* Bookkeeping. */ /* Bookkeeping. */
pp->ocount -= count; pp->ocount -= count;