2005-04-21 16:53:53 +02:00
|
|
|
/* pty.c - pseudo terminal driver Author: Kees J. Bot
|
|
|
|
* 30 Dec 1995
|
|
|
|
* PTYs can be seen as a bidirectional pipe with TTY
|
|
|
|
* input and output processing. For example a simple rlogin session:
|
|
|
|
*
|
|
|
|
* keyboard -> rlogin -> in.rld -> /dev/ptypX -> /dev/ttypX -> shell
|
|
|
|
* shell -> /dev/ttypX -> /dev/ptypX -> in.rld -> rlogin -> screen
|
|
|
|
*
|
|
|
|
* This file takes care of copying data between the tty/pty device pairs and
|
|
|
|
* the open/read/write/close calls on the pty devices. The TTY task takes
|
|
|
|
* care of the input and output processing (interrupt, backspace, raw I/O,
|
|
|
|
* etc.) using the pty_read() and pty_write() functions as the "keyboard" and
|
|
|
|
* "screen" functions of the ttypX devices.
|
|
|
|
* Be careful when reading this code, the terms "reading" and "writing" are
|
|
|
|
* used both for the tty and the pty end of the pseudo tty. Writes to one
|
|
|
|
* end are to be read at the other end and vice-versa.
|
|
|
|
*/
|
|
|
|
|
2010-03-22 22:25:22 +01:00
|
|
|
#include <minix/drivers.h>
|
2005-08-01 16:40:21 +02:00
|
|
|
#include <assert.h>
|
2005-04-21 16:53:53 +02:00
|
|
|
#include <termios.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <minix/com.h>
|
|
|
|
#include <minix/callnr.h>
|
2005-08-05 15:50:58 +02:00
|
|
|
#include <sys/select.h>
|
2005-04-21 16:53:53 +02:00
|
|
|
#include "tty.h"
|
|
|
|
|
|
|
|
#if NR_PTYS > 0
|
|
|
|
|
|
|
|
/* PTY bookkeeping structure, one per pty/tty pair. */
|
|
|
|
typedef struct pty {
|
|
|
|
tty_t *tty; /* associated TTY structure */
|
|
|
|
char state; /* flags: busy, closed, ... */
|
|
|
|
|
|
|
|
/* Read call on /dev/ptypX. */
|
2005-08-01 16:40:21 +02:00
|
|
|
char rdsendreply; /* send a reply (instead of notify) */
|
2006-03-03 11:21:45 +01:00
|
|
|
int rdcaller; /* process making the call (usually FS) */
|
|
|
|
int rdproc; /* process that wants to read from the pty */
|
2011-03-25 11:43:24 +01:00
|
|
|
cp_grant_id_t rdgrant; /* grant for readers address space */
|
|
|
|
vir_bytes rdoffset; /* offset in above grant */
|
2005-04-21 16:53:53 +02:00
|
|
|
int rdleft; /* # bytes yet to be read */
|
|
|
|
int rdcum; /* # bytes written so far */
|
|
|
|
|
|
|
|
/* Write call to /dev/ptypX. */
|
2005-08-01 16:40:21 +02:00
|
|
|
char wrsendreply; /* send a reply (instead of notify) */
|
2006-03-03 11:21:45 +01:00
|
|
|
int wrcaller; /* process making the call (usually FS) */
|
|
|
|
int wrproc; /* process that wants to write to the pty */
|
2011-03-25 11:43:24 +01:00
|
|
|
cp_grant_id_t wrgrant; /* grant for writers address space */
|
|
|
|
vir_bytes wroffset; /* offset in above grant */
|
2005-04-21 16:53:53 +02:00
|
|
|
int wrleft; /* # bytes yet to be written */
|
|
|
|
int wrcum; /* # bytes written so far */
|
|
|
|
|
|
|
|
/* Output buffer. */
|
|
|
|
int ocount; /* # characters in the buffer */
|
|
|
|
char *ohead, *otail; /* head and tail of the circular buffer */
|
2006-06-20 11:02:54 +02:00
|
|
|
char obuf[2048]; /* buffer for bytes going to the pty reader */
|
2005-08-05 15:50:58 +02:00
|
|
|
|
|
|
|
/* select() data. */
|
|
|
|
int select_ops, /* Which operations do we want to know about? */
|
|
|
|
select_proc, /* Who wants to know about it? */
|
|
|
|
select_ready_ops; /* For callback. */
|
2005-04-21 16:53:53 +02:00
|
|
|
} pty_t;
|
|
|
|
|
|
|
|
#define PTY_ACTIVE 0x01 /* pty is open/active */
|
|
|
|
#define TTY_CLOSED 0x02 /* tty side has closed down */
|
|
|
|
#define PTY_CLOSED 0x04 /* pty side has closed down */
|
|
|
|
|
2012-03-25 20:25:53 +02:00
|
|
|
static pty_t pty_table[NR_PTYS]; /* PTY bookkeeping */
|
|
|
|
|
|
|
|
static int pty_write(tty_t *tp, int try);
|
|
|
|
static void pty_echo(tty_t *tp, int c);
|
|
|
|
static void pty_start(pty_t *pp);
|
|
|
|
static void pty_finish(pty_t *pp);
|
|
|
|
static int pty_read(tty_t *tp, int try);
|
|
|
|
static int pty_close(tty_t *tp, int try);
|
|
|
|
static int pty_icancel(tty_t *tp, int try);
|
|
|
|
static int pty_ocancel(tty_t *tp, int try);
|
|
|
|
static int pty_select(tty_t *tp, message *m);
|
2005-04-21 16:53:53 +02:00
|
|
|
|
2005-09-11 19:09:11 +02:00
|
|
|
/*===========================================================================*
|
|
|
|
* do_pty *
|
|
|
|
*===========================================================================*/
|
2012-03-25 20:25:53 +02:00
|
|
|
void do_pty(tty_t *tp, message *m_ptr)
|
2005-04-21 16:53:53 +02:00
|
|
|
{
|
|
|
|
/* Perform an open/close/read/write call on a /dev/ptypX device. */
|
|
|
|
pty_t *pp = tp->tty_priv;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
switch (m_ptr->m_type) {
|
2006-06-20 11:02:54 +02:00
|
|
|
case DEV_READ_S:
|
2005-04-21 16:53:53 +02:00
|
|
|
/* Check, store information on the reader, do I/O. */
|
|
|
|
if (pp->state & TTY_CLOSED) {
|
|
|
|
r = 0;
|
|
|
|
break;
|
|
|
|
}
|
2005-08-01 16:40:21 +02:00
|
|
|
if (pp->rdleft != 0 || pp->rdcum != 0) {
|
2005-04-21 16:53:53 +02:00
|
|
|
r = EIO;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (m_ptr->COUNT <= 0) {
|
|
|
|
r = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
2012-04-04 15:46:34 +02:00
|
|
|
if (pp->rdgrant != GRANT_INVALID) {
|
|
|
|
r = ENOBUFS;
|
|
|
|
break;
|
|
|
|
}
|
2005-08-01 16:40:21 +02:00
|
|
|
pp->rdsendreply = TRUE;
|
2005-04-21 16:53:53 +02:00
|
|
|
pp->rdcaller = m_ptr->m_source;
|
Server/driver protocols: no longer allow third-party copies.
Before safecopies, the IO_ENDPT and DL_ENDPT message fields were needed
to know which actual process to copy data from/to, as that process may
not always be the caller. Now that we have full safecopy support, these
fields have become useless for that purpose: the owner of the grant is
*always* the caller. Allowing the caller to supply another endpoint is
in fact dangerous, because the callee may then end up using a grant
from a third party. One could call this a variant of the confused
deputy problem.
From now on, safecopy calls should always use the caller's endpoint as
grant owner. This fully obsoletes the DL_ENDPT field in the
inet/ethernet protocol. IO_ENDPT has other uses besides identifying the
grant owner though. This patch renames IO_ENDPT to USER_ENDPT, not only
because that is a more fitting name (it should never be used for I/O
after all), but also in order to intentionally break any old system
source code outside the base system. If this patch breaks your code,
fixing it is fairly simple:
- DL_ENDPT should be replaced with m_source;
- IO_ENDPT should be replaced with m_source when used for safecopies;
- IO_ENDPT should be replaced with USER_ENDPT for any other use, e.g.
when setting REP_ENDPT, matching requests in CANCEL calls, getting
DEV_SELECT flags, and retrieving of the real user process's endpoint
in DEV_OPEN.
The changes in this patch are binary backward compatible.
2011-04-11 19:35:05 +02:00
|
|
|
pp->rdproc = m_ptr->USER_ENDPT;
|
2011-03-25 11:43:24 +01:00
|
|
|
pp->rdgrant = (cp_grant_id_t) m_ptr->IO_GRANT;
|
|
|
|
pp->rdoffset = 0;
|
2005-04-21 16:53:53 +02:00
|
|
|
pp->rdleft = m_ptr->COUNT;
|
|
|
|
pty_start(pp);
|
|
|
|
handle_events(tp);
|
2006-06-20 11:02:54 +02:00
|
|
|
if (pp->rdleft == 0) {
|
2012-04-04 15:46:34 +02:00
|
|
|
pp->rdgrant = GRANT_INVALID;
|
2006-06-20 11:02:54 +02:00
|
|
|
return; /* already done */
|
|
|
|
}
|
2005-04-21 16:53:53 +02:00
|
|
|
|
2013-08-30 10:48:34 +02:00
|
|
|
if (m_ptr->FLAGS & FLG_OP_NONBLOCK) {
|
|
|
|
r = pp->rdcum > 0 ? pp->rdcum : EAGAIN;
|
|
|
|
pp->rdleft = pp->rdcum = 0;
|
|
|
|
pp->rdgrant = GRANT_INVALID;
|
|
|
|
} else {
|
2005-04-21 16:53:53 +02:00
|
|
|
r = SUSPEND; /* do suspend */
|
2005-08-01 16:40:21 +02:00
|
|
|
pp->rdsendreply = FALSE;
|
2005-04-21 16:53:53 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2006-06-20 11:02:54 +02:00
|
|
|
case DEV_WRITE_S:
|
2005-04-21 16:53:53 +02:00
|
|
|
/* Check, store information on the writer, do I/O. */
|
|
|
|
if (pp->state & TTY_CLOSED) {
|
|
|
|
r = EIO;
|
|
|
|
break;
|
|
|
|
}
|
2005-08-01 16:40:21 +02:00
|
|
|
if (pp->wrleft != 0 || pp->wrcum != 0) {
|
2005-04-21 16:53:53 +02:00
|
|
|
r = EIO;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (m_ptr->COUNT <= 0) {
|
|
|
|
r = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
2012-04-04 15:46:34 +02:00
|
|
|
if (pp->wrgrant != GRANT_INVALID) {
|
|
|
|
r = ENOBUFS;
|
|
|
|
break;
|
|
|
|
}
|
2005-08-01 16:40:21 +02:00
|
|
|
pp->wrsendreply = TRUE;
|
2005-04-21 16:53:53 +02:00
|
|
|
pp->wrcaller = m_ptr->m_source;
|
Server/driver protocols: no longer allow third-party copies.
Before safecopies, the IO_ENDPT and DL_ENDPT message fields were needed
to know which actual process to copy data from/to, as that process may
not always be the caller. Now that we have full safecopy support, these
fields have become useless for that purpose: the owner of the grant is
*always* the caller. Allowing the caller to supply another endpoint is
in fact dangerous, because the callee may then end up using a grant
from a third party. One could call this a variant of the confused
deputy problem.
From now on, safecopy calls should always use the caller's endpoint as
grant owner. This fully obsoletes the DL_ENDPT field in the
inet/ethernet protocol. IO_ENDPT has other uses besides identifying the
grant owner though. This patch renames IO_ENDPT to USER_ENDPT, not only
because that is a more fitting name (it should never be used for I/O
after all), but also in order to intentionally break any old system
source code outside the base system. If this patch breaks your code,
fixing it is fairly simple:
- DL_ENDPT should be replaced with m_source;
- IO_ENDPT should be replaced with m_source when used for safecopies;
- IO_ENDPT should be replaced with USER_ENDPT for any other use, e.g.
when setting REP_ENDPT, matching requests in CANCEL calls, getting
DEV_SELECT flags, and retrieving of the real user process's endpoint
in DEV_OPEN.
The changes in this patch are binary backward compatible.
2011-04-11 19:35:05 +02:00
|
|
|
pp->wrproc = m_ptr->USER_ENDPT;
|
2011-03-25 11:43:24 +01:00
|
|
|
pp->wrgrant = (cp_grant_id_t) m_ptr->IO_GRANT;
|
|
|
|
pp->wroffset = 0;
|
2005-04-21 16:53:53 +02:00
|
|
|
pp->wrleft = m_ptr->COUNT;
|
|
|
|
handle_events(tp);
|
2006-06-20 11:02:54 +02:00
|
|
|
if (pp->wrleft == 0) {
|
2012-04-04 15:46:34 +02:00
|
|
|
pp->wrgrant = GRANT_INVALID;
|
2006-06-20 11:02:54 +02:00
|
|
|
return; /* already done */
|
|
|
|
}
|
2005-04-21 16:53:53 +02:00
|
|
|
|
2013-08-30 10:48:34 +02:00
|
|
|
if (m_ptr->FLAGS & FLG_OP_NONBLOCK) {
|
|
|
|
r = pp->wrcum > 0 ? pp->wrcum : EAGAIN;
|
|
|
|
pp->wrleft = pp->wrcum = 0;
|
|
|
|
pp->wrgrant = GRANT_INVALID;
|
|
|
|
r = EAGAIN;
|
|
|
|
} else {
|
2005-08-01 16:40:21 +02:00
|
|
|
pp->wrsendreply = FALSE; /* do suspend */
|
2005-04-21 16:53:53 +02:00
|
|
|
r = SUSPEND;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEV_OPEN:
|
|
|
|
r = pp->state != 0 ? EIO : OK;
|
|
|
|
pp->state |= PTY_ACTIVE;
|
2005-08-01 16:40:21 +02:00
|
|
|
pp->rdcum = 0;
|
|
|
|
pp->wrcum = 0;
|
2005-04-21 16:53:53 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DEV_CLOSE:
|
|
|
|
r = OK;
|
|
|
|
if (pp->state & TTY_CLOSED) {
|
|
|
|
pp->state = 0;
|
|
|
|
} else {
|
|
|
|
pp->state |= PTY_CLOSED;
|
2009-04-06 11:39:42 +02:00
|
|
|
sigchar(tp, SIGHUP, 1);
|
2005-04-21 16:53:53 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2005-08-05 15:50:58 +02:00
|
|
|
case DEV_SELECT:
|
|
|
|
r = pty_select(tp, m_ptr);
|
|
|
|
break;
|
|
|
|
|
2005-04-21 16:53:53 +02:00
|
|
|
case CANCEL:
|
2006-06-20 11:02:54 +02:00
|
|
|
r = EINTR;
|
Server/driver protocols: no longer allow third-party copies.
Before safecopies, the IO_ENDPT and DL_ENDPT message fields were needed
to know which actual process to copy data from/to, as that process may
not always be the caller. Now that we have full safecopy support, these
fields have become useless for that purpose: the owner of the grant is
*always* the caller. Allowing the caller to supply another endpoint is
in fact dangerous, because the callee may then end up using a grant
from a third party. One could call this a variant of the confused
deputy problem.
From now on, safecopy calls should always use the caller's endpoint as
grant owner. This fully obsoletes the DL_ENDPT field in the
inet/ethernet protocol. IO_ENDPT has other uses besides identifying the
grant owner though. This patch renames IO_ENDPT to USER_ENDPT, not only
because that is a more fitting name (it should never be used for I/O
after all), but also in order to intentionally break any old system
source code outside the base system. If this patch breaks your code,
fixing it is fairly simple:
- DL_ENDPT should be replaced with m_source;
- IO_ENDPT should be replaced with m_source when used for safecopies;
- IO_ENDPT should be replaced with USER_ENDPT for any other use, e.g.
when setting REP_ENDPT, matching requests in CANCEL calls, getting
DEV_SELECT flags, and retrieving of the real user process's endpoint
in DEV_OPEN.
The changes in this patch are binary backward compatible.
2011-04-11 19:35:05 +02:00
|
|
|
if (m_ptr->USER_ENDPT == pp->rdproc) {
|
2005-04-21 16:53:53 +02:00
|
|
|
/* Cancel a read from a PTY. */
|
2006-06-20 11:02:54 +02:00
|
|
|
r = pp->rdcum > 0 ? pp->rdcum : EAGAIN;
|
2005-04-21 16:53:53 +02:00
|
|
|
pp->rdleft = pp->rdcum = 0;
|
2012-04-04 15:46:34 +02:00
|
|
|
pp->rdgrant = GRANT_INVALID;
|
2005-04-21 16:53:53 +02:00
|
|
|
}
|
Server/driver protocols: no longer allow third-party copies.
Before safecopies, the IO_ENDPT and DL_ENDPT message fields were needed
to know which actual process to copy data from/to, as that process may
not always be the caller. Now that we have full safecopy support, these
fields have become useless for that purpose: the owner of the grant is
*always* the caller. Allowing the caller to supply another endpoint is
in fact dangerous, because the callee may then end up using a grant
from a third party. One could call this a variant of the confused
deputy problem.
From now on, safecopy calls should always use the caller's endpoint as
grant owner. This fully obsoletes the DL_ENDPT field in the
inet/ethernet protocol. IO_ENDPT has other uses besides identifying the
grant owner though. This patch renames IO_ENDPT to USER_ENDPT, not only
because that is a more fitting name (it should never be used for I/O
after all), but also in order to intentionally break any old system
source code outside the base system. If this patch breaks your code,
fixing it is fairly simple:
- DL_ENDPT should be replaced with m_source;
- IO_ENDPT should be replaced with m_source when used for safecopies;
- IO_ENDPT should be replaced with USER_ENDPT for any other use, e.g.
when setting REP_ENDPT, matching requests in CANCEL calls, getting
DEV_SELECT flags, and retrieving of the real user process's endpoint
in DEV_OPEN.
The changes in this patch are binary backward compatible.
2011-04-11 19:35:05 +02:00
|
|
|
if (m_ptr->USER_ENDPT == pp->wrproc) {
|
2005-04-21 16:53:53 +02:00
|
|
|
/* Cancel a write to a PTY. */
|
2006-06-20 11:02:54 +02:00
|
|
|
r = pp->wrcum > 0 ? pp->wrcum : EAGAIN;
|
2005-04-21 16:53:53 +02:00
|
|
|
pp->wrleft = pp->wrcum = 0;
|
2012-04-04 15:46:34 +02:00
|
|
|
pp->wrgrant = GRANT_INVALID;
|
2005-04-21 16:53:53 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
r = EINVAL;
|
|
|
|
}
|
Server/driver protocols: no longer allow third-party copies.
Before safecopies, the IO_ENDPT and DL_ENDPT message fields were needed
to know which actual process to copy data from/to, as that process may
not always be the caller. Now that we have full safecopy support, these
fields have become useless for that purpose: the owner of the grant is
*always* the caller. Allowing the caller to supply another endpoint is
in fact dangerous, because the callee may then end up using a grant
from a third party. One could call this a variant of the confused
deputy problem.
From now on, safecopy calls should always use the caller's endpoint as
grant owner. This fully obsoletes the DL_ENDPT field in the
inet/ethernet protocol. IO_ENDPT has other uses besides identifying the
grant owner though. This patch renames IO_ENDPT to USER_ENDPT, not only
because that is a more fitting name (it should never be used for I/O
after all), but also in order to intentionally break any old system
source code outside the base system. If this patch breaks your code,
fixing it is fairly simple:
- DL_ENDPT should be replaced with m_source;
- IO_ENDPT should be replaced with m_source when used for safecopies;
- IO_ENDPT should be replaced with USER_ENDPT for any other use, e.g.
when setting REP_ENDPT, matching requests in CANCEL calls, getting
DEV_SELECT flags, and retrieving of the real user process's endpoint
in DEV_OPEN.
The changes in this patch are binary backward compatible.
2011-04-11 19:35:05 +02:00
|
|
|
tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->USER_ENDPT, r);
|
2005-04-21 16:53:53 +02:00
|
|
|
}
|
|
|
|
|
2005-09-11 19:09:11 +02:00
|
|
|
/*===========================================================================*
|
|
|
|
* pty_write *
|
|
|
|
*===========================================================================*/
|
2012-03-25 20:25:53 +02:00
|
|
|
static int pty_write(tty_t *tp, int try)
|
2005-04-21 16:53:53 +02:00
|
|
|
{
|
|
|
|
/* (*dev_write)() routine for PTYs. Transfer bytes from the writer on
|
|
|
|
* /dev/ttypX to the output buffer.
|
|
|
|
*/
|
|
|
|
pty_t *pp = tp->tty_priv;
|
2005-05-09 16:35:26 +02:00
|
|
|
int count, ocount, s;
|
2008-11-19 13:26:10 +01:00
|
|
|
|
2005-04-21 16:53:53 +02:00
|
|
|
|
|
|
|
/* PTY closed down? */
|
|
|
|
if (pp->state & PTY_CLOSED) {
|
2005-09-11 19:09:11 +02:00
|
|
|
if (try) return 1;
|
2005-04-21 16:53:53 +02:00
|
|
|
if (tp->tty_outleft > 0) {
|
2006-06-20 11:02:54 +02:00
|
|
|
if(tp->tty_outrepcode == TTY_REVIVE) {
|
|
|
|
notify(tp->tty_outcaller);
|
|
|
|
tp->tty_outrevived = 1;
|
|
|
|
} else {
|
|
|
|
tty_reply(tp->tty_outrepcode, tp->tty_outcaller,
|
2005-04-21 16:53:53 +02:00
|
|
|
tp->tty_outproc, EIO);
|
2006-06-20 11:02:54 +02:00
|
|
|
tp->tty_outleft = tp->tty_outcum = 0;
|
|
|
|
}
|
2005-04-21 16:53:53 +02:00
|
|
|
}
|
2008-11-19 13:26:10 +01:00
|
|
|
return 0;
|
2005-04-21 16:53:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* While there is something to do. */
|
|
|
|
for (;;) {
|
|
|
|
ocount = buflen(pp->obuf) - pp->ocount;
|
2005-09-11 19:09:11 +02:00
|
|
|
if (try) return (ocount > 0);
|
2005-04-21 16:53:53 +02:00
|
|
|
count = bufend(pp->obuf) - pp->ohead;
|
|
|
|
if (count > ocount) count = ocount;
|
|
|
|
if (count > tp->tty_outleft) count = tp->tty_outleft;
|
2005-08-05 15:50:58 +02:00
|
|
|
if (count == 0 || tp->tty_inhibited)
|
2005-06-17 15:37:41 +02:00
|
|
|
break;
|
2005-04-21 16:53:53 +02:00
|
|
|
|
|
|
|
/* Copy from user space to the PTY output buffer. */
|
TTY: seperate hardware dependent parts + add new serial driver
.Split TTY in order to support both x86 and ARM.
.Add support for the TI 16750 UARTs on OMAP35x.
.Various other improvements:
.Kernel messages are printed using generic terminal write
functions. That is, they are no longer directly displayed
on the console.
.The console can now be displayed on any terminal. This
is configured by the "console={tty00,tty01,ttyc2,ttyc3,ttyc4}"
boot variable -- basically any valid /dev/tty* terminal.
.Cutify kernel messages with colors. Configured by
"kernelclr={1,2,3,4,5,6,7}" boot variable.
2012-10-17 16:07:53 +02:00
|
|
|
if (tp->tty_outcaller == KERNEL) {
|
|
|
|
/* We're trying to print on kernel's behalf */
|
|
|
|
memcpy(pp->ohead, (void *) tp->tty_outgrant + tp->tty_outoffset,
|
|
|
|
count);
|
|
|
|
} else {
|
|
|
|
if ((s = sys_safecopyfrom(tp->tty_outcaller, tp->tty_outgrant,
|
|
|
|
tp->tty_outoffset, (vir_bytes) pp->ohead,
|
|
|
|
count)) != OK) {
|
|
|
|
break;
|
|
|
|
}
|
2005-05-09 16:35:26 +02:00
|
|
|
}
|
2005-04-21 16:53:53 +02:00
|
|
|
|
|
|
|
/* Perform output processing on the output buffer. */
|
|
|
|
out_process(tp, pp->obuf, pp->ohead, bufend(pp->obuf), &count, &ocount);
|
|
|
|
if (count == 0) break;
|
|
|
|
|
|
|
|
/* Assume echoing messed up by output. */
|
|
|
|
tp->tty_reprint = TRUE;
|
|
|
|
|
|
|
|
/* Bookkeeping. */
|
|
|
|
pp->ocount += ocount;
|
|
|
|
if ((pp->ohead += ocount) >= bufend(pp->obuf))
|
|
|
|
pp->ohead -= buflen(pp->obuf);
|
|
|
|
pty_start(pp);
|
2006-06-20 11:02:54 +02:00
|
|
|
|
2011-03-25 11:43:24 +01:00
|
|
|
tp->tty_outoffset += count;
|
2006-06-20 11:02:54 +02:00
|
|
|
|
2005-04-21 16:53:53 +02:00
|
|
|
tp->tty_outcum += count;
|
|
|
|
if ((tp->tty_outleft -= count) == 0) {
|
|
|
|
/* Output is finished, reply to the writer. */
|
2006-06-20 11:02:54 +02:00
|
|
|
if(tp->tty_outrepcode == TTY_REVIVE) {
|
|
|
|
notify(tp->tty_outcaller);
|
|
|
|
tp->tty_outrevived = 1;
|
|
|
|
} else {
|
|
|
|
tty_reply(tp->tty_outrepcode, tp->tty_outcaller,
|
2005-04-21 16:53:53 +02:00
|
|
|
tp->tty_outproc, tp->tty_outcum);
|
2006-06-20 11:02:54 +02:00
|
|
|
tp->tty_outcum = 0;
|
|
|
|
}
|
2005-04-21 16:53:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
pty_finish(pp);
|
2005-06-17 15:37:41 +02:00
|
|
|
return 1;
|
2005-04-21 16:53:53 +02:00
|
|
|
}
|
|
|
|
|
2005-09-11 19:09:11 +02:00
|
|
|
/*===========================================================================*
|
|
|
|
* pty_echo *
|
|
|
|
*===========================================================================*/
|
2012-03-25 20:25:53 +02:00
|
|
|
static void pty_echo(tty_t *tp, int c)
|
2005-04-21 16:53:53 +02:00
|
|
|
{
|
|
|
|
/* Echo one character. (Like pty_write, but only one character, optionally.) */
|
|
|
|
|
|
|
|
pty_t *pp = tp->tty_priv;
|
|
|
|
int count, ocount;
|
|
|
|
|
|
|
|
ocount = buflen(pp->obuf) - pp->ocount;
|
|
|
|
if (ocount == 0) return; /* output buffer full */
|
|
|
|
count = 1;
|
|
|
|
*pp->ohead = c; /* add one character */
|
|
|
|
|
|
|
|
out_process(tp, pp->obuf, pp->ohead, bufend(pp->obuf), &count, &ocount);
|
|
|
|
if (count == 0) return;
|
|
|
|
|
|
|
|
pp->ocount += ocount;
|
|
|
|
if ((pp->ohead += ocount) >= bufend(pp->obuf)) pp->ohead -= buflen(pp->obuf);
|
|
|
|
pty_start(pp);
|
|
|
|
}
|
|
|
|
|
2005-09-11 19:09:11 +02:00
|
|
|
/*===========================================================================*
|
|
|
|
* pty_start *
|
|
|
|
*===========================================================================*/
|
2012-03-25 20:25:53 +02:00
|
|
|
static void pty_start(pty_t *pp)
|
2005-04-21 16:53:53 +02:00
|
|
|
{
|
|
|
|
/* Transfer bytes written to the output buffer to the PTY reader. */
|
|
|
|
int count;
|
|
|
|
|
|
|
|
/* While there are things to do. */
|
|
|
|
for (;;) {
|
2005-05-09 16:35:26 +02:00
|
|
|
int s;
|
2005-04-21 16:53:53 +02:00
|
|
|
count = bufend(pp->obuf) - pp->otail;
|
|
|
|
if (count > pp->ocount) count = pp->ocount;
|
|
|
|
if (count > pp->rdleft) count = pp->rdleft;
|
|
|
|
if (count == 0) break;
|
|
|
|
|
|
|
|
/* Copy from the output buffer to the readers address space. */
|
Server/driver protocols: no longer allow third-party copies.
Before safecopies, the IO_ENDPT and DL_ENDPT message fields were needed
to know which actual process to copy data from/to, as that process may
not always be the caller. Now that we have full safecopy support, these
fields have become useless for that purpose: the owner of the grant is
*always* the caller. Allowing the caller to supply another endpoint is
in fact dangerous, because the callee may then end up using a grant
from a third party. One could call this a variant of the confused
deputy problem.
From now on, safecopy calls should always use the caller's endpoint as
grant owner. This fully obsoletes the DL_ENDPT field in the
inet/ethernet protocol. IO_ENDPT has other uses besides identifying the
grant owner though. This patch renames IO_ENDPT to USER_ENDPT, not only
because that is a more fitting name (it should never be used for I/O
after all), but also in order to intentionally break any old system
source code outside the base system. If this patch breaks your code,
fixing it is fairly simple:
- DL_ENDPT should be replaced with m_source;
- IO_ENDPT should be replaced with m_source when used for safecopies;
- IO_ENDPT should be replaced with USER_ENDPT for any other use, e.g.
when setting REP_ENDPT, matching requests in CANCEL calls, getting
DEV_SELECT flags, and retrieving of the real user process's endpoint
in DEV_OPEN.
The changes in this patch are binary backward compatible.
2011-04-11 19:35:05 +02:00
|
|
|
if((s = sys_safecopyto(pp->rdcaller, pp->rdgrant,
|
2012-06-16 03:46:15 +02:00
|
|
|
pp->rdoffset, (vir_bytes) pp->otail, count)) != OK) {
|
2006-06-20 11:02:54 +02:00
|
|
|
break;
|
2011-03-25 11:43:24 +01:00
|
|
|
}
|
|
|
|
pp->rdoffset += count;
|
2005-04-21 16:53:53 +02:00
|
|
|
|
|
|
|
/* Bookkeeping. */
|
|
|
|
pp->ocount -= count;
|
|
|
|
if ((pp->otail += count) == bufend(pp->obuf)) pp->otail = pp->obuf;
|
|
|
|
pp->rdcum += count;
|
|
|
|
pp->rdleft -= count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-11 19:09:11 +02:00
|
|
|
/*===========================================================================*
|
|
|
|
* pty_finish *
|
|
|
|
*===========================================================================*/
|
2012-03-25 20:25:53 +02:00
|
|
|
static void pty_finish(pty_t *pp)
|
2005-04-21 16:53:53 +02:00
|
|
|
{
|
|
|
|
/* Finish the read request of a PTY reader if there is at least one byte
|
|
|
|
* transferred.
|
|
|
|
*/
|
|
|
|
if (pp->rdcum > 0) {
|
2005-08-01 16:40:21 +02:00
|
|
|
if (pp->rdsendreply) {
|
|
|
|
tty_reply(TASK_REPLY, pp->rdcaller, pp->rdproc, pp->rdcum);
|
|
|
|
pp->rdleft = pp->rdcum = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
notify(pp->rdcaller);
|
2005-04-21 16:53:53 +02:00
|
|
|
}
|
2005-08-05 15:50:58 +02:00
|
|
|
|
2005-04-21 16:53:53 +02:00
|
|
|
}
|
|
|
|
|
2005-09-11 19:09:11 +02:00
|
|
|
/*===========================================================================*
|
|
|
|
* pty_read *
|
|
|
|
*===========================================================================*/
|
2012-03-25 20:25:53 +02:00
|
|
|
static int pty_read(tty_t *tp, int try)
|
2005-04-21 16:53:53 +02:00
|
|
|
{
|
|
|
|
/* Offer bytes from the PTY writer for input on the TTY. (Do it one byte at
|
|
|
|
* a time, 99% of the writes will be for one byte, so no sense in being smart.)
|
|
|
|
*/
|
|
|
|
pty_t *pp = tp->tty_priv;
|
|
|
|
char c;
|
|
|
|
|
|
|
|
if (pp->state & PTY_CLOSED) {
|
2005-09-11 19:09:11 +02:00
|
|
|
if (try) return 1;
|
2005-04-21 16:53:53 +02:00
|
|
|
if (tp->tty_inleft > 0) {
|
2006-06-20 11:02:54 +02:00
|
|
|
if(tp->tty_inrepcode == TTY_REVIVE) {
|
|
|
|
notify(tp->tty_incaller);
|
|
|
|
tp->tty_inrevived = 1;
|
|
|
|
} else {
|
|
|
|
tty_reply(tp->tty_inrepcode, tp->tty_incaller,
|
|
|
|
tp->tty_inproc, tp->tty_incum);
|
|
|
|
tp->tty_inleft = tp->tty_incum = 0;
|
|
|
|
}
|
2005-04-21 16:53:53 +02:00
|
|
|
}
|
2005-06-17 15:37:41 +02:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2005-09-11 19:09:11 +02:00
|
|
|
if (try) {
|
|
|
|
if (pp->wrleft > 0)
|
2005-06-17 15:37:41 +02:00
|
|
|
return 1;
|
|
|
|
return 0;
|
2005-04-21 16:53:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
while (pp->wrleft > 0) {
|
2005-05-09 16:35:26 +02:00
|
|
|
int s;
|
|
|
|
|
2005-04-21 16:53:53 +02:00
|
|
|
/* Transfer one character to 'c'. */
|
Server/driver protocols: no longer allow third-party copies.
Before safecopies, the IO_ENDPT and DL_ENDPT message fields were needed
to know which actual process to copy data from/to, as that process may
not always be the caller. Now that we have full safecopy support, these
fields have become useless for that purpose: the owner of the grant is
*always* the caller. Allowing the caller to supply another endpoint is
in fact dangerous, because the callee may then end up using a grant
from a third party. One could call this a variant of the confused
deputy problem.
From now on, safecopy calls should always use the caller's endpoint as
grant owner. This fully obsoletes the DL_ENDPT field in the
inet/ethernet protocol. IO_ENDPT has other uses besides identifying the
grant owner though. This patch renames IO_ENDPT to USER_ENDPT, not only
because that is a more fitting name (it should never be used for I/O
after all), but also in order to intentionally break any old system
source code outside the base system. If this patch breaks your code,
fixing it is fairly simple:
- DL_ENDPT should be replaced with m_source;
- IO_ENDPT should be replaced with m_source when used for safecopies;
- IO_ENDPT should be replaced with USER_ENDPT for any other use, e.g.
when setting REP_ENDPT, matching requests in CANCEL calls, getting
DEV_SELECT flags, and retrieving of the real user process's endpoint
in DEV_OPEN.
The changes in this patch are binary backward compatible.
2011-04-11 19:35:05 +02:00
|
|
|
if ((s = sys_safecopyfrom(pp->wrcaller, pp->wrgrant, pp->wroffset,
|
2012-06-16 03:46:15 +02:00
|
|
|
(vir_bytes) &c, 1)) != OK) {
|
2006-06-20 11:02:54 +02:00
|
|
|
printf("pty: safecopy failed (error %d)\n", s);
|
|
|
|
break;
|
2005-05-09 16:35:26 +02:00
|
|
|
}
|
2011-03-25 11:43:24 +01:00
|
|
|
pp->wroffset++;
|
2005-04-21 16:53:53 +02:00
|
|
|
|
|
|
|
/* Input processing. */
|
2010-04-15 08:55:42 +02:00
|
|
|
if (in_process(tp, &c, 1, -1) == 0) break;
|
2005-04-21 16:53:53 +02:00
|
|
|
|
|
|
|
/* PTY writer bookkeeping. */
|
|
|
|
pp->wrcum++;
|
|
|
|
if (--pp->wrleft == 0) {
|
2005-08-01 16:40:21 +02:00
|
|
|
if (pp->wrsendreply) {
|
|
|
|
tty_reply(TASK_REPLY, pp->wrcaller, pp->wrproc,
|
|
|
|
pp->wrcum);
|
|
|
|
pp->wrcum = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
notify(pp->wrcaller);
|
2005-04-21 16:53:53 +02:00
|
|
|
}
|
|
|
|
}
|
2008-11-19 13:26:10 +01:00
|
|
|
|
|
|
|
return 0;
|
2005-04-21 16:53:53 +02:00
|
|
|
}
|
|
|
|
|
2005-09-11 19:09:11 +02:00
|
|
|
/*===========================================================================*
|
|
|
|
* pty_close *
|
|
|
|
*===========================================================================*/
|
2012-03-25 20:25:53 +02:00
|
|
|
static int pty_close(tty_t *tp, int UNUSED(try))
|
2005-04-21 16:53:53 +02:00
|
|
|
{
|
|
|
|
/* The tty side has closed, so shut down the pty side. */
|
|
|
|
pty_t *pp = tp->tty_priv;
|
|
|
|
|
2008-11-19 13:26:10 +01:00
|
|
|
if (!(pp->state & PTY_ACTIVE)) return 0;
|
2005-04-21 16:53:53 +02:00
|
|
|
|
|
|
|
if (pp->rdleft > 0) {
|
2005-08-01 16:40:21 +02:00
|
|
|
assert(!pp->rdsendreply);
|
|
|
|
notify(pp->rdcaller);
|
2005-04-21 16:53:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (pp->wrleft > 0) {
|
2005-08-01 16:40:21 +02:00
|
|
|
assert(!pp->wrsendreply);
|
|
|
|
notify(pp->wrcaller);
|
2005-04-21 16:53:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (pp->state & PTY_CLOSED) pp->state = 0; else pp->state |= TTY_CLOSED;
|
2008-11-19 13:26:10 +01:00
|
|
|
|
|
|
|
return 0;
|
2005-04-21 16:53:53 +02:00
|
|
|
}
|
|
|
|
|
2005-09-11 19:09:11 +02:00
|
|
|
/*===========================================================================*
|
|
|
|
* pty_icancel *
|
|
|
|
*===========================================================================*/
|
2012-03-25 20:25:53 +02:00
|
|
|
static int pty_icancel(tty_t *tp, int UNUSED(try))
|
2005-04-21 16:53:53 +02:00
|
|
|
{
|
|
|
|
/* Discard waiting input. */
|
|
|
|
pty_t *pp = tp->tty_priv;
|
|
|
|
|
|
|
|
if (pp->wrleft > 0) {
|
2005-08-01 16:40:21 +02:00
|
|
|
pp->wrcum += pp->wrleft;
|
|
|
|
pp->wrleft= 0;
|
|
|
|
notify(pp->wrcaller);
|
2005-04-21 16:53:53 +02:00
|
|
|
}
|
2008-11-19 13:26:10 +01:00
|
|
|
|
|
|
|
return 0;
|
2005-04-21 16:53:53 +02:00
|
|
|
}
|
|
|
|
|
2005-09-11 19:09:11 +02:00
|
|
|
/*===========================================================================*
|
|
|
|
* pty_ocancel *
|
|
|
|
*===========================================================================*/
|
2012-03-25 20:25:53 +02:00
|
|
|
static int pty_ocancel(tty_t *tp, int UNUSED(try))
|
2005-04-21 16:53:53 +02:00
|
|
|
{
|
|
|
|
/* Drain the output buffer. */
|
|
|
|
pty_t *pp = tp->tty_priv;
|
|
|
|
|
|
|
|
pp->ocount = 0;
|
|
|
|
pp->otail = pp->ohead;
|
2008-11-19 13:26:10 +01:00
|
|
|
|
|
|
|
return 0;
|
2005-04-21 16:53:53 +02:00
|
|
|
}
|
|
|
|
|
2005-09-11 19:09:11 +02:00
|
|
|
/*===========================================================================*
|
|
|
|
* pty_init *
|
|
|
|
*===========================================================================*/
|
2012-03-25 20:25:53 +02:00
|
|
|
void pty_init(tty_t *tp)
|
2005-04-21 16:53:53 +02:00
|
|
|
{
|
|
|
|
pty_t *pp;
|
|
|
|
int line;
|
|
|
|
|
|
|
|
/* Associate PTY and TTY structures. */
|
|
|
|
line = tp - &tty_table[NR_CONS + NR_RS_LINES];
|
|
|
|
pp = tp->tty_priv = &pty_table[line];
|
|
|
|
pp->tty = tp;
|
2005-08-05 15:50:58 +02:00
|
|
|
pp->select_ops = 0;
|
2012-04-04 15:46:34 +02:00
|
|
|
pp->rdgrant = GRANT_INVALID;
|
|
|
|
pp->wrgrant = GRANT_INVALID;
|
2005-04-21 16:53:53 +02:00
|
|
|
|
|
|
|
/* Set up output queue. */
|
|
|
|
pp->ohead = pp->otail = pp->obuf;
|
|
|
|
|
|
|
|
/* Fill in TTY function hooks. */
|
|
|
|
tp->tty_devread = pty_read;
|
|
|
|
tp->tty_devwrite = pty_write;
|
|
|
|
tp->tty_echo = pty_echo;
|
|
|
|
tp->tty_icancel = pty_icancel;
|
|
|
|
tp->tty_ocancel = pty_ocancel;
|
|
|
|
tp->tty_close = pty_close;
|
2005-08-05 15:50:58 +02:00
|
|
|
tp->tty_select_ops = 0;
|
2005-04-21 16:53:53 +02:00
|
|
|
}
|
2005-08-01 16:40:21 +02:00
|
|
|
|
2005-09-11 19:09:11 +02:00
|
|
|
/*===========================================================================*
|
|
|
|
* pty_status *
|
|
|
|
*===========================================================================*/
|
2012-03-25 20:25:53 +02:00
|
|
|
int pty_status(message *m_ptr)
|
2005-08-01 16:40:21 +02:00
|
|
|
{
|
|
|
|
int i, event_found;
|
|
|
|
pty_t *pp;
|
|
|
|
|
|
|
|
event_found = 0;
|
|
|
|
for (i= 0, pp = pty_table; i<NR_PTYS; i++, pp++) {
|
2005-08-05 15:50:58 +02:00
|
|
|
if ((((pp->state & TTY_CLOSED) && pp->rdleft > 0) ||
|
2005-08-01 16:40:21 +02:00
|
|
|
pp->rdcum > 0) &&
|
|
|
|
pp->rdcaller == m_ptr->m_source)
|
|
|
|
{
|
|
|
|
m_ptr->m_type = DEV_REVIVE;
|
2006-03-03 11:21:45 +01:00
|
|
|
m_ptr->REP_ENDPT = pp->rdproc;
|
2011-03-25 11:43:24 +01:00
|
|
|
m_ptr->REP_IO_GRANT = pp->rdgrant;
|
2005-08-01 16:40:21 +02:00
|
|
|
m_ptr->REP_STATUS = pp->rdcum;
|
|
|
|
pp->rdleft = pp->rdcum = 0;
|
2012-04-04 15:46:34 +02:00
|
|
|
pp->rdgrant = GRANT_INVALID;
|
2005-08-01 16:40:21 +02:00
|
|
|
event_found = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2005-08-05 15:50:58 +02:00
|
|
|
if ((((pp->state & TTY_CLOSED) && pp->wrleft > 0) ||
|
2005-08-01 16:40:21 +02:00
|
|
|
pp->wrcum > 0) &&
|
|
|
|
pp->wrcaller == m_ptr->m_source)
|
|
|
|
{
|
|
|
|
m_ptr->m_type = DEV_REVIVE;
|
2006-03-03 11:21:45 +01:00
|
|
|
m_ptr->REP_ENDPT = pp->wrproc;
|
2011-03-25 11:43:24 +01:00
|
|
|
m_ptr->REP_IO_GRANT = pp->wrgrant;
|
2005-08-01 16:40:21 +02:00
|
|
|
if (pp->wrcum == 0)
|
|
|
|
m_ptr->REP_STATUS = EIO;
|
|
|
|
else
|
|
|
|
m_ptr->REP_STATUS = pp->wrcum;
|
|
|
|
|
|
|
|
pp->wrleft = pp->wrcum = 0;
|
2012-04-04 15:46:34 +02:00
|
|
|
pp->wrgrant = GRANT_INVALID;
|
2005-08-01 16:40:21 +02:00
|
|
|
event_found = 1;
|
|
|
|
break;
|
|
|
|
}
|
2005-08-05 15:50:58 +02:00
|
|
|
|
2005-09-11 19:09:11 +02:00
|
|
|
if (pp->select_ready_ops && pp->select_proc == m_ptr->m_source) {
|
2005-08-05 15:50:58 +02:00
|
|
|
m_ptr->m_type = DEV_IO_READY;
|
|
|
|
m_ptr->DEV_MINOR = PTYPX_MINOR + i;
|
|
|
|
m_ptr->DEV_SEL_OPS = pp->select_ready_ops;
|
|
|
|
pp->select_ready_ops = 0;
|
|
|
|
event_found = 1;
|
|
|
|
break;
|
|
|
|
}
|
2005-08-01 16:40:21 +02:00
|
|
|
}
|
|
|
|
return event_found;
|
|
|
|
}
|
|
|
|
|
2005-09-11 19:09:11 +02:00
|
|
|
/*===========================================================================*
|
|
|
|
* select_try_pty *
|
|
|
|
*===========================================================================*/
|
2012-03-25 20:25:53 +02:00
|
|
|
static int select_try_pty(tty_t *tp, int ops)
|
2005-08-05 15:50:58 +02:00
|
|
|
{
|
|
|
|
pty_t *pp = tp->tty_priv;
|
|
|
|
int r = 0;
|
|
|
|
|
2005-09-11 19:09:11 +02:00
|
|
|
if (ops & SEL_WR) {
|
2005-08-05 15:50:58 +02:00
|
|
|
/* Write won't block on error. */
|
|
|
|
if (pp->state & TTY_CLOSED) r |= SEL_WR;
|
|
|
|
else if (pp->wrleft != 0 || pp->wrcum != 0) r |= SEL_WR;
|
|
|
|
else r |= SEL_WR;
|
|
|
|
}
|
|
|
|
|
2005-09-11 19:09:11 +02:00
|
|
|
if (ops & SEL_RD) {
|
2005-08-05 15:50:58 +02:00
|
|
|
/* Read won't block on error. */
|
|
|
|
if (pp->state & TTY_CLOSED) r |= SEL_RD;
|
2005-09-11 19:09:11 +02:00
|
|
|
else if (pp->rdleft != 0 || pp->rdcum != 0) r |= SEL_RD;
|
|
|
|
else if (pp->ocount > 0) r |= SEL_RD; /* Actual data. */
|
2005-08-05 15:50:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2005-09-11 19:09:11 +02:00
|
|
|
/*===========================================================================*
|
|
|
|
* select_retry_pty *
|
|
|
|
*===========================================================================*/
|
2012-03-25 20:25:53 +02:00
|
|
|
void select_retry_pty(tty_t *tp)
|
2005-08-05 15:50:58 +02:00
|
|
|
{
|
|
|
|
pty_t *pp = tp->tty_priv;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
/* See if the pty side of a pty is ready to return a select. */
|
2005-09-11 19:09:11 +02:00
|
|
|
if (pp->select_ops && (r=select_try_pty(tp, pp->select_ops))) {
|
2005-08-05 15:50:58 +02:00
|
|
|
pp->select_ops &= ~r;
|
|
|
|
pp->select_ready_ops |= r;
|
|
|
|
notify(pp->select_proc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-11 19:09:11 +02:00
|
|
|
/*===========================================================================*
|
|
|
|
* pty_select *
|
|
|
|
*===========================================================================*/
|
2012-03-25 20:25:53 +02:00
|
|
|
static int pty_select(tty_t *tp, message *m)
|
2005-08-05 15:50:58 +02:00
|
|
|
{
|
|
|
|
pty_t *pp = tp->tty_priv;
|
|
|
|
int ops, ready_ops = 0, watch;
|
|
|
|
|
Server/driver protocols: no longer allow third-party copies.
Before safecopies, the IO_ENDPT and DL_ENDPT message fields were needed
to know which actual process to copy data from/to, as that process may
not always be the caller. Now that we have full safecopy support, these
fields have become useless for that purpose: the owner of the grant is
*always* the caller. Allowing the caller to supply another endpoint is
in fact dangerous, because the callee may then end up using a grant
from a third party. One could call this a variant of the confused
deputy problem.
From now on, safecopy calls should always use the caller's endpoint as
grant owner. This fully obsoletes the DL_ENDPT field in the
inet/ethernet protocol. IO_ENDPT has other uses besides identifying the
grant owner though. This patch renames IO_ENDPT to USER_ENDPT, not only
because that is a more fitting name (it should never be used for I/O
after all), but also in order to intentionally break any old system
source code outside the base system. If this patch breaks your code,
fixing it is fairly simple:
- DL_ENDPT should be replaced with m_source;
- IO_ENDPT should be replaced with m_source when used for safecopies;
- IO_ENDPT should be replaced with USER_ENDPT for any other use, e.g.
when setting REP_ENDPT, matching requests in CANCEL calls, getting
DEV_SELECT flags, and retrieving of the real user process's endpoint
in DEV_OPEN.
The changes in this patch are binary backward compatible.
2011-04-11 19:35:05 +02:00
|
|
|
ops = m->USER_ENDPT & (SEL_RD|SEL_WR|SEL_ERR);
|
|
|
|
watch = (m->USER_ENDPT & SEL_NOTIFY) ? 1 : 0;
|
2005-08-05 15:50:58 +02:00
|
|
|
|
|
|
|
ready_ops = select_try_pty(tp, ops);
|
|
|
|
|
2005-09-11 19:09:11 +02:00
|
|
|
if (!ready_ops && ops && watch) {
|
2005-08-05 15:50:58 +02:00
|
|
|
pp->select_ops |= ops;
|
|
|
|
pp->select_proc = m->m_source;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ready_ops;
|
|
|
|
}
|
|
|
|
|
2005-04-21 16:53:53 +02:00
|
|
|
#endif /* NR_PTYS > 0 */
|