/* Copyright (C) 1991, 1993, 1995 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #undef B0 #undef B50 #undef B75 #undef B110 #undef B134 #undef B150 #undef B200 #undef B300 #undef B600 #undef B1200 #undef B1800 #undef B2400 #undef B4800 #undef B9600 #undef B19200 #undef B38400 #undef EXTA #undef EXTB #undef ECHO #undef TOSTOP #undef NOFLSH #undef MDMBUF #undef FLUSHO #undef PENDIN #undef CERASE #undef CKILL #undef CINTR #undef CQUIT #undef CSTART #undef CSTOP #undef CEOF #undef CEOT #undef CBRK #undef CSUSP #undef CDSUSP #undef CRPRNT #undef CFLUSH #undef CWERASE #undef CLNEXT #undef CSTATUS #undef CERASE #undef CKILL #undef CINTR #undef CQUIT #undef CSTART #undef CSTOP #undef CEOF #undef CEOT #undef CBRK #undef CSUSP #undef CDSUSP #undef CRPRNT #undef CFLUSH #undef CWERASE #undef CLNEXT #undef CSTATUS #undef CERASE #undef CKILL #undef CINTR #undef CQUIT #undef CSTART #undef CSTOP #undef CEOF #undef CEOT #undef CBRK #undef CSUSP #undef CDSUSP #undef CRPRNT #undef CFLUSH #undef CWERASE #undef CLNEXT #undef CSTATUS #undef CERASE #undef CKILL #undef CINTR #undef CQUIT #undef CSTART #undef CSTOP #undef CEOF #undef CEOT #undef CBRK #undef CSUSP #undef CDSUSP #undef CRPRNT #undef CFLUSH #undef CWERASE #undef CLNEXT #undef CSTATUS #undef CERASE #undef CKILL #undef CINTR #undef CQUIT #undef CSTART #undef CSTOP #undef CEOF #undef CEOT #undef CBRK #undef CSUSP #undef CDSUSP #undef CRPRNT #undef CFLUSH #undef CWERASE #undef CLNEXT #undef CSTATUS #undef CERASE #undef CKILL #undef CINTR #undef CQUIT #undef CSTART #undef CSTOP #undef CEOF #undef CEOT #undef CBRK #undef CSUSP #undef CDSUSP #undef CRPRNT #undef CFLUSH #undef CWERASE #undef CLNEXT #undef CSTATUS #undef CERASE #undef CKILL #undef CINTR #undef CQUIT #undef CSTART #undef CSTOP #undef CEOF #undef CEOT #undef CBRK #undef CSUSP #undef CDSUSP #undef CRPRNT #undef CFLUSH #undef CWERASE #undef CLNEXT #undef CSTATUS #undef CERASE #undef CKILL #undef CINTR #undef CQUIT #undef CSTART #undef CSTOP #undef CEOF #undef CEOT #undef CBRK #undef CSUSP #undef CDSUSP #undef CRPRNT #undef CFLUSH #undef CWERASE #undef CLNEXT #undef CSTATUS #undef CERASE #undef CKILL #undef CINTR #undef CQUIT #undef CSTART #undef CSTOP #undef CEOF #undef CEOT #undef CBRK #undef CSUSP #undef CDSUSP #undef CRPRNT #undef CFLUSH #undef CWERASE #undef CLNEXT #undef CSTATUS #undef CERASE #undef CKILL #undef CINTR #undef CQUIT #undef CSTART #undef CSTOP #undef CEOF #undef CEOT #undef CBRK #undef CSUSP #undef CDSUSP #undef CRPRNT #undef CFLUSH #undef CWERASE #undef CLNEXT #undef CSTATUS #undef CERASE #undef CKILL #undef CINTR #undef CQUIT #undef CSTART #undef CSTOP #undef CEOF #undef CEOT #undef CBRK #undef CSUSP #undef CDSUSP #undef CRPRNT #undef CFLUSH #undef CWERASE #undef CLNEXT #undef CSTATUS #undef CERASE #undef CKILL #undef CINTR #undef CQUIT #undef CSTART #undef CSTOP #undef CEOF #undef CEOT #undef CBRK #undef CSUSP #undef CDSUSP #undef CRPRNT #undef CFLUSH #undef CWERASE #undef CLNEXT #undef CSTATUS #define IOCPARM_MASK 0x7f #define IOC_OUT 0x40000000 #define IOC_IN 0x80000000 #define _IOR(x,y,t) (IOC_OUT|((sizeof(t)&IOCPARM_MASK)<<16)|(x<<8)|y) #define _IOW(x,y,t) (IOC_IN|((sizeof(t)&IOCPARM_MASK)<<16)|(x<<8)|y) #define FIONREAD _IOR('f', 127, int) #define FIOASYNC _IOW('f', 125, int) #define TIOCGETP _IOR('t', 8, struct sgttyb) #define TIOCLGET _IOR('t', 124, int) #define TIOCLSET _IOW('t', 125, int) #define TIOCSETN _IOW('t', 10, struct sgttyb) #define TIOCSETP _IOW('t', 9,struct sgttyb)/* set parameters -- stty */ #define TIOCFLUSH _IOW('t', 16, int) /* flush buffers */ #define TIOCSETC _IOW('t',17,struct tchars)/* set special characters */ #define TIOCGETC _IOR('t',18,struct tchars)/* get special characters */ #define TANDEM 0x00000001 /* send stopc on out q full */ #define CBREAK 0x00000002 /* half-cooked mode */ #define LCASE 0x00000004 /* simulate lower case */ #define ECHO 0x00000008 /* echo input */ #define CRMOD 0x00000010 /* map \r to \r\n on output */ #define RAW 0x00000020 /* no i/o processing */ #define ODDP 0x00000040 /* get/send odd parity */ #define EVENP 0x00000080 /* get/send even parity */ #define ANYP 0x000000c0 /* get any parity/send none */ #define PRTERA 0x00020000 /* \ ... / erase */ #define CRTERA 0x00040000 /* " \b " to wipe out char */ #define TILDE 0x00080000 /* hazeltine tilde kludge */ #define MDMBUF 0x00100000 /* start/stop output on carrier intr */ #define LITOUT 0x00200000 /* literal output */ #define TOSTOP 0x00400000 /* SIGSTOP on background output */ #define FLUSHO 0x00800000 /* flush output to terminal */ #define NOHANG 0x01000000 /* no SIGHUP on carrier drop */ #define L001000 0x02000000 #define CRTKIL 0x04000000 /* kill line with " \b " */ #define PASS8 0x08000000 #define CTLECH 0x10000000 /* echo control chars as ^X */ #define PENDIN 0x20000000 /* tp->t_rawq needs reread */ #define DECCTQ 0x40000000 /* only ^Q starts after ^S */ #define NOFLSH 0x80000000 /* no output flush on signal */ #define TIOCLSET _IOW('t', 125, int) /* set entire local mode word */ #define TIOCLGET _IOR('t', 124, int) /* get local modes */ #define LCRTBS (CRTBS>>16) #define LPRTERA (PRTERA>>16) #define LCRTERA (CRTERA>>16) #define LTILDE (TILDE>>16) #define LMDMBUF (MDMBUF>>16) #define LLITOUT (LITOUT>>16) #define LTOSTOP (TOSTOP>>16) #define LFLUSHO (FLUSHO>>16) #define LNOHANG (NOHANG>>16) #define LCRTKIL (CRTKIL>>16) #define LPASS8 (PASS8>>16) #define LCTLECH (CTLECH>>16) #define LPENDIN (PENDIN>>16) #define LDECCTQ (DECCTQ>>16) #define LNOFLSH (NOFLSH>>16) #define TIOCSLTC _IOW('t',117,struct ltchars)/* set local special chars */ #define TIOCGLTC _IOR('t',116,struct ltchars)/* get local special chars */ #if defined(TIOCGETC) || defined(TIOCSETC) /* Type of ARG for TIOCGETC and TIOCSETC requests. */ struct tchars { char t_intrc; /* Interrupt character. */ char t_quitc; /* Quit character. */ char t_startc; /* Start-output character. */ char t_stopc; /* Stop-output character. */ char t_eofc; /* End-of-file character. */ char t_brkc; /* Input delimiter character. */ }; #define _IOT_tchars /* Hurd ioctl type field. */ \ _IOT (_IOTS (char), 6, 0, 0, 0, 0) #endif #if defined(TIOCGLTC) || defined(TIOCSLTC) /* Type of ARG for TIOCGLTC and TIOCSLTC requests. */ struct ltchars { char t_suspc; /* Suspend character. */ char t_dsuspc; /* Delayed suspend character. */ char t_rprntc; /* Reprint-line character. */ char t_flushc; /* Flush-output character. */ char t_werasc; /* Word-erase character. */ char t_lnextc; /* Literal-next character. */ }; #define _IOT_ltchars /* Hurd ioctl type field. */ \ _IOT (_IOTS (char), 6, 0, 0, 0, 0) #endif /* Type of ARG for TIOCGETP and TIOCSETP requests (and gtty and stty). */ struct sgttyb { char sg_ispeed; /* Input speed. */ char sg_ospeed; /* Output speed. */ char sg_erase; /* Erase character. */ char sg_kill; /* Kill character. */ short int sg_flags; /* Mode flags. */ }; const speed_t __bsd_speeds[] = { 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, }; extern int ioctl (); /* Set the state of FD to *TERMIOS_P. */ int tcsetattr (int fd, int optional_actions, const struct termios *termios_p) { struct sgttyb buf; struct tchars tchars; struct ltchars ltchars; int local; #ifdef TIOCGETX int extra; #endif size_t i; if (ioctl(fd, TIOCGETP, &buf) < 0 || ioctl(fd, TIOCGETC, &tchars) < 0 || ioctl(fd, TIOCGLTC, <chars) < 0 || #ifdef TIOCGETX ioctl(fd, TIOCGETX, &extra) < 0 || #endif ioctl(fd, TIOCLGET, &local) < 0) return -1; if (termios_p == NULL) { errno = EINVAL; return -1; } buf.sg_ispeed = buf.sg_ospeed = -1; for (i = 0; i <= sizeof (__bsd_speeds) / sizeof (__bsd_speeds[0]); ++i) { if (__bsd_speeds[i] == termios_p->__ispeed) buf.sg_ispeed = i; if (__bsd_speeds[i] == termios_p->__ospeed) buf.sg_ospeed = i; } if (buf.sg_ispeed == -1 || buf.sg_ospeed == -1) { errno = EINVAL; return -1; } buf.sg_flags &= ~(CBREAK|RAW); if (!(termios_p->c_lflag & ICANON)) buf.sg_flags |= (termios_p->c_cflag & ISIG) ? CBREAK : RAW; #ifdef LPASS8 if (termios_p->c_oflag & CS8) local |= LPASS8; else local &= ~LPASS8; #endif if (termios_p->c_lflag & _NOFLSH) local |= LNOFLSH; else local &= ~LNOFLSH; if (termios_p->c_oflag & OPOST) local &= ~LLITOUT; else local |= LLITOUT; #ifdef TIOCGETX if (termios_p->c_lflag & ISIG) extra &= ~NOISIG; else extra |= NOISIG; if (termios_p->c_cflag & CSTOPB) extra |= STOPB; else extra &= ~STOPB; #endif if (termios_p->c_iflag & ICRNL) buf.sg_flags |= CRMOD; else buf.sg_flags &= ~CRMOD; if (termios_p->c_iflag & IXOFF) buf.sg_flags |= TANDEM; else buf.sg_flags &= ~TANDEM; buf.sg_flags &= ~(ODDP|EVENP); if (!(termios_p->c_cflag & PARENB)) buf.sg_flags |= ODDP | EVENP; else if (termios_p->c_cflag & PARODD) buf.sg_flags |= ODDP; else buf.sg_flags |= EVENP; if (termios_p->c_lflag & _ECHO) buf.sg_flags |= ECHO; else buf.sg_flags &= ~ECHO; if (termios_p->c_lflag & ECHOE) local |= LCRTERA; else local &= ~LCRTERA; if (termios_p->c_lflag & ECHOK) local |= LCRTKIL; else local &= ~LCRTKIL; if (termios_p->c_lflag & _TOSTOP) local |= LTOSTOP; else local &= ~LTOSTOP; buf.sg_erase = termios_p->c_cc[VERASE]; buf.sg_kill = termios_p->c_cc[VKILL]; tchars.t_eofc = termios_p->c_cc[VEOF]; tchars.t_intrc = termios_p->c_cc[VINTR]; tchars.t_quitc = termios_p->c_cc[VQUIT]; ltchars.t_suspc = termios_p->c_cc[VSUSP]; tchars.t_startc = termios_p->c_cc[VSTART]; tchars.t_stopc = termios_p->c_cc[VSTOP]; if (ioctl(fd, TIOCSETP, &buf) < 0 || ioctl(fd, TIOCSETC, &tchars) < 0 || ioctl(fd, TIOCSLTC, <chars) < 0 || #ifdef TIOCGETX ioctl(fd, TIOCSETX, &extra) < 0 || #endif ioctl(fd, TIOCLSET, &local) < 0) return -1; return 0; } #undef tcgetattr /* Put the state of FD into *TERMIOS_P. */ int tcgetattr (int fd, struct termios *termios_p) { struct sgttyb buf; struct tchars tchars; struct ltchars ltchars; int local; #ifdef TIOCGETX int extra; #endif if (termios_p == NULL) { errno = EINVAL; return -1; } if (ioctl(fd, TIOCGETP, &buf) < 0 || ioctl(fd, TIOCGETC, &tchars) < 0 || ioctl(fd, TIOCGLTC, <chars) < 0 || #ifdef TIOCGETX ioctl(fd, TIOCGETX, &extra) < 0 || #endif ioctl(fd, TIOCLGET, &local) < 0) return -1; termios_p->__ispeed = __bsd_speeds[(unsigned char) buf.sg_ispeed]; termios_p->__ospeed = __bsd_speeds[(unsigned char) buf.sg_ospeed]; termios_p->c_iflag = 0; termios_p->c_oflag = 0; termios_p->c_cflag = 0; termios_p->c_lflag = 0; termios_p->c_oflag |= CREAD | HUPCL; #ifdef LPASS8 if (local & LPASS8) termios_p->c_oflag |= CS8; else #endif termios_p->c_oflag |= CS7; if (!(buf.sg_flags & RAW)) { termios_p->c_iflag |= IXON; termios_p->c_cflag |= OPOST; #ifndef NOISIG termios_p->c_lflag |= ISIG; #endif } if ((buf.sg_flags & (CBREAK|RAW)) == 0) termios_p->c_lflag |= ICANON; if (!(buf.sg_flags & RAW) && !(local & LLITOUT)) termios_p->c_oflag |= OPOST; if (buf.sg_flags & CRMOD) termios_p->c_iflag |= ICRNL; if (buf.sg_flags & TANDEM) termios_p->c_iflag |= IXOFF; #ifdef TIOCGETX if (!(extra & NOISIG)) termios_p->c_lflag |= ISIG; if (extra & STOPB) termios_p->c_cflag |= CSTOPB; #endif switch (buf.sg_flags & (EVENP|ODDP)) { case EVENP|ODDP: break; case ODDP: termios_p->c_cflag |= PARODD; default: termios_p->c_cflag |= PARENB; termios_p->c_iflag |= IGNPAR | INPCK; break; } if (buf.sg_flags & ECHO) termios_p->c_lflag |= _ECHO; if (local & LCRTERA) termios_p->c_lflag |= ECHOE; if (local & LCRTKIL) termios_p->c_lflag |= ECHOK; if (local & LTOSTOP) termios_p->c_lflag |= _TOSTOP; if (local & LNOFLSH) termios_p->c_lflag |= _NOFLSH; termios_p->c_cc[VEOF] = tchars.t_eofc; termios_p->c_cc[VEOL] = '\n'; termios_p->c_cc[VERASE] = buf.sg_erase; termios_p->c_cc[VKILL] = buf.sg_kill; termios_p->c_cc[VINTR] = tchars.t_intrc; termios_p->c_cc[VQUIT] = tchars.t_quitc; termios_p->c_cc[VSTART] = tchars.t_startc; termios_p->c_cc[VSTOP] = tchars.t_stopc; termios_p->c_cc[VSUSP] = ltchars.t_suspc; termios_p->c_cc[VMIN] = -1; termios_p->c_cc[VTIME] = -1; return 0; }