1 /*        $NetBSD: ttcompat.c,v 1.12 2003/08/07 11:25:28 agc Exp $    */
2 /*
3  * Copyright (c) 1995
4  *        The Regents of the University of California.  All rights reserved.
5  *
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 /*
33  * ttcompat.c -- convert sgtty flags to termios
34  *        originally from /sys/kern/tty_compat.c
35  */
36 
37 #include <sys/param.h>
38 #include <sys/types.h>
39 
40 #include <unistd.h>
41 #include <sys/ioctl_compat.h>
42 #include <termios.h>
43 #include <syslog.h>
44 #include <fcntl.h>
45 #include <dirent.h>
46 #include <errno.h>
47 #include <stdio.h>
48 #include <string.h>
49 #include <stdlib.h>
50 #include "extern.h"
51 
52 /* Macros to clear/set/test flags. */
53 #define   SET(t, f) (t) |= (f)
54 #define   CLR(t, f) (t) &= ~(f)
55 #define   ISSET(t, f)         ((t) & (f))
56 
57 static int          sttygetoflags(struct termios *);
58 static void         sttysetoflags(struct termios *, int);
59 
60 static int
sttygetoflags(struct termios * tp)61 sttygetoflags(struct termios *tp)
62 {
63           tcflag_t iflag = tp->c_iflag;
64           tcflag_t lflag = tp->c_lflag;
65           tcflag_t oflag = tp->c_oflag;
66           tcflag_t cflag = tp->c_cflag;
67           int flags = 0;
68 
69           if (ISSET(cflag, PARENB)) {
70                     if (ISSET(iflag, INPCK)) {
71                               if (ISSET(cflag, PARODD))
72                                         SET(flags, ODDP);
73                               else
74                                         SET(flags, EVENP);
75                     } else
76                               SET(flags, EVENP|ODDP);
77           }
78           if (ISSET(cflag, CSIZE) == CS8) {
79                     if (!ISSET(iflag, ISTRIP))
80                               SET(flags, PASS8);
81                     if (!ISSET(oflag, OPOST))
82                               SET(flags, LITOUT);
83           }
84 
85           if (!ISSET(lflag, ICANON)) {
86                     /* fudge */
87                     if (ISSET(iflag, IXON) || ISSET(lflag, ISIG|IEXTEN) ||
88                         ISSET(cflag, PARENB))
89                               SET(flags, CBREAK);
90                     else
91                               SET(flags, RAW);
92           }
93 
94           return (flags);
95 }
96 
97 static void
sttysetoflags(struct termios * tp,int flags)98 sttysetoflags(struct termios *tp, int flags)
99 {
100           tcflag_t iflag = tp->c_iflag;
101           tcflag_t oflag = tp->c_oflag;
102           tcflag_t lflag = tp->c_lflag;
103           tcflag_t cflag = tp->c_cflag;
104 
105           if (ISSET(flags, RAW)) {
106                     iflag &= IXOFF;
107                     CLR(lflag, ISIG|ICANON|IEXTEN);
108                     CLR(cflag, PARENB);
109           } else {
110                     SET(iflag, BRKINT|IXON|IMAXBEL);
111                     SET(lflag, ISIG|IEXTEN);
112                     if (ISSET(flags, CBREAK))
113                               CLR(lflag, ICANON);
114                     else
115                               SET(lflag, ICANON);
116                     switch (ISSET(flags, ANYP)) {
117                     case 0:
118                               CLR(cflag, PARENB);
119                               break;
120                     case ANYP:
121                               SET(cflag, PARENB);
122                               CLR(iflag, INPCK);
123                               break;
124                     case EVENP:
125                               SET(cflag, PARENB);
126                               SET(iflag, INPCK);
127                               CLR(cflag, PARODD);
128                               break;
129                     case ODDP:
130                               SET(cflag, PARENB);
131                               SET(iflag, INPCK);
132                               SET(cflag, PARODD);
133                               break;
134                     }
135           }
136 
137           if (ISSET(flags, RAW|LITOUT|PASS8)) {
138                     CLR(cflag, CSIZE);
139                     SET(cflag, CS8);
140                     if (!ISSET(flags, RAW|PASS8))
141                               SET(iflag, ISTRIP);
142                     else
143                               CLR(iflag, ISTRIP);
144                     if (!ISSET(flags, RAW|LITOUT))
145                               SET(oflag, OPOST);
146                     else
147                               CLR(oflag, OPOST);
148           } else {
149                     CLR(cflag, CSIZE);
150                     SET(cflag, CS7);
151                     SET(iflag, ISTRIP);
152                     SET(oflag, OPOST);
153           }
154 
155           tp->c_iflag = iflag;
156           tp->c_oflag = oflag;
157           tp->c_lflag = lflag;
158           tp->c_cflag = cflag;
159 }
160 
161 void
sttyclearflags(struct termios * tp,int flags)162 sttyclearflags(struct termios *tp, int flags)
163 {
164           tcflag_t iflag = tp->c_iflag;
165           tcflag_t oflag = tp->c_oflag;
166           tcflag_t lflag = tp->c_lflag;
167           tcflag_t cflag = tp->c_cflag;
168           int oflags = sttygetoflags(tp) & ~flags;
169 
170           if (ISSET(flags, TANDEM))
171                     CLR(iflag, IXOFF);
172           if (ISSET(flags, ECHO))
173                     CLR(lflag, ECHO);
174           if (ISSET(flags, CRMOD)) {
175                     CLR(iflag, ICRNL);
176                     CLR(oflag, ONLCR);
177           }
178           if (ISSET(flags, XTABS))
179                     CLR(oflag, OXTABS);
180 
181 
182           tp->c_iflag = iflag;
183           tp->c_oflag = oflag;
184           tp->c_lflag = lflag;
185           tp->c_cflag = cflag;
186 
187           sttysetoflags(tp, oflags);
188 }
189 
190 void
sttysetflags(struct termios * tp,int flags)191 sttysetflags(struct termios *tp, int flags)
192 {
193           tcflag_t iflag = tp->c_iflag;
194           tcflag_t oflag = tp->c_oflag;
195           tcflag_t lflag = tp->c_lflag;
196           tcflag_t cflag = tp->c_cflag;
197           int oflags = sttygetoflags(tp) | flags;
198 
199           if (ISSET(flags, TANDEM))
200                     SET(iflag, IXOFF);
201           if (ISSET(flags, ECHO))
202                     SET(lflag, ECHO);
203           if (ISSET(flags, CRMOD)) {
204                     SET(iflag, ICRNL);
205                     SET(oflag, ONLCR);
206           }
207           if (ISSET(flags, XTABS))
208                     SET(oflag, OXTABS);
209 
210           tp->c_iflag = iflag;
211           tp->c_oflag = oflag;
212           tp->c_lflag = lflag;
213           tp->c_cflag = cflag;
214 
215           sttysetoflags(tp, oflags);
216 }
217 
218 void
sttyclearlflags(struct termios * tp,int flags)219 sttyclearlflags(struct termios *tp, int flags)
220 {
221           tcflag_t iflag = tp->c_iflag;
222           tcflag_t oflag = tp->c_oflag;
223           tcflag_t lflag = tp->c_lflag;
224           tcflag_t cflag = tp->c_cflag;
225           int oflags = sttygetoflags(tp) & ~flags;
226 
227           /* Nothing we can do with CRTBS. */
228           if (ISSET(flags, PRTERA))
229                     CLR(lflag, ECHOPRT);
230           if (ISSET(flags, CRTERA))
231                     CLR(lflag, ECHOE);
232           /* Nothing we can do with TILDE. */
233           if (ISSET(flags, MDMBUF))
234                     CLR(cflag, MDMBUF);
235           if (ISSET(flags, NOHANG))
236                     SET(cflag, HUPCL);
237           if (ISSET(flags, CRTKIL))
238                     CLR(lflag, ECHOKE);
239           if (ISSET(flags, CTLECH))
240                     CLR(lflag, ECHOCTL);
241           if (ISSET(flags, DECCTQ))
242                     SET(iflag, IXANY);
243           CLR(lflag, ISSET(flags, TOSTOP|FLUSHO|PENDIN|NOFLSH));
244 
245           tp->c_iflag = iflag;
246           tp->c_oflag = oflag;
247           tp->c_lflag = lflag;
248           tp->c_cflag = cflag;
249 
250           sttysetoflags(tp, oflags);
251 }
252 
253 void
sttysetlflags(struct termios * tp,int flags)254 sttysetlflags(struct termios *tp, int flags)
255 {
256           tcflag_t iflag = tp->c_iflag;
257           tcflag_t oflag = tp->c_oflag;
258           tcflag_t lflag = tp->c_lflag;
259           tcflag_t cflag = tp->c_cflag;
260           int oflags = sttygetoflags(tp) | flags;
261 
262           /* Nothing we can do with CRTBS. */
263           if (ISSET(flags, PRTERA))
264                     SET(lflag, ECHOPRT);
265           if (ISSET(flags, CRTERA))
266                     SET(lflag, ECHOE);
267           /* Nothing we can do with TILDE. */
268           if (ISSET(flags, MDMBUF))
269                     SET(cflag, MDMBUF);
270           if (ISSET(flags, NOHANG))
271                     CLR(cflag, HUPCL);
272           if (ISSET(flags, CRTKIL))
273                     SET(lflag, ECHOKE);
274           if (ISSET(flags, CTLECH))
275                     SET(lflag, ECHOCTL);
276           if (ISSET(flags, DECCTQ))
277                     CLR(iflag, IXANY);
278           SET(lflag, ISSET(flags, TOSTOP|FLUSHO|PENDIN|NOFLSH));
279 
280           tp->c_iflag = iflag;
281           tp->c_oflag = oflag;
282           tp->c_lflag = lflag;
283           tp->c_cflag = cflag;
284 
285           sttysetoflags(tp, oflags);
286 }
287