summaryrefslogtreecommitdiff
path: root/libc/termios/termios.c
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2001-01-15 18:16:14 +0000
committerEric Andersen <andersen@codepoet.org>2001-01-15 18:16:14 +0000
commit6fce1235bea41b65a0b7a978c65b908c736365d4 (patch)
tree87f187b31b047b77f09d7581affbe2a032b36ced /libc/termios/termios.c
parent5d83a25c29718b926ed547abf9131ffbbd35bc95 (diff)
Fix termios handling. Now synced with behavior of GNU libc.
-Erik
Diffstat (limited to 'libc/termios/termios.c')
-rw-r--r--libc/termios/termios.c402
1 files changed, 173 insertions, 229 deletions
diff --git a/libc/termios/termios.c b/libc/termios/termios.c
index 6781f32fd..9bfcf1171 100644
--- a/libc/termios/termios.c
+++ b/libc/termios/termios.c
@@ -1,12 +1,28 @@
-/* Copyright (C) 1996 Robert de Bath <robert@mayday.compulink.co.uk> This
- * file is part of the Linux-8086 C library and is distributed under the
- * GNU Library General Public License.
+/* Copyright (C) 1992, 1993, 1996, 1997, 1998 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+
+ About the only thing remaining here fromthe original Linux-8086 C library
+ version by Robert de Bath <robert@mayday.compulink.co.uk>, is the general
+ layout. All else has been recently stolen from GNU libc, since that was
+ much more current.
*/
-/* Note: This is based loosely on the Glib termios routines. */
-
-#ifndef __MSDOS__
-
#include <errno.h>
#include <stddef.h>
#include <sys/ioctl.h>
@@ -14,82 +30,43 @@
#include <unistd.h>
#ifdef L_isatty
+/* Return 1 if FD is a terminal, 0 if not. */
int isatty(int fd)
{
- struct termios term;
- int rv, err = errno;
-
- rv = (ioctl(fd, TCGETS, &term) == 0);
- if (rv == 0 && errno == ENOSYS)
- rv = (fd < 3);
- errno = err;
- return rv;
-}
-#endif
+ struct termios term;
-#ifdef L_tcgetattr
-int tcgetattr(fd, term)
-int fd;
-struct termios *term;
-{
- return ioctl(fd, TCGETS, term);
-}
-#endif
-
-#ifdef L_tcsetattr
-int tcsetattr(fildes, optional_actions, termios_p)
-int fildes;
-int optional_actions;
-struct termios *termios_p;
-{
- switch (optional_actions) {
- case TCSANOW:
- return ioctl(fildes, TCSETS, termios_p);
- case TCSADRAIN:
- return ioctl(fildes, TCSETSW, termios_p);
- case TCSAFLUSH:
- return ioctl(fildes, TCSETSF, termios_p);
- default:
- errno = EINVAL;
- return -1;
- }
+ return tcgetattr(fd, &term) == 0;
}
#endif
#ifdef L_tcdrain
/* Wait for pending output to be written on FD. */
-int tcdrain(fd)
-int fd;
+int tcdrain (int fd)
{
- /* With an argument of 1, TCSBRK just waits for output to drain. */
- return ioctl(fd, TCSBRK, 1);
+ /* With an argument of 1, TCSBRK waits for the output to drain. */
+ return ioctl(fd, TCSBRK, 1);
}
#endif
#ifdef L_tcflow
-int tcflow(fd, action)
-int fd;
-int action;
+/* Suspend or restart transmission on FD. */
+int tcflow ( int fd, int action)
{
- return ioctl(fd, TCXONC, action);
+ return ioctl(fd, TCXONC, action);
}
#endif
#ifdef L_tcflush
/* Flush pending data on FD. */
-int tcflush(fd, queue_selector)
-int fd;
-int queue_selector;
+int tcflush ( int fd, int queue_selector)
{
- return ioctl(fd, TCFLSH, queue_selector);
+ return ioctl(fd, TCFLSH, queue_selector);
}
#endif
#ifdef L_tcsendbreak
/* Send zero bits on FD. */
-int tcsendbreak(fd, duration)
-int fd;
-int duration;
+int tcsendbreak( int fd, int duration)
{
/*
* The break lasts 0.25 to 0.5 seconds if DURATION is zero, and an
@@ -111,260 +88,227 @@ int duration;
#ifdef L_tcsetpgrp
/* Set the foreground process group ID of FD set PGRP_ID. */
-int tcsetpgrp(fd, pgrp_id)
-int fd;
-pid_t pgrp_id;
+int tcsetpgrp ( int fd, pid_t pgrp_id)
{
- return ioctl(fd, TIOCSPGRP, &pgrp_id);
+ return ioctl (fd, TIOCSPGRP, &pgrp_id);
}
#endif
#ifdef L_tcgetpgrp
/* Return the foreground process group ID of FD. */
-pid_t tcgetpgrp(fd)
-int fd;
+pid_t tcgetpgrp ( int fd)
{
- int pgrp;
+ int pgrp;
- if (ioctl(fd, TIOCGPGRP, &pgrp) < 0)
- return (pid_t) - 1;
- return (pid_t) pgrp;
+ if (ioctl (fd, TIOCGPGRP, &pgrp) < 0)
+ return (pid_t) -1;
+ return (pid_t) pgrp;
}
#endif
+/* This is a gross hack around a kernel bug. If the cfsetispeed functions is
+ * called with the SPEED argument set to zero this means use the same speed as
+ * for output. But we don't have independent input and output speeds and
+ * therefore cannot record this.
+ *
+ * We use an unused bit in the `c_iflag' field to keep track of this use of
+ * `cfsetispeed'. The value here must correspond to the one used in
+ * `tcsetattr.c'. */
+#define IBAUD0 020000000000
+
#ifdef L_cfgetospeed
-speed_t cfgetospeed(tp)
-struct termios *tp;
+/* Return the output baud rate stored in *TERMIOS_P. */
+speed_t cfgetospeed ( const struct termios *termios_p)
{
- return (tp->c_cflag & CBAUD);
+ return termios_p->c_cflag & (CBAUD | CBAUDEX);
}
#endif
#ifdef L_cfgetispeed
-speed_t cfgetispeed(tp)
-struct termios *tp;
+
+/* Return the input baud rate stored in *TERMIOS_P.
+ * Although for Linux there is no difference between input and output
+ * speed, the numerical 0 is a special case for the input baud rate. It
+ * should set the input baud rate to the output baud rate. */
+speed_t cfgetispeed (const struct termios *termios_p)
{
- return (tp->c_cflag & CBAUD);
+ return ((termios_p->c_iflag & IBAUD0)
+ ? 0 : termios_p->c_cflag & (CBAUD | CBAUDEX));
}
#endif
#ifdef L_cfsetospeed
-int cfsetospeed(tp, speed)
-struct termios *tp;
-speed_t speed;
+/* Set the output baud rate stored in *TERMIOS_P to SPEED. */
+int cfsetospeed (struct termios *termios_p, speed_t speed)
{
-#ifdef CBAUDEX
- if ((speed & ~CBAUD) ||
- ((speed & CBAUDEX) && (speed < B57600 || speed > B115200)))
- return 0;
-#else
- if (speed & ~CBAUD)
- return 0;
-#endif
- tp->c_cflag &= ~CBAUD;
- tp->c_cflag |= speed;
+ if ((speed & ~CBAUD) != 0
+ && (speed < B57600 || speed > B460800))
+ {
+ errno=EINVAL;
+ return -1;
+ }
- return 0;
+ termios_p->c_cflag &= ~(CBAUD | CBAUDEX);
+ termios_p->c_cflag |= speed;
+
+ return 0;
}
#endif
#ifdef L_cfsetispeed
-int cfsetispeed(tp, speed)
-struct termios *tp;
-speed_t speed;
+/* Set the input baud rate stored in *TERMIOS_P to SPEED.
+ * Although for Linux there is no difference between input and output
+ * speed, the numerical 0 is a special case for the input baud rate. It
+ * should set the input baud rate to the output baud rate. */
+int cfsetispeed ( struct termios *termios_p, speed_t speed)
{
- return cfsetospeed(tp, speed);
+ if ((speed & ~CBAUD) != 0
+ && (speed < B57600 || speed > B460800))
+ {
+ errno=EINVAL;
+ return -1;
+ }
+
+ if (speed == 0)
+ termios_p->c_iflag |= IBAUD0;
+ else
+ {
+ termios_p->c_iflag &= ~IBAUD0;
+ termios_p->c_cflag &= ~(CBAUD | CBAUDEX);
+ termios_p->c_cflag |= speed;
+ }
+
+ return 0;
}
#endif
-#if 0
-
-/* Not POSIX standard, not worth the bother to keep it up */
-
#ifdef L_tcspeed
-static struct {
- int number;
- speed_t code;
-} tcspeeds[] = {
+struct speed_struct
+{
+ speed_t value;
+ speed_t internal;
+};
+
+static const struct speed_struct speeds[] =
+ {
+#ifdef B0
+ { 0, B0 },
+#endif
#ifdef B50
- {
- 50, B50},
+ { 50, B50 },
#endif
#ifdef B75
- {
- 75, B75},
+ { 75, B75 },
#endif
#ifdef B110
- {
- 110, B110},
+ { 110, B110 },
#endif
#ifdef B134
- {
- 134, B134},
+ { 134, B134 },
#endif
#ifdef B150
- {
- 150, B150},
+ { 150, B150 },
#endif
#ifdef B200
- {
- 200, B200},
+ { 200, B200 },
#endif
#ifdef B300
- {
- 300, B300},
+ { 300, B300 },
#endif
#ifdef B600
- {
- 600, B600},
+ { 600, B600 },
#endif
#ifdef B1200
- {
- 1200, B1200},
+ { 1200, B1200 },
+#endif
+#ifdef B1200
+ { 1200, B1200 },
#endif
#ifdef B1800
- {
- 1800, B1800},
+ { 1800, B1800 },
#endif
#ifdef B2400
- {
- 2400, B2400},
+ { 2400, B2400 },
#endif
#ifdef B4800
- {
- 4800, B4800},
+ { 4800, B4800 },
#endif
#ifdef B9600
- {
- 9600, B9600},
+ { 9600, B9600 },
#endif
#ifdef B19200
- {
- 19200, B19200},
+ { 19200, B19200 },
#endif
#ifdef B38400
- {
- 38400, B38400},
+ { 38400, B38400 },
#endif
#ifdef B57600
- {
- 57600, B57600},
+ { 57600, B57600 },
+#endif
+#ifdef B76800
+ { 76800, B76800 },
#endif
#ifdef B115200
- {
- 115200, B115200},
+ { 115200, B115200 },
+#endif
+#ifdef B153600
+ { 153600, B153600 },
#endif
#ifdef B230400
- {
- 230400, B230400},
+ { 230400, B230400 },
#endif
-#ifdef B460800
- {
- 460800, B460800},
+#ifdef B307200
+ { 307200, B307200 },
#endif
-#ifdef B0
- {
- 0, B0},
+#ifdef B460800
+ { 460800, B460800 },
#endif
- {
- 0, 0}
-};
-
-int tcspeed_to_number(code)
-speed_t code;
-{
- int i;
+ };
- code &= CBAUD;
- for (i = 0; tcspeeds[i].code; i++)
- if (tcspeeds[i].code == code)
- return tcspeeds[i].number;
- return 0;
-}
-speed_t tcspeed_from_number(number)
-int number;
+/* Set both the input and output baud rates stored in *TERMIOS_P to SPEED. */
+int cfsetspeed (struct termios *termios_p, speed_t speed)
{
- int i;
-
- for (i = 0; tcspeeds[i].code; i++)
- if (tcspeeds[i].number == number)
- return tcspeeds[i].code;
- return B0;
-}
-#endif
+ size_t cnt;
-#ifdef L_cfgetospeedn
-int cfgetospeedn(tp)
-struct termios *tp;
-{
- return tcspeed_to_number(cfgetospeed(tp));
-}
-#endif
-
-#ifdef L_cfgetispeedn
-int cfgetispeedn(tp)
-struct termios *tp;
-{
- return tcspeed_to_number(cfgetispeed(tp));
-}
-#endif
+ for (cnt = 0; cnt < sizeof (speeds) / sizeof (speeds[0]); ++cnt)
+ if (speed == speeds[cnt].internal)
+ {
+ cfsetispeed (termios_p, speed);
+ cfsetospeed (termios_p, speed);
+ return 0;
+ }
+ else if (speed == speeds[cnt].value)
+ {
+ cfsetispeed (termios_p, speeds[cnt].internal);
+ cfsetospeed (termios_p, speeds[cnt].internal);
+ return 0;
+ }
-#ifdef L_cfsetospeedn
-int cfsetospeedn(tp, speed)
-struct termios *tp;
-int speed;
-{
- return cfsetospeed(tp, tcspeed_from_number(speed));
-}
-#endif
+ __set_errno (EINVAL);
-#ifdef L_cfsetispeedn
-int cfsetispeedn(tp, speed)
-struct termios *tp;
-int speed;
-{
- return cfsetispeedn(tp, tcspeed_from_number(speed));
+ return -1;
}
#endif
-#endif
-
-/* From linux libc-4.6.27 again */
#ifdef L_cfmakeraw
-/* Copyright (C) 1992 Free Software Foundation, Inc.
-This file is part of the GNU C Library.*/
+/* Copyright (C) 1992, 1996, 1997 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+*/
+#include <termios.h>
-void cfmakeraw(t)
-struct termios *t;
+/* Set *T to indicate raw mode. */
+void
+cfmakeraw (t)
+ struct termios *t;
{
-/* I changed it to the current form according to the suggestions
- * from Bruce Evans. Thanks Bruce. Please report the problems to
- * H.J. Lu (hlu@eecs.wsu.edu).
- */
-
-/*
- * I took out the bits commented out by #if 1...#else - RHP
- */
-
- /* VMIN = 0 means non-blocking for Linux */
- t->c_cc[VMIN] = 1;
- t->c_cc[VTIME] = 1;
- /* clear some bits with &= ~(bits), set others with |= */
- t->c_cflag &= ~(CSIZE | PARENB | CSTOPB);
- t->c_cflag |= (CS8 | HUPCL | CREAD);
- t->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | INPCK | ISTRIP);
- t->c_iflag &= ~(INLCR | IGNCR | ICRNL | IXON | IXOFF);
- t->c_iflag |= (BRKINT | IGNPAR);
- t->c_oflag &=
- ~(OPOST | OLCUC | OCRNL | ONOCR | ONLRET | OFILL | OFDEL);
- t->c_oflag &= ~(NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY);
- t->c_oflag |= (ONLCR | NL0 | CR0 | TAB3 | BS0 | VT0 | FF0);
- t->c_lflag &=
- ~(ISIG | ICANON | IEXTEN | ECHO | ECHOE | ECHOK | ECHONL);
- t->c_lflag &= ~(NOFLSH | XCASE);
- t->c_lflag &= ~(ECHOPRT | ECHOCTL | ECHOKE);
+ t->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+ t->c_oflag &= ~OPOST;
+ t->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+ t->c_cflag &= ~(CSIZE|PARENB);
+ t->c_cflag |= CS8;
+ t->c_cc[VMIN] = 1; /* read returns when one char is available. */
+ t->c_cc[VTIME] = 0;
}
#endif
-#endif