aboutsummaryrefslogtreecommitdiff
path: root/term/ptyio.c
diff options
context:
space:
mode:
Diffstat (limited to 'term/ptyio.c')
-rw-r--r--term/ptyio.c169
1 files changed, 114 insertions, 55 deletions
diff --git a/term/ptyio.c b/term/ptyio.c
index 22c46407..9c1509ff 100644
--- a/term/ptyio.c
+++ b/term/ptyio.c
@@ -1,5 +1,5 @@
-/*
- Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+/*
+ Copyright (C) 1995, 1996, 1999, 2002 Free Software Foundation, Inc.
Written by Michael I. Bushnell, p/BSG.
This file is part of the GNU Hurd.
@@ -19,12 +19,12 @@
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
#include <sys/ioctl.h>
-#include <hurd/hurd_types.h>
#include <string.h>
#include <hurd/ports.h>
#include <unistd.h>
#include <fcntl.h>
#include "term.h"
+#include "tioctl_S.h"
/* Set if we need a wakeup when tty output has been done */
static int pty_read_blocked = 0;
@@ -55,22 +55,22 @@ static int ptyopen = 0;
static int nptyperopens = 0;
-void
-ptyio_init ()
+static error_t
+ptyio_init (void)
{
condition_implies (inputq->wait, &pty_select_wakeup);
condition_implies (&pty_read_wakeup, &pty_select_wakeup);
+ return 0;
}
-
+
error_t
pty_open_hook (struct trivfs_control *cntl,
- uid_t *uids, u_int nuids,
- uid_t *gids, u_int ngids,
+ struct iouser *user,
int flags)
{
if ((flags & (O_READ|O_WRITE)) == 0)
return 0;
-
+
mutex_lock (&global_lock);
if (ptyopen)
@@ -78,9 +78,18 @@ pty_open_hook (struct trivfs_control *cntl,
mutex_unlock (&global_lock);
return EBUSY;
}
-
+
ptyopen = 1;
+
+ /* Re-initialize pty state. */
+ external_processing = 0;
+ packet_mode = 0;
+ user_ioctl_mode = 0;
+ control_byte = 0;
+ pktnostop = 0;
+
mutex_unlock (&global_lock);
+
return 0;
}
@@ -129,7 +138,7 @@ wake_reader ()
/* Lower half for tty node */
-static void
+static error_t
ptyio_start_output ()
{
if (packet_mode && output_stopped && (!(termflags & USER_OUTPUT_SUSP)))
@@ -139,9 +148,10 @@ ptyio_start_output ()
output_stopped = 0;
}
wake_reader ();
+ return 0;
}
-static void
+static error_t
ptyio_abandon_physical_output ()
{
if (packet_mode)
@@ -149,9 +159,10 @@ ptyio_abandon_physical_output ()
control_byte |= TIOCPKT_FLUSHWRITE;
wake_reader ();
}
+ return 0;
}
-static void
+static error_t
ptyio_suspend_physical_output ()
{
if (packet_mode)
@@ -161,16 +172,17 @@ ptyio_suspend_physical_output ()
output_stopped = 1;
wake_reader ();
}
+ return 0;
}
-static int
+static int
ptyio_pending_output_size ()
{
/* We don't maintain any pending output buffer separate from the outputq. */
return 0;
}
-static void
+static error_t
ptyio_notice_input_flushed ()
{
if (packet_mode)
@@ -178,76 +190,94 @@ ptyio_notice_input_flushed ()
control_byte |= TIOCPKT_FLUSHREAD;
wake_reader ();
}
+ return 0;
}
-static error_t
+static error_t
ptyio_assert_dtr ()
{
dtr_on = 1;
return 0;
}
-static void
+static error_t
ptyio_desert_dtr ()
{
dtr_on = 0;
wake_reader ();
+ return 0;
}
-static void
-ptyio_set_bits ()
+static error_t
+ptyio_set_bits (struct termios *state)
{
- int stop;
-
- if (packet_mode && external_processing)
+ if (packet_mode)
{
- control_byte |= TIOCPKT_IOCTL;
+ int wakeup = 0;
+ int stop = ((state->c_iflag & IXON)
+ && CCEQ (state->c_cc[VSTOP], CHAR_DC3)
+ && CCEQ (state->c_cc[VSTART], CHAR_DC1));
+
+ if (external_processing)
+ {
+ control_byte |= TIOCPKT_IOCTL;
+ wakeup = 1;
+ }
- stop = ((termstate.c_iflag & IXON)
- && CCEQ (termstate.c_cc[VSTOP], CHAR_DC3)
- && CCEQ (termstate.c_cc[VSTART], CHAR_DC1));
if (pktnostop && stop)
{
pktnostop = 0;
control_byte |= TIOCPKT_DOSTOP;
control_byte &= ~TIOCPKT_NOSTOP;
+ wakeup = 1;
}
else if (!pktnostop && !stop)
{
pktnostop = 1;
control_byte |= TIOCPKT_NOSTOP;
control_byte &= ~TIOCPKT_DOSTOP;
+ wakeup = 1;
}
- wake_reader ();
+ if (wakeup)
+ wake_reader ();
}
+ return 0;
}
/* These do nothing. In BSD the associated ioctls get errors, but
I'd rather just ignore them. */
-static void
+static error_t
ptyio_set_break ()
{
+ return 0;
}
-static void
+static error_t
ptyio_clear_break ()
{
+ return 0;
}
-static void
+static error_t
ptyio_mdmctl (int a, int b)
{
+ return 0;
}
-static int
-ptyio_mdmstate ()
+static error_t
+ptyio_mdmstate (int *state)
{
+ *state = 0;
return 0;
}
-struct bottomhalf ptyio_bottom =
+const struct bottomhalf ptyio_bottom =
{
+ TERM_ON_MASTERPTY,
+ ptyio_init,
+ NULL, /* fini */
+ NULL, /* gwinsz */
ptyio_start_output,
ptyio_set_break,
ptyio_clear_break,
@@ -275,9 +305,9 @@ pty_io_read (struct trivfs_protid *cred,
mach_msg_type_number_t amount)
{
int size;
-
+
mutex_lock (&global_lock);
-
+
if ((cred->po->openmodes & O_READ) == 0)
{
mutex_unlock (&global_lock);
@@ -285,8 +315,14 @@ pty_io_read (struct trivfs_protid *cred,
}
while (!control_byte
+ && (termflags & TTY_OPEN)
&& (!qsize (outputq) || (termflags & USER_OUTPUT_SUSP)))
{
+ if (cred->po->openmodes & O_NONBLOCK)
+ {
+ mutex_unlock (&global_lock);
+ return EWOULDBLOCK;
+ }
pty_read_blocked = 1;
if (hurd_condition_wait (&pty_read_wakeup, &global_lock))
{
@@ -294,7 +330,7 @@ pty_io_read (struct trivfs_protid *cred,
return EINTR;
}
}
-
+
if (control_byte)
{
size = 1;
@@ -307,18 +343,18 @@ pty_io_read (struct trivfs_protid *cred,
if (packet_mode || user_ioctl_mode)
size++;
}
-
+
if (size > amount)
size = amount;
if (size > *datalen)
- vm_allocate (mach_task_self (), (vm_address_t *) data, size, 1);
+ *data = mmap (0, size, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
*datalen = size;
if (control_byte)
{
**data = control_byte;
if (packet_mode && (control_byte & TIOCPKT_IOCTL))
- bcopy (&termstate, *data + 1, size - 1);
+ memcpy (*data + 1, &termstate, size - 1);
control_byte = 0;
}
else
@@ -338,7 +374,7 @@ pty_io_read (struct trivfs_protid *cred,
return 0;
}
-
+
/* Validation has already been done by trivfs_S_io_write. */
error_t
pty_io_write (struct trivfs_protid *cred,
@@ -350,7 +386,7 @@ pty_io_write (struct trivfs_protid *cred,
int cancel = 0;
mutex_lock (&global_lock);
-
+
if ((cred->po->openmodes & O_WRITE) == 0)
{
mutex_unlock (&global_lock);
@@ -361,7 +397,14 @@ pty_io_write (struct trivfs_protid *cred,
{
/* Wait for the queue to be empty */
while (qsize (inputq) && !cancel)
- cancel = hurd_condition_wait (inputq->wait, &global_lock);
+ {
+ if (cred->po->openmodes & O_NONBLOCK)
+ {
+ mutex_unlock (&global_lock);
+ return EWOULDBLOCK;
+ }
+ cancel = hurd_condition_wait (inputq->wait, &global_lock);
+ }
if (cancel)
{
mutex_unlock (&global_lock);
@@ -370,7 +413,7 @@ pty_io_write (struct trivfs_protid *cred,
for (i = 0; i < datalen; i++)
enqueue (&inputq, data[i]);
-
+
/* Extra garbage charater */
enqueue (&inputq, 0);
}
@@ -398,7 +441,7 @@ pty_io_write (struct trivfs_protid *cred,
/* Validation has already been done by trivfs_S_io_readable */
error_t
-pty_io_readable (int *amt)
+pty_io_readable (size_t *amt)
{
mutex_lock (&global_lock);
if (control_byte)
@@ -416,10 +459,10 @@ pty_io_readable (int *amt)
/* Validation has already been done by trivfs_S_io_select. */
error_t
pty_io_select (struct trivfs_protid *cred, mach_port_t reply,
- int *type, int *idtag)
+ int *type)
{
int avail = 0;
-
+
if (*type == 0)
return 0;
@@ -427,7 +470,8 @@ pty_io_select (struct trivfs_protid *cred, mach_port_t reply,
while (1)
{
- if ((*type & SELECT_READ) && (control_byte || qsize (outputq)))
+ if ((*type & SELECT_READ)
+ && (control_byte || qsize (outputq) || !(termflags & TTY_OPEN)))
avail |= SELECT_READ;
if ((*type & SELECT_URG) && control_byte)
@@ -435,7 +479,7 @@ pty_io_select (struct trivfs_protid *cred, mach_port_t reply,
if ((*type & SELECT_WRITE) && (!remote_input_mode || !qsize (inputq)))
avail |= SELECT_WRITE;
-
+
if (avail)
{
*type = avail;
@@ -463,13 +507,18 @@ S_tioctl_tiocsig (io_t port,
port, pty_class);
if (!cred)
return EOPNOTSUPP;
-
+
+ mutex_lock (&global_lock);
+
drop_output ();
clear_queue (inputq);
clear_queue (rawq);
ptyio_notice_input_flushed ();
send_signal (sig);
+
+ mutex_unlock (&global_lock);
ports_port_deref (cred);
+
return 0;
}
@@ -478,12 +527,14 @@ S_tioctl_tiocpkt (io_t port,
int mode)
{
error_t err;
-
+
struct trivfs_protid *cred = ports_lookup_port (term_bucket,
port, pty_class);
if (!cred)
return EOPNOTSUPP;
-
+
+ mutex_lock (&global_lock);
+
if (!!mode == !!packet_mode)
err = 0;
else if (mode && user_ioctl_mode)
@@ -494,7 +545,10 @@ S_tioctl_tiocpkt (io_t port,
control_byte = 0;
err = 0;
}
+
+ mutex_unlock (&global_lock);
ports_port_deref (cred);
+
return err;
}
@@ -503,12 +557,14 @@ S_tioctl_tiocucntl (io_t port,
int mode)
{
error_t err;
-
+
struct trivfs_protid *cred = ports_lookup_port (term_bucket,
port, pty_class);
if (!cred)
return EOPNOTSUPP;
-
+
+ mutex_lock (&global_lock);
+
if (!!mode == !!user_ioctl_mode)
err = 0;
else if (mode && packet_mode)
@@ -519,7 +575,10 @@ S_tioctl_tiocucntl (io_t port,
control_byte = 0;
err = 0;
}
+
+ mutex_unlock (&global_lock);
ports_port_deref (cred);
+
return err;
}
@@ -529,7 +588,7 @@ S_tioctl_tiocremote (io_t port,
{
struct trivfs_protid *cred = ports_lookup_port (term_bucket,
port, pty_class);
-
+
if (!cred)
return EOPNOTSUPP;
@@ -552,7 +611,7 @@ S_tioctl_tiocext (io_t port,
port, pty_class);
if (!cred)
return EOPNOTSUPP;
-
+
mutex_lock (&global_lock);
if (mode && !external_processing)
{