chiark / gitweb /
eglibc (2.11.3-4+deb6u3) squeeze-lts; urgency=medium
[eglibc.git] / sysdeps / unix / bsd / tcsetattr.c
1 /* Copyright (C) 1991, 1993, 1996, 1997, 2002 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, write to the Free
16    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17    02111-1307 USA.  */
18
19 #include <errno.h>
20 #include <stddef.h>
21 #include <termios.h>
22
23 #include "bsdtty.h"
24
25
26 const speed_t __bsd_speeds[] =
27   {
28     0,
29     50,
30     75,
31     110,
32     134,
33     150,
34     200,
35     300,
36     600,
37     1200,
38     1800,
39     2400,
40     4800,
41     9600,
42     19200,
43     38400,
44   };
45
46
47 /* Set the state of FD to *TERMIOS_P.  */
48 int
49 tcsetattr (fd, optional_actions, termios_p)
50      int fd;
51      int optional_actions;
52      const struct termios *termios_p;
53 {
54   struct sgttyb buf;
55   struct tchars tchars;
56   struct ltchars ltchars;
57   int local;
58 #ifdef  TIOCGETX
59   int extra;
60 #endif
61   size_t i;
62
63   if (__ioctl (fd, TIOCGETP, &buf) < 0 ||
64       __ioctl (fd, TIOCGETC, &tchars) < 0 ||
65       __ioctl (fd, TIOCGLTC, &ltchars) < 0 ||
66 #ifdef  TIOCGETX
67       __ioctl (fd, TIOCGETX, &extra) < 0 ||
68 #endif
69       __ioctl (fd, TIOCLGET, &local) < 0)
70     return -1;
71
72   if (termios_p == NULL)
73     {
74       __set_errno (EINVAL);
75       return -1;
76     }
77   switch (optional_actions)
78     {
79     case TCSANOW:
80       break;
81     case TCSADRAIN:
82       if (tcdrain (fd) < 0)
83         return -1;
84       break;
85     case TCSAFLUSH:
86       if (tcflush (fd, TCIFLUSH) < 0)
87         return -1;
88       break;
89     default:
90       __set_errno (EINVAL);
91       return -1;
92     }
93
94   buf.sg_ispeed = buf.sg_ospeed = -1;
95   for (i = 0; i <= sizeof (__bsd_speeds) / sizeof (__bsd_speeds[0]); ++i)
96     {
97       if (__bsd_speeds[i] == termios_p->__ispeed)
98         buf.sg_ispeed = i;
99       if (__bsd_speeds[i] == termios_p->__ospeed)
100         buf.sg_ospeed = i;
101     }
102   if (buf.sg_ispeed == -1 || buf.sg_ospeed == -1)
103     {
104       __set_errno (EINVAL);
105       return -1;
106     }
107
108   buf.sg_flags &= ~(CBREAK|RAW);
109   if (!(termios_p->c_lflag & ICANON))
110     buf.sg_flags |= (termios_p->c_cflag & ISIG) ? CBREAK : RAW;
111 #ifdef  LPASS8
112   if (termios_p->c_oflag & CS8)
113     local |= LPASS8;
114   else
115     local &= ~LPASS8;
116 #endif
117   if (termios_p->c_lflag & _NOFLSH)
118     local |= LNOFLSH;
119   else
120     local &= ~LNOFLSH;
121   if (termios_p->c_oflag & OPOST)
122     local &= ~LLITOUT;
123   else
124     local |= LLITOUT;
125 #ifdef  TIOCGETX
126   if (termios_p->c_lflag & ISIG)
127     extra &= ~NOISIG;
128   else
129     extra |= NOISIG;
130   if (termios_p->c_cflag & CSTOPB)
131     extra |= STOPB;
132   else
133     extra &= ~STOPB;
134 #endif
135   if (termios_p->c_iflag & ICRNL)
136     buf.sg_flags |= CRMOD;
137   else
138     buf.sg_flags &= ~CRMOD;
139   if (termios_p->c_iflag & IXOFF)
140     buf.sg_flags |= TANDEM;
141   else
142     buf.sg_flags &= ~TANDEM;
143
144   buf.sg_flags &= ~(ODDP|EVENP);
145   if (!(termios_p->c_cflag & PARENB))
146     buf.sg_flags |= ODDP | EVENP;
147   else if (termios_p->c_cflag & PARODD)
148     buf.sg_flags |= ODDP;
149   else
150     buf.sg_flags |= EVENP;
151
152   if (termios_p->c_lflag & _ECHO)
153     buf.sg_flags |= ECHO;
154   else
155     buf.sg_flags &= ~ECHO;
156   if (termios_p->c_lflag & ECHOE)
157     local |= LCRTERA;
158   else
159     local &= ~LCRTERA;
160   if (termios_p->c_lflag & ECHOK)
161     local |= LCRTKIL;
162   else
163     local &= ~LCRTKIL;
164   if (termios_p->c_lflag & _TOSTOP)
165     local |= LTOSTOP;
166   else
167     local &= ~LTOSTOP;
168
169   buf.sg_erase = termios_p->c_cc[VERASE];
170   buf.sg_kill = termios_p->c_cc[VKILL];
171   tchars.t_eofc = termios_p->c_cc[VEOF];
172   tchars.t_intrc = termios_p->c_cc[VINTR];
173   tchars.t_quitc = termios_p->c_cc[VQUIT];
174   ltchars.t_suspc = termios_p->c_cc[VSUSP];
175   tchars.t_startc = termios_p->c_cc[VSTART];
176   tchars.t_stopc = termios_p->c_cc[VSTOP];
177
178   if (__ioctl (fd, TIOCSETP, &buf) < 0 ||
179       __ioctl (fd, TIOCSETC, &tchars) < 0 ||
180       __ioctl (fd, TIOCSLTC, &ltchars) < 0 ||
181 #ifdef  TIOCGETX
182       __ioctl (fd, TIOCSETX, &extra) < 0 ||
183 #endif
184       __ioctl (fd, TIOCLSET, &local) < 0)
185     return -1;
186   return 0;
187 }
188 libc_hidden_def (tcsetattr)