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 */
|
|
|
|
|
|
|
|
PRIVATE pty_t pty_table[NR_PTYS]; /* PTY bookkeeping */
|
|
|
|
|
2012-03-24 16:16:34 +01:00
|
|
|
FORWARD int pty_write(tty_t *tp, int try);
|
|
|
|
FORWARD void pty_echo(tty_t *tp, int c);
|
|
|
|
FORWARD void pty_start(pty_t *pp);
|
|
|
|
FORWARD void pty_finish(pty_t *pp);
|
|
|
|
FORWARD int pty_read(tty_t *tp, int try);
|
|
|
|
FORWARD int pty_close(tty_t *tp, int try);
|
|
|
|
FORWARD int pty_icancel(tty_t *tp, int try);
|
|
|
|
FORWARD int pty_ocancel(tty_t *tp, int try);
|
|
|
|
FORWARD 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 *
|
|
|
|
*===========================================================================*/
|
2010-01-27 11:19:13 +01:00
|
|
|
PUBLIC 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;
|
|
|
|
}
|
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) {
|
|
|
|
return; /* already done */
|
|
|
|
}
|
2005-04-21 16:53:53 +02:00
|
|
|
|
2006-06-20 11:02:54 +02:00
|
|
|
{
|
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;
|
|
|
|
}
|
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) {
|
|
|
|
return; /* already done */
|
|
|
|
}
|
2005-04-21 16:53:53 +02:00
|
|
|
|
2006-06-20 11:02:54 +02:00
|
|
|
{
|
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;
|
|
|
|
}
|
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;
|
|
|
|
}
|
|
|
|
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 *
|
|
|
|
*===========================================================================*/
|
2010-01-27 11:19:13 +01:00
|
|
|
PRIVATE 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. */
|
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(tp->tty_outcaller, tp->tty_outgrant,
|
2011-03-25 11:43:24 +01:00
|
|
|
tp->tty_outoffset, (vir_bytes) pp->ohead, count, D))!=OK) {
|
2006-06-20 11:02:54 +02:00
|
|
|
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 *
|
|
|
|
*===========================================================================*/
|
2010-01-27 11:19:13 +01:00
|
|
|
PRIVATE 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 *
|
|
|
|
*===========================================================================*/
|
2010-01-27 11:19:13 +01:00
|
|
|
PRIVATE 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,
|
2011-03-25 11:43:24 +01:00
|
|
|
pp->rdoffset, (vir_bytes) pp->otail, count, D)) != 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 *
|
|
|
|
*===========================================================================*/
|
2010-01-27 11:19:13 +01:00
|
|
|
PRIVATE 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 *
|
|
|
|
*===========================================================================*/
|
2010-01-27 11:19:13 +01:00
|
|
|
PRIVATE 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,
|
2011-03-25 11:43:24 +01:00
|
|
|
(vir_bytes) &c, 1, D)) != 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 *
|
|
|
|
*===========================================================================*/
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
PRIVATE 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 *
|
|
|
|
*===========================================================================*/
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
PRIVATE 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 *
|
|
|
|
*===========================================================================*/
|
Split block/character protocols and libdriver
This patch separates the character and block driver communication
protocols. The old character protocol remains the same, but a new
block protocol is introduced. The libdriver library is replaced by
two new libraries: libchardriver and libblockdriver. Their exposed
API, and drivers that use them, have been updated accordingly.
Together, libbdev and libblockdriver now completely abstract away
the message format used by the block protocol. As the memory driver
is both a character and a block device driver, it now implements its
own message loop.
The most important semantic change made to the block protocol is that
it is no longer possible to return both partial results and an error
for a single transfer. This simplifies the interaction between the
caller and the driver, as the I/O vector no longer needs to be copied
back. Also, drivers are now no longer supposed to decide based on the
layout of the I/O vector when a transfer should be cut short. Put
simply, transfers are now supposed to either succeed completely, or
result in an error.
After this patch, the state of the various pieces is as follows:
- block protocol: stable
- libbdev API: stable for synchronous communication
- libblockdriver API: needs slight revision (the drvlib/partition API
in particular; the threading API will also change shortly)
- character protocol: needs cleanup
- libchardriver API: needs cleanup accordingly
- driver restarts: largely unsupported until endpoint changes are
reintroduced
As a side effect, this patch eliminates several bugs, hacks, and gcc
-Wall and -W warnings all over the place. It probably introduces a
few new ones, too.
Update warning: this patch changes the protocol between MFS and disk
drivers, so in order to use old/new images, the MFS from the ramdisk
must be used to mount all file systems.
2011-11-22 13:27:53 +01:00
|
|
|
PRIVATE 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 *
|
|
|
|
*===========================================================================*/
|
2010-01-27 11:19:13 +01:00
|
|
|
PUBLIC 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;
|
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 *
|
|
|
|
*===========================================================================*/
|
2005-08-01 16:40:21 +02:00
|
|
|
PUBLIC int pty_status(message *m_ptr)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
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;
|
|
|
|
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 *
|
|
|
|
*===========================================================================*/
|
2005-08-05 15:50:58 +02:00
|
|
|
PRIVATE int select_try_pty(tty_t *tp, int ops)
|
|
|
|
{
|
|
|
|
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 *
|
|
|
|
*===========================================================================*/
|
2005-08-05 15:50:58 +02:00
|
|
|
PUBLIC void select_retry_pty(tty_t *tp)
|
|
|
|
{
|
|
|
|
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 *
|
|
|
|
*===========================================================================*/
|
2005-08-05 15:50:58 +02:00
|
|
|
PRIVATE int pty_select(tty_t *tp, message *m)
|
|
|
|
{
|
|
|
|
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 */
|