diff options
Diffstat (limited to 'term')
-rw-r--r-- | term/ChangeLog | 26 | ||||
-rw-r--r-- | term/devio.c | 168 | ||||
-rw-r--r-- | term/users.c | 4 |
3 files changed, 133 insertions, 65 deletions
diff --git a/term/ChangeLog b/term/ChangeLog index 92002cda..cf70ca4c 100644 --- a/term/ChangeLog +++ b/term/ChangeLog @@ -1,3 +1,29 @@ +Wed Mar 17 16:32:05 1999 Thomas Bushnell, BSG <tb@mit.edu> + + * users.c (S_term_get_peername): Compare BOTTOM against the + correct value. Reported by Yamashita TAKAO (az207@epa.go.jp). + + * devio.c (devio_desert_dtr): Cast &BITS correctly in call to + device_set_status. + (device_open_reply): Alwas clean open_pending no matter what. Use + ERR instead of ERRNO. On fake opens, close the device before + deallocating the port. + Reported by Mark Kettenis (kettenis@gnu.org). + +Tue Mar 16 01:04:06 1999 Thomas Bushnell, BSG <tb@mit.edu> + + * devio.c (open_pending): Make an enum. + (devio_desert_dtr): Don't close the device, just set the TM_HUP + modem bit, which should cause a hangup to occur. + (devio_assert_dtr): Don't always open the device, instead use + initial_open the first time, and schedule a fake open the other + times. + (initial_open): New function, guts from old device_assert_dtr. + (device_open_reply): Distinguish replies from initial and fake + opens appropriately. + (ports_do_mach_notify_send_once): Test and set open_pending using + new enum values. + Mon Mar 15 14:58:33 1999 Thomas Bushnell, BSG <tb@mit.edu> * users.c (S_term_get_peername): Implement new RPC. diff --git a/term/devio.c b/term/devio.c index aeae5eaf..f8010bac 100644 --- a/term/devio.c +++ b/term/devio.c @@ -54,8 +54,13 @@ static int output_pending; /* This flag is set if there is an outstanding device_read. */ static int input_pending; -/* This flag is set if there is an outstanding device_open. */ -static int open_pending; +/* Tell the status of any pending open */ +static enum +{ + NOTPENDING, /* no open is pending */ + INITIAL, /* initial open of device pending */ + FAKE, /* open pending to block on dtr */ +} open_pending; static char pending_output[IO_INBAND_MAX]; static int npending_output; @@ -84,8 +89,6 @@ static int char_size_mask_xxx = 0xff; /* Forward */ static void devio_desert_dtr (); - - static void init_devio (void) __attribute__ ((constructor)); static void init_devio () @@ -393,37 +396,21 @@ devio_pending_output_size () return npending_output; } -static void -devio_desert_dtr () -{ - /* This will work, because we set the TF_HUPCLS bit earlier. */ - device_close (phys_device); - mach_port_deallocate (mach_task_self (), phys_device); - phys_device = MACH_PORT_NULL; - - mach_port_deallocate (mach_task_self (), phys_reply); - mach_port_deallocate (mach_task_self (), phys_reply_writes); - phys_reply = phys_reply_writes = MACH_PORT_NULL; - - ports_port_deref (phys_reply_pi); - ports_port_deref (phys_reply_writes_pi); - phys_reply_pi = phys_reply_writes_pi = 0; - - report_carrier_off (); -} - +/* Do this the first time the device is to be opened */ static error_t -devio_assert_dtr () +initial_open () { - error_t err; + assert (open_pending != FAKE); - if (open_pending || (phys_device != MACH_PORT_NULL)) + /* Nothing to do */ + if (open_pending == INITIAL) return 0; - + + assert (phys_device == MACH_PORT_NULL); assert (phys_reply == MACH_PORT_NULL); assert (phys_reply_pi == 0); - - err = ports_create_port (phys_reply_class, term_bucket, + + err = ports_create_port (phys_reply_class, term_bucket, sizeof (struct port_info), &phys_reply_pi); if (err) return err; @@ -442,11 +429,49 @@ devio_assert_dtr () phys_reply_pi = 0; } else - open_pending = 1; + open_pending = INITIAL; return err; } +static void +devio_desert_dtr () +{ + dev_status_t bits; + + /* Turn off DTR. */ + bits = TM_HUP; + device_set_status (phys_device, TTY_MODEM, + (dev_status_t) &bits, TTY_MODEM_COUNT); + + report_carrier_off (); +} + +static error_t +devio_assert_dtr () +{ + error_t err; + + /* The first time is special. */ + if (phys_device == MACH_PORT_NULL) + return initial_open (); + + /* Schedule a fake open to wait for DTR, unless one is already + happening. */ + assert (open_pending != INITIAL); + if (open_pending == FAKE) + return 0; + + err = device_open_request (device_master, phys_reply, + D_READ|D_WRITE, pterm_name); + + if (err) + return err; + + open_pending = FAKE; + return 0; +} + kern_return_t device_open_reply (mach_port_t replyport, int returncode, @@ -454,45 +479,65 @@ device_open_reply (mach_port_t replyport, { struct tty_status ttystat; int count = TTY_STATUS_COUNT; - error_t err; + error_t err = 0; if (replyport != phys_reply) return EOPNOTSUPP; mutex_lock (&global_lock); - open_pending = 0; + assert (open_pending != NOTPENDING); - if (returncode != 0) + if (open_pending == INITIAL) { - /* Bogus. */ - report_carrier_on (); - report_carrier_off (); + /* Special handling for the first open */ - mach_port_deallocate (mach_task_self (), phys_reply); - phys_reply = MACH_PORT_NULL; - ports_port_deref (phys_reply_pi); - phys_reply_pi = 0; - mutex_unlock (&global_lock); - return 0; - } + if (returncode != 0) + { + /* Bogus. */ + report_carrier_on (); + report_carrier_off (); - assert (phys_device == MACH_PORT_NULL); - assert (phys_reply_writes == MACH_PORT_NULL); - assert (phys_reply_writes_pi == 0); - phys_device = device; - errno = ports_create_port (phys_reply_class, term_bucket, - sizeof (struct port_info), - &phys_reply_writes_pi); - if (errno) + mach_port_deallocate (mach_task_self (), phys_reply); + phys_reply = MACH_PORT_NULL; + ports_port_deref (phys_reply_pi); + phys_reply_pi = 0; + + open_pending = NOTPENDING; + mutex_unlock (&global_lock); + return 0; + } + + assert (phys_device == MACH_PORT_NULL); + assert (phys_reply_writes == MACH_PORT_NULL); + assert (phys_reply_writes_pi == 0); + phys_device = device; + err = ports_create_port (phys_reply_class, term_bucket, + sizeof (struct port_info), + &phys_reply_writes_pi); + if (err) + { + open_pending = NOTPENDING; + mutex_unlock (&global_lock); + return err; + } + phys_reply_writes = ports_get_right (phys_reply_writes_pi); + mach_port_insert_right (mach_task_self (), phys_reply_writes, + phys_reply_writes, MACH_MSG_TYPE_MAKE_SEND); + + /* Schedule our first read */ + err = device_read_request_inband (phys_device, phys_reply, D_NOWAIT, + 0, vm_page_size); + + input_pending = 1; + } + else { - mutex_unlock (&global_lock); - return errno; + /* This was a fake open, only for the sake of assert DTR. */ + device_close (device); + mach_port_deallocate (mach_task_self (), device); } - phys_reply_writes = ports_get_right (phys_reply_writes_pi); - mach_port_insert_right (mach_task_self (), phys_reply_writes, - phys_reply_writes, MACH_MSG_TYPE_MAKE_SEND); - + device_get_status (phys_device, TTY_STATUS, (dev_status_t)&ttystat, &count); ttystat.tt_breakc = 0; @@ -500,14 +545,11 @@ device_open_reply (mach_port_t replyport, device_set_status (phys_device, TTY_STATUS, (dev_status_t)&ttystat, TTY_STATUS_COUNT); - err = device_read_request_inband (phys_device, phys_reply, D_NOWAIT, - 0, vm_page_size); - - input_pending = 1; report_carrier_on (); if (err) devio_desert_dtr (); + open_pending = NOTPENDING; mutex_unlock (&global_lock); return 0; @@ -661,9 +703,9 @@ ports_do_mach_notify_send_once (mach_port_t notify) else input_pending = 1; } - else if (open_pending) + else if (open_pending != NOTPENDING) { - open_pending = 0; + open_pending = NOTPENDiNG; report_carrier_on (); report_carrier_off (); diff --git a/term/users.c b/term/users.c index 828b1a3d..9f2a3eff 100644 --- a/term/users.c +++ b/term/users.c @@ -2208,9 +2208,9 @@ S_term_get_peername (io_t arg, peer = (cred->pi.class == tty_class) ? ptyctl : termctl; - if (bottom != ptyio_bottom || !peer->hook) + if (bottom != &ptyio_bottom || !peer->hook) { - port_port_deref (cred); + ports_port_deref (cred); return ENOENT; } |