diff options
Diffstat (limited to 'term/ptyio.c')
-rw-r--r-- | term/ptyio.c | 169 |
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) { |