summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <cgf@redhat.com>2003-02-01 04:48:22 +0000
committerChristopher Faylor <cgf@redhat.com>2003-02-01 04:48:22 +0000
commitcb393d5e461b30cb058bfe3293ebf8dba23ee7f1 (patch)
tree7362cafab878b4b8d63d1b52e4347b7f848c5ad2
parent7c500b39174baba19061c9f4cc617b86ce7960a5 (diff)
downloadgdb-cb393d5e461b30cb058bfe3293ebf8dba23ee7f1.tar.gz
merge from trunk
-rw-r--r--winsup/cygwin/ChangeLog17
-rw-r--r--winsup/cygwin/devices.gperf4
-rw-r--r--winsup/cygwin/fhandler_serial.cc328
-rw-r--r--winsup/cygwin/termios.cc268
4 files changed, 456 insertions, 161 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 0bee235f4fd..fc3bfcb8150 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,22 @@
2003-01-31 Christopher Faylor <cgf@redhat.com>
+ * fhandler_serial.cc (fhandler_serial::open): Avoid extraneous setting
+ of res.
+
+ * termios.cc (tcsetattr): Correctly record errno after tcsetattr call.
+
+2003-01-31 Troy Curtiss <troyc@usa.net>
+
+ * fhandler_serial.cc (fhandler_serial::tcsetattr): Add error-checking
+ so that if any Win32 SetComm*() calls fail, errno gets set to EINVAL
+ and tcsetattr() returns -1. Catch invalid bitrates, mostly. If baud
+ rate setting is B0, just drop DTR and leave Win32 DCB bitrate as-is
+ since 0 is not a valid Win32 setting.
+ (fhandler_serial::tcgetattr): If DTR is low, populate the bitrate as
+ B0, otherwise get it from the DCB.
+
+2003-01-31 Christopher Faylor <cgf@redhat.com>
+
* passwd.cc (pwdgrp::read_passwd): linebuf *must* be static (from
Pierre Humblet).
* pwdgrp.h (pwdgrp::refresh): Avoid calling read function if we already
diff --git a/winsup/cygwin/devices.gperf b/winsup/cygwin/devices.gperf
index 0f495e2ce29..fd42e4645cd 100644
--- a/winsup/cygwin/devices.gperf
+++ b/winsup/cygwin/devices.gperf
@@ -41,8 +41,8 @@ struct device;
"/dev/tcp", FH_SOCKET, "\\dev\\socket", 0, 0, 0, 0
"/dev/udp", FH_SOCKET, "\\dev\\socket", 0, 0, 0, 0
"/dev/dgsocket", FH_SOCKET, "\\dev\\socket", 0, 0, 0, 0
-"/dev/st", FH_TAPE, "\\Device\\Tape%d", 0, 127,
-"/dev/nst", FH_NTAPE, "\\Device\\Tape%d", 0, 127,
+"/dev/st", FH_TAPE, "\\Device\\Tape%d", 0, 127
+"/dev/nst", FH_NTAPE, "\\Device\\Tape%d", 0, 127
"/dev/fd", FH_FLOPPY, "\\Device\\Floppy%d", 0, 15
"/dev/scd", FH_CDROM, "\\Device\\CdRom%d", 0, 15
"/dev/sr", FH_CDROM, "\\Device\\CdRom%d", 0, 15
diff --git a/winsup/cygwin/fhandler_serial.cc b/winsup/cygwin/fhandler_serial.cc
index b813c9121a7..e460c1549e1 100644
--- a/winsup/cygwin/fhandler_serial.cc
+++ b/winsup/cygwin/fhandler_serial.cc
@@ -168,12 +168,12 @@ fhandler_serial::raw_write (const void *ptr, size_t len)
switch (GetLastError ())
{
- case ERROR_OPERATION_ABORTED:
- continue;
- case ERROR_IO_PENDING:
- break;
- default:
- goto err;
+ case ERROR_OPERATION_ABORTED:
+ continue;
+ case ERROR_IO_PENDING:
+ break;
+ default:
+ goto err;
}
if (!GetOverlappedResult (get_handle (), &write_status, &bytes_written, TRUE))
@@ -214,7 +214,7 @@ fhandler_serial::open (path_conv *, int flags, mode_t mode)
syscall_printf ("fhandler_serial::open (%s, %p, %p)",
get_name (), flags, mode);
- if (!(res = this->fhandler_base::open (NULL, flags, mode)))
+ if (!this->fhandler_base::open (NULL, flags, mode))
return 0;
res = 1;
@@ -347,27 +347,27 @@ fhandler_serial::tcflow (int action)
switch (action)
{
- case TCOOFF:
- win32action = SETXOFF;
- break;
- case TCOON:
- win32action = SETXON;
- break;
- case TCION:
- case TCIOFF:
- if (GetCommState (get_handle (), &dcb) == 0)
- return -1;
- if (action == TCION)
- xchar = (dcb.XonChar ? dcb.XonChar : 0x11);
- else
- xchar = (dcb.XoffChar ? dcb.XoffChar : 0x13);
- if (TransmitCommChar (get_handle (), xchar) == 0)
- return -1;
- return 0;
- break;
- default:
+ case TCOOFF:
+ win32action = SETXOFF;
+ break;
+ case TCOON:
+ win32action = SETXON;
+ break;
+ case TCION:
+ case TCIOFF:
+ if (GetCommState (get_handle (), &dcb) == 0)
return -1;
- break;
+ if (action == TCION)
+ xchar = (dcb.XonChar ? dcb.XonChar : 0x11);
+ else
+ xchar = (dcb.XoffChar ? dcb.XoffChar : 0x13);
+ if (TransmitCommChar (get_handle (), xchar) == 0)
+ return -1;
+ return 0;
+ break;
+ default:
+ return -1;
+ break;
}
if (EscapeCommFunction (get_handle (), win32action) == 0)
@@ -530,8 +530,8 @@ fhandler_serial::tcsetattr (int action, const struct termios *t)
COMMTIMEOUTS to;
DCB ostate, state;
unsigned int ovtime = vtime_, ovmin = vmin_;
- int tmpDtr, tmpRts;
- tmpDtr = tmpRts = 0;
+ int tmpDtr, tmpRts, res;
+ res = tmpDtr = tmpRts = 0;
termios_printf ("action %d", action);
if ((action == TCSADRAIN) || (action == TCSAFLUSH))
@@ -554,75 +554,76 @@ fhandler_serial::tcsetattr (int action, const struct termios *t)
switch (t->c_ospeed)
{
- case B0: /* drop DTR */
- dropDTR = TRUE;
- state.BaudRate = 0;
- break;
- case B110:
- state.BaudRate = CBR_110;
- break;
- case B300:
- state.BaudRate = CBR_300;
- break;
- case B600:
- state.BaudRate = CBR_600;
- break;
- case B1200:
- state.BaudRate = CBR_1200;
- break;
- case B2400:
- state.BaudRate = CBR_2400;
- break;
- case B4800:
- state.BaudRate = CBR_4800;
- break;
- case B9600:
- state.BaudRate = CBR_9600;
- break;
- case B19200:
- state.BaudRate = CBR_19200;
- break;
- case B38400:
- state.BaudRate = CBR_38400;
- break;
- case B57600:
- state.BaudRate = CBR_57600;
- break;
- case B115200:
- state.BaudRate = CBR_115200;
- break;
- case B230400:
- state.BaudRate = 230400 /* CBR_230400 - not defined */;
- break;
- default:
- /* Unsupported baud rate! */
- termios_printf ("Invalid t->c_ospeed %d", t->c_ospeed);
- set_errno (EINVAL);
- return -1;
+ case B0:
+ /* Drop DTR - but leave DCB-resident bitrate as-is since
+ 0 is an invalid bitrate in Win32 */
+ dropDTR = TRUE;
+ break;
+ case B110:
+ state.BaudRate = CBR_110;
+ break;
+ case B300:
+ state.BaudRate = CBR_300;
+ break;
+ case B600:
+ state.BaudRate = CBR_600;
+ break;
+ case B1200:
+ state.BaudRate = CBR_1200;
+ break;
+ case B2400:
+ state.BaudRate = CBR_2400;
+ break;
+ case B4800:
+ state.BaudRate = CBR_4800;
+ break;
+ case B9600:
+ state.BaudRate = CBR_9600;
+ break;
+ case B19200:
+ state.BaudRate = CBR_19200;
+ break;
+ case B38400:
+ state.BaudRate = CBR_38400;
+ break;
+ case B57600:
+ state.BaudRate = CBR_57600;
+ break;
+ case B115200:
+ state.BaudRate = CBR_115200;
+ break;
+ case B230400:
+ state.BaudRate = 230400 /* CBR_230400 - not defined */;
+ break;
+ default:
+ /* Unsupported baud rate! */
+ termios_printf ("Invalid t->c_ospeed %d", t->c_ospeed);
+ set_errno (EINVAL);
+ return -1;
}
/* -------------- Set byte size ------------------ */
switch (t->c_cflag & CSIZE)
{
- case CS5:
- state.ByteSize = 5;
- break;
- case CS6:
- state.ByteSize = 6;
- break;
- case CS7:
- state.ByteSize = 7;
- break;
- case CS8:
- state.ByteSize = 8;
- break;
- default:
- /* Unsupported byte size! */
- termios_printf ("Invalid t->c_cflag byte size %d",
- t->c_cflag & CSIZE);
- set_errno (EINVAL);
- return -1;
+ case CS5:
+ state.ByteSize = 5;
+ break;
+ case CS6:
+ state.ByteSize = 6;
+ break;
+ case CS7:
+ state.ByteSize = 7;
+ break;
+ case CS8:
+ state.ByteSize = 8;
+ break;
+ default:
+ /* Unsupported byte size! */
+ termios_printf ("Invalid t->c_cflag byte size %d",
+ t->c_cflag & CSIZE);
+ set_errno (EINVAL);
+ return -1;
}
/* -------------- Set stop bits ------------------ */
@@ -725,8 +726,16 @@ fhandler_serial::tcsetattr (int action, const struct termios *t)
state.fAbortOnError = TRUE;
- if (memcmp (&ostate, &state, sizeof (state)) != 0)
- SetCommState (get_handle (), &state);
+ if ((memcmp (&ostate, &state, sizeof (state)) != 0)
+ && !SetCommState (get_handle (), &state))
+ {
+ /* SetCommState() failed, usually due to invalid DCB param.
+ Keep track of this so we can set errno to EINVAL later
+ and return failure */
+ termios_printf ("SetCommState() failed, %E");
+ __seterrno ();
+ res = -1;
+ }
set_r_binary ((t->c_iflag & IGNCR) ? 0 : 1);
set_w_binary ((t->c_oflag & ONLCR) ? 0 : 1);
@@ -750,8 +759,7 @@ fhandler_serial::tcsetattr (int action, const struct termios *t)
rts = tmpRts;
dtr = tmpDtr;
- /*
- The following documentation on was taken from "Linux Serial Programming
+ /* The following documentation on was taken from "Linux Serial Programming
HOWTO". It explains how MIN (t->c_cc[VMIN] || vmin_) and TIME
(t->c_cc[VTIME] || vtime_) is to be used.
@@ -794,49 +802,51 @@ fhandler_serial::tcsetattr (int action, const struct termios *t)
debug_printf ("vtime %d, vmin %d", vtime_, vmin_);
- if (ovmin == vmin_ && ovtime == vtime_)
- return 0;
+ if (ovmin != vmin_ || ovtime != vtime_)
+ {
+ memset (&to, 0, sizeof (to));
- memset (&to, 0, sizeof (to));
+ if ((vmin_ > 0) && (vtime_ == 0))
+ {
+ /* Returns immediately with whatever is in buffer on a ReadFile();
+ or blocks if nothing found. We will keep calling ReadFile(); until
+ vmin_ characters are read */
+ to.ReadIntervalTimeout = to.ReadTotalTimeoutMultiplier = MAXDWORD;
+ to.ReadTotalTimeoutConstant = MAXDWORD - 1;
+ }
+ else if ((vmin_ == 0) && (vtime_ > 0))
+ {
+ /* set timeoout constant appropriately and we will only try to
+ read one character in ReadFile() */
+ to.ReadTotalTimeoutConstant = vtime_;
+ to.ReadIntervalTimeout = to.ReadTotalTimeoutMultiplier = MAXDWORD;
+ }
+ else if ((vmin_ > 0) && (vtime_ > 0))
+ {
+ /* time applies to the interval time for this case */
+ to.ReadIntervalTimeout = vtime_;
+ }
+ else if ((vmin_ == 0) && (vtime_ == 0))
+ {
+ /* returns immediately with whatever is in buffer as per
+ Time-Outs docs in Win32 SDK API docs */
+ to.ReadIntervalTimeout = MAXDWORD;
+ }
- if ((vmin_ > 0) && (vtime_ == 0))
- {
- /* Returns immediately with whatever is in buffer on a ReadFile();
- or blocks if nothing found. We will keep calling ReadFile(); until
- vmin_ characters are read */
- to.ReadIntervalTimeout = to.ReadTotalTimeoutMultiplier = MAXDWORD;
- to.ReadTotalTimeoutConstant = MAXDWORD - 1;
- }
- else if ((vmin_ == 0) && (vtime_ > 0))
- {
- /* set timeoout constant appropriately and we will only try to
- read one character in ReadFile() */
- to.ReadTotalTimeoutConstant = vtime_;
- to.ReadIntervalTimeout = to.ReadTotalTimeoutMultiplier = MAXDWORD;
- }
- else if ((vmin_ > 0) && (vtime_ > 0))
- {
- /* time applies to the interval time for this case */
- to.ReadIntervalTimeout = vtime_;
- }
- else if ((vmin_ == 0) && (vtime_ == 0))
- {
- /* returns immediately with whatever is in buffer as per
- Time-Outs docs in Win32 SDK API docs */
- to.ReadIntervalTimeout = MAXDWORD;
- }
+ debug_printf ("ReadTotalTimeoutConstant %d, ReadIntervalTimeout %d, ReadTotalTimeoutMultiplier %d",
+ to.ReadTotalTimeoutConstant, to.ReadIntervalTimeout, to.ReadTotalTimeoutMultiplier);
- debug_printf ("ReadTotalTimeoutConstant %d, ReadIntervalTimeout %d, ReadTotalTimeoutMultiplier %d",
- to.ReadTotalTimeoutConstant, to.ReadIntervalTimeout, to.ReadTotalTimeoutMultiplier);
- int res = SetCommTimeouts (get_handle (), &to);
- if (!res)
- {
- system_printf ("SetCommTimeout failed, %E");
- __seterrno ();
- return -1;
- }
+ if (!SetCommTimeouts(get_handle (), &to))
+ {
+ /* SetCommTimeouts() failed. Keep track of this so we
+ can set errno to EINVAL later and return failure */
+ termios_printf ("SetCommTimeouts() failed, %E");
+ __seterrno ();
+ res = -1;
+ }
+ }
- return 0;
+ return res;
}
/* tcgetattr: POSIX 7.2.1.1 */
@@ -854,12 +864,12 @@ fhandler_serial::tcgetattr (struct termios *t)
/* -------------- Baud rate ------------------ */
- switch (state.BaudRate)
- {
- case 0:
- /* FIXME: need to drop DTR */
- t->c_cflag = t->c_ospeed = t->c_ispeed = B0;
- break;
+ /* If DTR is NOT set, return B0 as our speed */
+ if (dtr != TIOCM_DTR)
+ t->c_cflag = t->c_ospeed = t->c_ispeed = B0;
+ else
+ switch (state.BaudRate)
+ {
case CBR_110:
t->c_cflag = t->c_ospeed = t->c_ispeed = B110;
break;
@@ -901,29 +911,29 @@ fhandler_serial::tcgetattr (struct termios *t)
termios_printf ("Invalid baud rate %d", state.BaudRate);
set_errno (EINVAL);
return -1;
- }
+ }
/* -------------- Byte size ------------------ */
switch (state.ByteSize)
{
- case 5:
- t->c_cflag |= CS5;
- break;
- case 6:
- t->c_cflag |= CS6;
- break;
- case 7:
- t->c_cflag |= CS7;
- break;
- case 8:
- t->c_cflag |= CS8;
- break;
- default:
- /* Unsupported byte size! */
- termios_printf ("Invalid byte size %d", state.ByteSize);
- set_errno (EINVAL);
- return -1;
+ case 5:
+ t->c_cflag |= CS5;
+ break;
+ case 6:
+ t->c_cflag |= CS6;
+ break;
+ case 7:
+ t->c_cflag |= CS7;
+ break;
+ case 8:
+ t->c_cflag |= CS8;
+ break;
+ default:
+ /* Unsupported byte size! */
+ termios_printf ("Invalid byte size %d", state.ByteSize);
+ set_errno (EINVAL);
+ return -1;
}
/* -------------- Stop bits ------------------ */
diff --git a/winsup/cygwin/termios.cc b/winsup/cygwin/termios.cc
new file mode 100644
index 00000000000..ac1c89bf0a8
--- /dev/null
+++ b/winsup/cygwin/termios.cc
@@ -0,0 +1,268 @@
+/* termios.cc: termios for WIN32.
+
+ Copyright 1996, 1997, 1998, 2000, 2001, 2002 Red Hat, Inc.
+
+ Written by Doug Evans and Steve Chamberlain of Cygnus Support
+ dje@cygnus.com, sac@cygnus.com
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#include "winsup.h"
+#include <errno.h>
+#include <signal.h>
+#include <stdlib.h>
+#include "cygerrno.h"
+#include "security.h"
+#include "fhandler.h"
+#include "path.h"
+#include "dtable.h"
+#include "cygheap.h"
+#include "cygwin/version.h"
+#include "perprocess.h"
+#include "sigproc.h"
+#include <sys/termios.h>
+
+/* tcsendbreak: POSIX 7.2.2.1 */
+extern "C" int
+tcsendbreak (int fd, int duration)
+{
+ int res = -1;
+
+ cygheap_fdget cfd (fd);
+ if (cfd < 0)
+ goto out;
+
+ if (!cfd->is_tty ())
+ set_errno (ENOTTY);
+ else if ((res = cfd->bg_check (-SIGTTOU)) > bg_eof)
+ res = cfd->tcsendbreak (duration);
+
+out:
+ syscall_printf ("%d = tcsendbreak (%d, %d)", res, fd, duration);
+ return res;
+}
+
+/* tcdrain: POSIX 7.2.2.1 */
+extern "C" int
+tcdrain (int fd)
+{
+ int res = -1;
+
+ termios_printf ("tcdrain");
+
+ cygheap_fdget cfd (fd);
+ if (cfd < 0)
+ goto out;
+
+ if (!cfd->is_tty ())
+ set_errno (ENOTTY);
+ else if ((res = cfd->bg_check (-SIGTTOU)) > bg_eof)
+ res = cfd->tcdrain ();
+
+out:
+ syscall_printf ("%d = tcdrain (%d)", res, fd);
+ return res;
+}
+
+/* tcflush: POSIX 7.2.2.1 */
+extern "C" int
+tcflush (int fd, int queue)
+{
+ int res = -1;
+
+ cygheap_fdget cfd (fd);
+ if (cfd < 0)
+ goto out;
+
+ if (!cfd->is_tty ())
+ set_errno (ENOTTY);
+ else if ((res = cfd->bg_check (-SIGTTOU)) > bg_eof)
+ res = cfd->tcflush (queue);
+
+out:
+ termios_printf ("%d = tcflush (%d, %d)", res, fd, queue);
+ return res;
+}
+
+/* tcflow: POSIX 7.2.2.1 */
+extern "C" int
+tcflow (int fd, int action)
+{
+ int res = -1;
+
+ cygheap_fdget cfd (fd);
+ if (cfd < 0)
+ goto out;
+
+ if (!cfd->is_tty ())
+ set_errno (ENOTTY);
+ else if ((res = cfd->bg_check (-SIGTTOU)) > bg_eof)
+ res = cfd->tcflow (action);
+
+out:
+ syscall_printf ("%d = tcflow (%d, %d)", res, fd, action);
+ return res;
+}
+
+/* tcsetattr: POSIX96 7.2.1.1 */
+extern "C" int
+tcsetattr (int fd, int a, const struct termios *t)
+{
+ int res;
+ t = __tonew_termios (t);
+ int e = get_errno ();
+
+ while (1)
+ {
+ sigframe thisframe (mainthread);
+
+ res = -1;
+ cygheap_fdget cfd (fd);
+ if (cfd < 0)
+ {
+ e = get_errno ();
+ break;
+ }
+
+ if (!cfd->is_tty ())
+ {
+ e = ENOTTY;
+ break;
+ }
+
+ res = cfd->bg_check (-SIGTTOU);
+
+ switch (res)
+ {
+ case bg_eof:
+ e = get_errno ();
+ break;
+ case bg_ok:
+ if (cfd.isopen ())
+ res = cfd->tcsetattr (a, t);
+ e = get_errno ();
+ break;
+ case bg_signalled:
+ if (thisframe.call_signal_handler ())
+ continue;
+ res = -1;
+ /* fall through intentionally */
+ default:
+ e = get_errno ();
+ break;
+ }
+ break;
+ }
+
+ set_errno (e);
+ termios_printf ("iflag %p, oflag %p, cflag %p, lflag %p, VMIN %d, VTIME %d",
+ t->c_iflag, t->c_oflag, t->c_cflag, t->c_lflag, t->c_cc[VMIN],
+ t->c_cc[VTIME]);
+ termios_printf ("%d = tcsetattr (%d, %d, %x)", res, fd, a, t);
+ return res;
+}
+
+/* tcgetattr: POSIX 7.2.1.1 */
+extern "C" int
+tcgetattr (int fd, struct termios *in_t)
+{
+ int res = -1;
+ struct termios *t = __makenew_termios (in_t);
+
+ cygheap_fdget cfd (fd);
+ if (cfd < 0)
+ /* saw an error */;
+ else if (!cfd->is_tty ())
+ set_errno (ENOTTY);
+ else if ((res = cfd->tcgetattr (t)) == 0)
+ (void) __toapp_termios (in_t, t);
+
+ if (res)
+ termios_printf ("%d = tcgetattr (%d, %p)", res, fd, in_t);
+ else
+ termios_printf ("iflag %x, oflag %x, cflag %x, lflag %x, VMIN %d, VTIME %d",
+ t->c_iflag, t->c_oflag, t->c_cflag, t->c_lflag, t->c_cc[VMIN],
+ t->c_cc[VTIME]);
+
+ return res;
+}
+
+/* tcgetpgrp: POSIX 7.2.3.1 */
+extern "C" int
+tcgetpgrp (int fd)
+{
+ int res = -1;
+
+ cygheap_fdget cfd (fd);
+ if (cfd < 0)
+ /* saw an error */;
+ else if (!cfd->is_tty ())
+ set_errno (ENOTTY);
+ else
+ res = cfd->tcgetpgrp ();
+
+ termios_printf ("%d = tcgetpgrp (%d)", res, fd);
+ return res;
+}
+
+/* tcsetpgrp: POSIX 7.2.4.1 */
+extern "C" int
+tcsetpgrp (int fd, pid_t pgid)
+{
+ int res = -1;
+
+ cygheap_fdget cfd (fd);
+ if (cfd < 0)
+ /* saw an error */;
+ else if (!cfd->is_tty ())
+ set_errno (ENOTTY);
+ else
+ res = cfd->tcsetpgrp (pgid);
+
+ termios_printf ("%d = tcsetpgrp (%d, %x)", res, fd, pgid);
+ return res;
+}
+
+/* NIST PCTS requires not macro-only implementation */
+#undef cfgetospeed
+#undef cfgetispeed
+#undef cfsetospeed
+#undef cfsetispeed
+
+/* cfgetospeed: POSIX96 7.1.3.1 */
+extern "C" speed_t
+cfgetospeed (struct termios *tp)
+{
+ return __tonew_termios (tp)->c_ospeed;
+}
+
+/* cfgetispeed: POSIX96 7.1.3.1 */
+extern "C" speed_t
+cfgetispeed (struct termios *tp)
+{
+ return __tonew_termios (tp)->c_ispeed;
+}
+
+/* cfsetospeed: POSIX96 7.1.3.1 */
+extern "C" int
+cfsetospeed (struct termios *in_tp, speed_t speed)
+{
+ struct termios *tp = __tonew_termios (in_tp);
+ tp->c_ospeed = speed;
+ (void) __toapp_termios (in_tp, tp);
+ return 0;
+}
+
+/* cfsetispeed: POSIX96 7.1.3.1 */
+extern "C" int
+cfsetispeed (struct termios *in_tp, speed_t speed)
+{
+ struct termios *tp = __tonew_termios (in_tp);
+ tp->c_ispeed = speed;
+ (void) __toapp_termios (in_tp, tp);
+ return 0;
+}