diff options
author | Eric Andersen <andersen@codepoet.org> | 2001-01-15 18:16:14 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2001-01-15 18:16:14 +0000 |
commit | 6fce1235bea41b65a0b7a978c65b908c736365d4 (patch) | |
tree | 87f187b31b047b77f09d7581affbe2a032b36ced /libc | |
parent | 5d83a25c29718b926ed547abf9131ffbbd35bc95 (diff) |
Fix termios handling. Now synced with behavior of GNU libc.
-Erik
Diffstat (limited to 'libc')
-rw-r--r-- | libc/sysdeps/linux/arm/bits/termios.h | 212 | ||||
-rw-r--r-- | libc/sysdeps/linux/common/syscalls.c | 6 | ||||
-rw-r--r-- | libc/sysdeps/linux/i386/bits/termios.h | 212 | ||||
-rw-r--r-- | libc/termios/Makefile | 9 | ||||
-rw-r--r-- | libc/termios/kernel_termios.h | 35 | ||||
-rw-r--r-- | libc/termios/tcgetattr.c | 67 | ||||
-rw-r--r-- | libc/termios/tcgetsid.c | 64 | ||||
-rw-r--r-- | libc/termios/tcsetattr.c | 120 | ||||
-rw-r--r-- | libc/termios/termios.c | 402 |
9 files changed, 891 insertions, 236 deletions
diff --git a/libc/sysdeps/linux/arm/bits/termios.h b/libc/sysdeps/linux/arm/bits/termios.h new file mode 100644 index 000000000..a5ba1d258 --- /dev/null +++ b/libc/sysdeps/linux/arm/bits/termios.h @@ -0,0 +1,212 @@ +/* termios type and macro definitions. Linux version. + Copyright (C) 1993, 94, 95, 96, 97, 98, 99 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. */ + +#ifndef _TERMIOS_H +# error "Never include <bits/termios.h> directly; use <termios.h> instead." +#endif + +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned int tcflag_t; + +#define NCCS 32 +struct termios + { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ + }; + +/* c_cc characters */ +#define VINTR 0 +#define VQUIT 1 +#define VERASE 2 +#define VKILL 3 +#define VEOF 4 +#define VTIME 5 +#define VMIN 6 +#define VSWTC 7 +#define VSTART 8 +#define VSTOP 9 +#define VSUSP 10 +#define VEOL 11 +#define VREPRINT 12 +#define VDISCARD 13 +#define VWERASE 14 +#define VLNEXT 15 +#define VEOL2 16 + +/* c_iflag bits */ +#define IGNBRK 0000001 +#define BRKINT 0000002 +#define IGNPAR 0000004 +#define PARMRK 0000010 +#define INPCK 0000020 +#define ISTRIP 0000040 +#define INLCR 0000100 +#define IGNCR 0000200 +#define ICRNL 0000400 +#define IUCLC 0001000 +#define IXON 0002000 +#define IXANY 0004000 +#define IXOFF 0010000 +#define IMAXBEL 0020000 + +/* c_oflag bits */ +#define OPOST 0000001 +#define OLCUC 0000002 +#define ONLCR 0000004 +#define OCRNL 0000010 +#define ONOCR 0000020 +#define ONLRET 0000040 +#define OFILL 0000100 +#define OFDEL 0000200 +#if defined __USE_MISC || defined __USE_XOPEN +# define NLDLY 0000400 +# define NL0 0000000 +# define NL1 0000400 +# define CRDLY 0003000 +# define CR0 0000000 +# define CR1 0001000 +# define CR2 0002000 +# define CR3 0003000 +# define TABDLY 0014000 +# define TAB0 0000000 +# define TAB1 0004000 +# define TAB2 0010000 +# define TAB3 0014000 +# define BSDLY 0020000 +# define BS0 0000000 +# define BS1 0020000 +# define FFDLY 0100000 +# define FF0 0000000 +# define FF1 0100000 +#endif + +#define VTDLY 0040000 +#define VT0 0000000 +#define VT1 0040000 + +#ifdef __USE_MISC +# define XTABS 0014000 +#endif + +/* c_cflag bit meaning */ +#ifdef __USE_MISC +# define CBAUD 0010017 +#endif +#define B0 0000000 /* hang up */ +#define B50 0000001 +#define B75 0000002 +#define B110 0000003 +#define B134 0000004 +#define B150 0000005 +#define B200 0000006 +#define B300 0000007 +#define B600 0000010 +#define B1200 0000011 +#define B1800 0000012 +#define B2400 0000013 +#define B4800 0000014 +#define B9600 0000015 +#define B19200 0000016 +#define B38400 0000017 +#ifdef __USE_MISC +# define EXTA B19200 +# define EXTB B38400 +#endif +#define CSIZE 0000060 +#define CS5 0000000 +#define CS6 0000020 +#define CS7 0000040 +#define CS8 0000060 +#define CSTOPB 0000100 +#define CREAD 0000200 +#define PARENB 0000400 +#define PARODD 0001000 +#define HUPCL 0002000 +#define CLOCAL 0004000 +#ifdef __USE_MISC +# define CBAUDEX 0010000 +#endif +#define B57600 0010001 +#define B115200 0010002 +#define B230400 0010003 +#define B460800 0010004 +#define B500000 0010005 +#define B576000 0010006 +#define B921600 0010007 +#define B1000000 0010010 +#define B1152000 0010011 +#define B1500000 0010012 +#define B2000000 0010013 +#define B2500000 0010014 +#define B3000000 0010015 +#define B3500000 0010016 +#define B4000000 0010017 +#ifdef __USE_MISC +# define CIBAUD 002003600000 /* input baud rate (not used) */ +# define CRTSCTS 020000000000 /* flow control */ +#endif + +/* c_lflag bits */ +#define ISIG 0000001 +#define ICANON 0000002 +#if defined __USE_MISC || defined __USE_XOPEN +# define XCASE 0000004 +#endif +#define ECHO 0000010 +#define ECHOE 0000020 +#define ECHOK 0000040 +#define ECHONL 0000100 +#define NOFLSH 0000200 +#define TOSTOP 0000400 +#ifdef __USE_MISC +# define ECHOCTL 0001000 +# define ECHOPRT 0002000 +# define ECHOKE 0004000 +# define FLUSHO 0010000 +# define PENDIN 0040000 +#endif +#define IEXTEN 0100000 + +/* tcflow() and TCXONC use these */ +#define TCOOFF 0 +#define TCOON 1 +#define TCIOFF 2 +#define TCION 3 + +/* tcflush() and TCFLSH use these */ +#define TCIFLUSH 0 +#define TCOFLUSH 1 +#define TCIOFLUSH 2 + +/* tcsetattr uses these */ +#define TCSANOW 0 +#define TCSADRAIN 1 +#define TCSAFLUSH 2 + + +#define _IOT_termios /* Hurd ioctl type field. */ \ + _IOT (_IOTS (cflag_t), 4, _IOTS (cc_t), NCCS, _IOTS (speed_t), 2) diff --git a/libc/sysdeps/linux/common/syscalls.c b/libc/sysdeps/linux/common/syscalls.c index e726ba7fc..534f3779c 100644 --- a/libc/sysdeps/linux/common/syscalls.c +++ b/libc/sysdeps/linux/common/syscalls.c @@ -966,15 +966,15 @@ _syscall2(int,flock,int,fd, int,operation); #ifdef L_writev #include <sys/uio.h> _syscall3(ssize_t, writev, int, filedes, const struct iovec *, vector, int, - count); #endif //#define __NR_getsid 147 #ifdef L_getsid -SYSCALL__(getsid, 1) - ret +#include <unistd.h> +_syscall1(pid_t, getsid, pid_t, pid); #endif + //#define __NR_fdatasync 148 #ifdef L_fdatasync SYSCALL__(fdatasync, 1) diff --git a/libc/sysdeps/linux/i386/bits/termios.h b/libc/sysdeps/linux/i386/bits/termios.h new file mode 100644 index 000000000..a5ba1d258 --- /dev/null +++ b/libc/sysdeps/linux/i386/bits/termios.h @@ -0,0 +1,212 @@ +/* termios type and macro definitions. Linux version. + Copyright (C) 1993, 94, 95, 96, 97, 98, 99 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. */ + +#ifndef _TERMIOS_H +# error "Never include <bits/termios.h> directly; use <termios.h> instead." +#endif + +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned int tcflag_t; + +#define NCCS 32 +struct termios + { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ + }; + +/* c_cc characters */ +#define VINTR 0 +#define VQUIT 1 +#define VERASE 2 +#define VKILL 3 +#define VEOF 4 +#define VTIME 5 +#define VMIN 6 +#define VSWTC 7 +#define VSTART 8 +#define VSTOP 9 +#define VSUSP 10 +#define VEOL 11 +#define VREPRINT 12 +#define VDISCARD 13 +#define VWERASE 14 +#define VLNEXT 15 +#define VEOL2 16 + +/* c_iflag bits */ +#define IGNBRK 0000001 +#define BRKINT 0000002 +#define IGNPAR 0000004 +#define PARMRK 0000010 +#define INPCK 0000020 +#define ISTRIP 0000040 +#define INLCR 0000100 +#define IGNCR 0000200 +#define ICRNL 0000400 +#define IUCLC 0001000 +#define IXON 0002000 +#define IXANY 0004000 +#define IXOFF 0010000 +#define IMAXBEL 0020000 + +/* c_oflag bits */ +#define OPOST 0000001 +#define OLCUC 0000002 +#define ONLCR 0000004 +#define OCRNL 0000010 +#define ONOCR 0000020 +#define ONLRET 0000040 +#define OFILL 0000100 +#define OFDEL 0000200 +#if defined __USE_MISC || defined __USE_XOPEN +# define NLDLY 0000400 +# define NL0 0000000 +# define NL1 0000400 +# define CRDLY 0003000 +# define CR0 0000000 +# define CR1 0001000 +# define CR2 0002000 +# define CR3 0003000 +# define TABDLY 0014000 +# define TAB0 0000000 +# define TAB1 0004000 +# define TAB2 0010000 +# define TAB3 0014000 +# define BSDLY 0020000 +# define BS0 0000000 +# define BS1 0020000 +# define FFDLY 0100000 +# define FF0 0000000 +# define FF1 0100000 +#endif + +#define VTDLY 0040000 +#define VT0 0000000 +#define VT1 0040000 + +#ifdef __USE_MISC +# define XTABS 0014000 +#endif + +/* c_cflag bit meaning */ +#ifdef __USE_MISC +# define CBAUD 0010017 +#endif +#define B0 0000000 /* hang up */ +#define B50 0000001 +#define B75 0000002 +#define B110 0000003 +#define B134 0000004 +#define B150 0000005 +#define B200 0000006 +#define B300 0000007 +#define B600 0000010 +#define B1200 0000011 +#define B1800 0000012 +#define B2400 0000013 +#define B4800 0000014 +#define B9600 0000015 +#define B19200 0000016 +#define B38400 0000017 +#ifdef __USE_MISC +# define EXTA B19200 +# define EXTB B38400 +#endif +#define CSIZE 0000060 +#define CS5 0000000 +#define CS6 0000020 +#define CS7 0000040 +#define CS8 0000060 +#define CSTOPB 0000100 +#define CREAD 0000200 +#define PARENB 0000400 +#define PARODD 0001000 +#define HUPCL 0002000 +#define CLOCAL 0004000 +#ifdef __USE_MISC +# define CBAUDEX 0010000 +#endif +#define B57600 0010001 +#define B115200 0010002 +#define B230400 0010003 +#define B460800 0010004 +#define B500000 0010005 +#define B576000 0010006 +#define B921600 0010007 +#define B1000000 0010010 +#define B1152000 0010011 +#define B1500000 0010012 +#define B2000000 0010013 +#define B2500000 0010014 +#define B3000000 0010015 +#define B3500000 0010016 +#define B4000000 0010017 +#ifdef __USE_MISC +# define CIBAUD 002003600000 /* input baud rate (not used) */ +# define CRTSCTS 020000000000 /* flow control */ +#endif + +/* c_lflag bits */ +#define ISIG 0000001 +#define ICANON 0000002 +#if defined __USE_MISC || defined __USE_XOPEN +# define XCASE 0000004 +#endif +#define ECHO 0000010 +#define ECHOE 0000020 +#define ECHOK 0000040 +#define ECHONL 0000100 +#define NOFLSH 0000200 +#define TOSTOP 0000400 +#ifdef __USE_MISC +# define ECHOCTL 0001000 +# define ECHOPRT 0002000 +# define ECHOKE 0004000 +# define FLUSHO 0010000 +# define PENDIN 0040000 +#endif +#define IEXTEN 0100000 + +/* tcflow() and TCXONC use these */ +#define TCOOFF 0 +#define TCOON 1 +#define TCIOFF 2 +#define TCION 3 + +/* tcflush() and TCFLSH use these */ +#define TCIFLUSH 0 +#define TCOFLUSH 1 +#define TCIOFLUSH 2 + +/* tcsetattr uses these */ +#define TCSANOW 0 +#define TCSADRAIN 1 +#define TCSAFLUSH 2 + + +#define _IOT_termios /* Hurd ioctl type field. */ \ + _IOT (_IOTS (cflag_t), 4, _IOTS (cc_t), NCCS, _IOTS (speed_t), 2) diff --git a/libc/termios/Makefile b/libc/termios/Makefile index f90c5922a..8b1f9e2ea 100644 --- a/libc/termios/Makefile +++ b/libc/termios/Makefile @@ -25,11 +25,12 @@ include $(TOPDIR)Rules.mak LIBC=$(TOPDIR)libc.a MSRC=termios.c -MOBJ=tcsetattr.o tcgetattr.o tcdrain.o tcflow.o tcflush.o tcsendbreak.o \ - tcsetpgrp.o tcgetpgrp.o isatty.o cfgetospeed.o cfgetispeed.o cfsetospeed.o \ - cfsetispeed.o cfmakeraw.o +MOBJ= tcdrain.o tcflow.o tcflush.o tcsendbreak.o tcsetpgrp.o tcgetpgrp.o \ + isatty.o cfgetospeed.o cfgetispeed.o cfsetospeed.o cfsetispeed.o \ + cfmakeraw.o cfsetspeed.o -CSRC=ttyname.c + +CSRC=tcgetattr.c tcgetsid.c tcsetattr.c ttyname.c COBJS=$(patsubst %.c,%.o, $(CSRC)) OBJS=$(MOBJ) $(COBJS) diff --git a/libc/termios/kernel_termios.h b/libc/termios/kernel_termios.h new file mode 100644 index 000000000..09504cc97 --- /dev/null +++ b/libc/termios/kernel_termios.h @@ -0,0 +1,35 @@ +/* Copyright (C) 1997 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. */ + +#ifndef _KERNEL_TERMIOS_H +#define _KERNEL_TERMIOS_H 1 +/* The following corresponds to the values from the Linux 2.1.20 kernel. */ + +#define __KERNEL_NCCS 19 + +struct __kernel_termios + { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[__KERNEL_NCCS]; /* control characters */ + }; + +#endif /* kernel_termios.h */ diff --git a/libc/termios/tcgetattr.c b/libc/termios/tcgetattr.c new file mode 100644 index 000000000..957b5b0c1 --- /dev/null +++ b/libc/termios/tcgetattr.c @@ -0,0 +1,67 @@ +/* Copyright (C) 1992, 1995, 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. */ + +#include <string.h> +#include <termios.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <sys/types.h> + +/* The difference here is that the termios structure used in the + kernel is not the same as we use in the libc. Therefore we must + translate it here. */ +#include "kernel_termios.h" + +/* Put the state of FD into *TERMIOS_P. */ +int tcgetattr ( int fd, struct termios *termios_p) +{ + struct __kernel_termios k_termios; + int retval; + + retval = ioctl (fd, TCGETS, &k_termios); + + termios_p->c_iflag = k_termios.c_iflag; + termios_p->c_oflag = k_termios.c_oflag; + termios_p->c_cflag = k_termios.c_cflag; + termios_p->c_lflag = k_termios.c_lflag; + termios_p->c_line = k_termios.c_line; +#ifdef _HAVE_C_ISPEED + termios_p->c_ispeed = k_termios.c_ispeed; +#endif +#ifdef _HAVE_C_OSPEED + termios_p->c_ospeed = k_termios.c_ospeed; +#endif + if (sizeof (cc_t) == 1 || _POSIX_VDISABLE == 0 + || (unsigned char) _POSIX_VDISABLE == (unsigned char) -1) + memset ( (memcpy (&termios_p->c_cc[0], &k_termios.c_cc[0], + __KERNEL_NCCS * sizeof (cc_t)) + (__KERNEL_NCCS * sizeof (cc_t))) , + _POSIX_VDISABLE, (NCCS - __KERNEL_NCCS) * sizeof (cc_t)); + else + { + size_t cnt; + + memcpy (&termios_p->c_cc[0], &k_termios.c_cc[0], + __KERNEL_NCCS * sizeof (cc_t)); + + for (cnt = __KERNEL_NCCS; cnt < NCCS; ++cnt) + termios_p->c_cc[cnt] = _POSIX_VDISABLE; + } + + return retval; +} + diff --git a/libc/termios/tcgetsid.c b/libc/termios/tcgetsid.c new file mode 100644 index 000000000..35e1c95eb --- /dev/null +++ b/libc/termios/tcgetsid.c @@ -0,0 +1,64 @@ +/* Copyright (C) 1997, 1999 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. */ + +#include <errno.h> +#include <termios.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#define __USE_XOPEN_EXTENDED +#include <unistd.h> + + +/* Return the session ID of FD. */ +pid_t tcgetsid (int fd) +{ + pid_t pgrp; + pid_t sid; +#ifdef TIOCGSID + static int tiocgsid_does_not_work; + + if (! tiocgsid_does_not_work) + { + int serrno = errno; + int sid; + + if (ioctl (fd, TIOCGSID, &sid) < 0) + { + if (errno == EINVAL) + { + tiocgsid_does_not_work = 1; + errno=serrno; + } + else + return (pid_t) -1; + } + else + return (pid_t) sid; + } +#endif + + pgrp = tcgetpgrp (fd); + if (pgrp == -1) + return (pid_t) -1; + + sid = getsid (pgrp); + if (sid == -1 && errno == ESRCH) + errno=ENOTTY; + + return sid; +} diff --git a/libc/termios/tcsetattr.c b/libc/termios/tcsetattr.c new file mode 100644 index 000000000..30ea46f4c --- /dev/null +++ b/libc/termios/tcsetattr.c @@ -0,0 +1,120 @@ +/* Copyright (C) 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. */ + +#include <errno.h> +#include <string.h> +#include <termios.h> +#include <sys/ioctl.h> +#include <sys/types.h> + +/* The difference here is that the termios structure used in the + kernel is not the same as we use in the libc. Therefore we must + translate it here. */ +#include <kernel_termios.h> + + +/* 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 `speed.c'. */ +#if !defined _HAVE_C_ISPEED || !defined _HAVE_C_OSPEED +# define IBAUD0 020000000000 +#else +/* If we have separate values for input and output speed don't bother + with this. Define the value as zero so the compiler sees we don't + have to do the AND below. */ +# define IBAUD0 0 +#endif + + +/* Set the state of FD to *TERMIOS_P. */ +int +tcsetattr (fd, optional_actions, termios_p) + int fd; + int optional_actions; + const struct termios *termios_p; +{ + struct __kernel_termios k_termios; + unsigned long int cmd; + int retval; + + switch (optional_actions) + { + case TCSANOW: + cmd = TCSETS; + break; + case TCSADRAIN: + cmd = TCSETSW; + break; + case TCSAFLUSH: + cmd = TCSETSF; + break; + default: + errno=EINVAL; + return -1; + } + + k_termios.c_iflag = termios_p->c_iflag & ~IBAUD0; + k_termios.c_oflag = termios_p->c_oflag; + k_termios.c_cflag = termios_p->c_cflag; + k_termios.c_lflag = termios_p->c_lflag; + k_termios.c_line = termios_p->c_line; +#ifdef _HAVE_C_ISPEED + k_termios.c_ispeed = termios_p->c_ispeed; +#endif +#ifdef _HAVE_C_OSPEED + k_termios.c_ospeed = termios_p->c_ospeed; +#endif + memcpy (&k_termios.c_cc[0], &termios_p->c_cc[0], + __KERNEL_NCCS * sizeof (cc_t)); + + retval = ioctl (fd, cmd, &k_termios); + + if (retval == 0 && cmd == TCSETS) + { + /* The Linux kernel has a bug which silently ignore the invalid + c_cflag on pty. We have to check it here. */ + int save = errno; + retval = ioctl (fd, TCGETS, &k_termios); + if (retval) + { + /* We cannot verify if the setting is ok. We don't return + an error (?). */ + errno=save; + retval = 0; + } + else if ((termios_p->c_cflag & (PARENB | CREAD)) + != (k_termios.c_cflag & (PARENB | CREAD)) + || ((termios_p->c_cflag & CSIZE) + && ((termios_p->c_cflag & CSIZE) + != (k_termios.c_cflag & CSIZE)))) + { + /* It looks like the Linux kernel silently changed the + PARENB/CREAD/CSIZE bits in c_cflag. Report it as an + error. */ + errno=EINVAL; + retval = -1; + } + } + + return retval; +} 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 |