xref: /NextBSD/sys/compat/svr4/svr4_termios.c (revision eb1a5f8de9f7ea602c373a710f531abbf81141c4)
1 /*-
2  * Copyright (c) 1998 Mark Newton
3  * Copyright (c) 1994 Christos Zoulas
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31 
32 #include <sys/param.h>
33 #include <sys/proc.h>
34 #include <sys/systm.h>
35 #include <sys/file.h>
36 #include <sys/filedesc.h>
37 #include <sys/tty.h>
38 
39 #include <sys/sysproto.h>
40 
41 #include <compat/svr4/svr4.h>
42 #include <compat/svr4/svr4_util.h>
43 #include <compat/svr4/svr4_ioctl.h>
44 #include <compat/svr4/svr4_termios.h>
45 
46 #ifndef __CONCAT3
47 # if __STDC__
48 #  define __CONCAT3(a,b,c)	a ## b ## c
49 # else
50 #  define __CONCAT3(a,b,c)	a/**/b/**/c
51 # endif
52 #endif
53 
54 static u_long bsd_to_svr4_speed(u_long, u_long);
55 static u_long svr4_to_bsd_speed(u_long, u_long);
56 static void svr4_to_bsd_termios(const struct svr4_termios *,
57 				     struct termios *, int);
58 static void bsd_to_svr4_termios(const struct termios *,
59 				     struct svr4_termios *);
60 static void svr4_termio_to_termios(const struct svr4_termio *,
61 					struct svr4_termios *);
62 static void svr4_termios_to_termio(const struct svr4_termios *,
63 					struct svr4_termio *);
64 #ifdef DEBUG_SVR4
65 static void print_svr4_termios(const struct svr4_termios *);
66 static void print_bsd_termios(const struct termios *);
67 #endif /* DEBUG_SVR4 */
68 
69 #define undefined_char(a,b)				/**/
70 #define undefined_flag1(f,a,b)				/**/
71 #define undefined_flag2(f,a,b,c1,t1,c2,t2)		/**/
72 #define undefined_flag4(f,a,b,c1,t1,c2,t2,c3,t3,c4,t4)	/**/
73 
74 #define svr4_to_bsd_char(a,b) \
75 	if (new || __CONCAT3(SVR4_,a,b) < SVR4_NCC) { \
76 		if (st->c_cc[__CONCAT3(SVR4_,a,b)] == SVR4_POSIX_VDISABLE) \
77 			bt->c_cc[__CONCAT(a,b)] = _POSIX_VDISABLE; \
78 		else \
79 			bt->c_cc[__CONCAT(a,b)] = st->c_cc[__CONCAT3(SVR4_,a,b)]; \
80 	}
81 
82 #define svr4_to_bsd_flag1(f,a,b) \
83 	if (new || __CONCAT3(SVR4_,a,b) < 0200000) { \
84 		if (st->f & __CONCAT3(SVR4_,a,b)) \
85 			bt->f |= __CONCAT(a,b); \
86 		else \
87 			bt->f &= ~__CONCAT(a,b); \
88 	}
89 
90 #define svr4_to_bsd_flag2(f,a,b,c1,t1,c2,t2) \
91 	if (new || __CONCAT3(SVR4_,a,b) < 0200000) { \
92 		bt->f &= ~__CONCAT(a,b); \
93 		switch (st->f & __CONCAT3(SVR4_,a,b)) { \
94 		case __CONCAT3(SVR4_,c1,t1): bt->f |= __CONCAT(c1,t1); break; \
95 		case __CONCAT3(SVR4_,c2,t2): bt->f |= __CONCAT(c2,t2); break; \
96 		} \
97 	}
98 
99 #define svr4_to_bsd_flag4(f,a,b,c1,t1,c2,t2,c3,t3,c4,t4) \
100 	if (new || __CONCAT3(SVR4_,a,b) < 0200000) { \
101 		bt->f &= ~__CONCAT(a,b); \
102 		switch (st->f & __CONCAT3(SVR4_,a,b)) { \
103 		case __CONCAT3(SVR4_,c1,t1): bt->f |= __CONCAT(c1,t1); break; \
104 		case __CONCAT3(SVR4_,c2,t2): bt->f |= __CONCAT(c2,t2); break; \
105 		case __CONCAT3(SVR4_,c3,t3): bt->f |= __CONCAT(c3,t3); break; \
106 		case __CONCAT3(SVR4_,c4,t4): bt->f |= __CONCAT(c4,t4); break; \
107 		} \
108 	}
109 
110 
111 #define bsd_to_svr4_char(a,b) \
112 	if (bt->c_cc[__CONCAT(a,b)] == _POSIX_VDISABLE) \
113 		st->c_cc[__CONCAT3(SVR4_,a,b)] = SVR4_POSIX_VDISABLE; \
114 	else \
115 		st->c_cc[__CONCAT3(SVR4_,a,b)] = bt->c_cc[__CONCAT(a,b)]
116 
117 #define bsd_to_svr4_flag1(f,a,b) \
118 	if (bt->f & __CONCAT(a,b)) \
119 		st->f |= __CONCAT3(SVR4_,a,b); \
120 	else \
121 		st->f &= ~__CONCAT3(SVR4_,a,b)
122 
123 #define bsd_to_svr4_flag2(f,a,b,c1,t1,c2,t2) \
124 	st->f &= ~__CONCAT(a,b); \
125 	switch (bt->f & __CONCAT(a,b)) { \
126 	case __CONCAT(c1,t1): st->f |= __CONCAT3(SVR4_,c1,t1); break; \
127 	case __CONCAT(c2,t2): st->f |= __CONCAT3(SVR4_,c2,t2); break; \
128 	}
129 
130 #define bsd_to_svr4_flag4(f,a,b,c1,t1,c2,t2,c3,t3,c4,t4) \
131 	st->f &= ~__CONCAT(a,b); \
132 	switch (bt->f & __CONCAT(a,b)) { \
133 	case __CONCAT(c1,t1): st->f |= __CONCAT3(SVR4_,c1,t1); break; \
134 	case __CONCAT(c2,t2): st->f |= __CONCAT3(SVR4_,c2,t2); break; \
135 	case __CONCAT(c3,t3): st->f |= __CONCAT3(SVR4_,c3,t3); break; \
136 	case __CONCAT(c4,t4): st->f |= __CONCAT3(SVR4_,c4,t4); break; \
137 	}
138 
139 #ifdef DEBUG_SVR4
140 static void
print_svr4_termios(st)141 print_svr4_termios(st)
142 	const struct svr4_termios *st;
143 {
144 	int i;
145 	DPRINTF(("SVR4\niflag=%lo oflag=%lo cflag=%lo lflag=%lo\n",
146 	    st->c_iflag, st->c_oflag, st->c_cflag, st->c_lflag));
147 	DPRINTF(("cc: "));
148 	for (i = 0; i < SVR4_NCCS; i++)
149 		DPRINTF(("%o ", st->c_cc[i]));
150 	DPRINTF(("\n"));
151 }
152 
153 
154 static void
print_bsd_termios(bt)155 print_bsd_termios(bt)
156 	const struct termios *bt;
157 {
158 	int i;
159 	uprintf("BSD\niflag=%o oflag=%o cflag=%o lflag=%o\n",
160 	    bt->c_iflag, bt->c_oflag, bt->c_cflag, bt->c_lflag);
161 	uprintf("cc: ");
162 	for (i = 0; i < NCCS; i++)
163 		uprintf("%o ", bt->c_cc[i]);
164 	uprintf("\n");
165 }
166 #endif /* DEBUG_SVR4 */
167 
168 static u_long
bsd_to_svr4_speed(sp,mask)169 bsd_to_svr4_speed(sp, mask)
170 	u_long sp;
171 	u_long mask;
172 {
173 	switch (sp) {
174 #undef getval
175 #define getval(a,b)	case __CONCAT(a,b):	sp = __CONCAT3(SVR4_,a,b)
176 	getval(B,0);
177 	getval(B,50);
178 	getval(B,75);
179 	getval(B,110);
180 	getval(B,134);
181 	getval(B,150);
182 	getval(B,200);
183 	getval(B,300);
184 	getval(B,600);
185 	getval(B,1200);
186 	getval(B,1800);
187 	getval(B,2400);
188 	getval(B,4800);
189 	getval(B,9600);
190 	getval(B,19200);
191 	getval(B,38400);
192 	getval(B,57600);
193 	getval(B,115200);
194 	default: sp = SVR4_B9600;	/* XXX */
195 	}
196 
197 	while ((mask & 1) == 0) {
198 		mask >>= 1;
199 		sp <<= 1;
200 	}
201 
202 	return sp;
203 }
204 
205 
206 static u_long
svr4_to_bsd_speed(sp,mask)207 svr4_to_bsd_speed(sp, mask)
208 	u_long sp;
209 	u_long mask;
210 {
211 	while ((mask & 1) == 0) {
212 		mask >>= 1;
213 		sp >>= 1;
214 	}
215 
216 	switch (sp & mask) {
217 #undef getval
218 #define getval(a,b)	case __CONCAT3(SVR4_,a,b):	return __CONCAT(a,b)
219 	getval(B,0);
220 	getval(B,50);
221 	getval(B,75);
222 	getval(B,110);
223 	getval(B,134);
224 	getval(B,150);
225 	getval(B,200);
226 	getval(B,300);
227 	getval(B,600);
228 	getval(B,1200);
229 	getval(B,1800);
230 	getval(B,2400);
231 	getval(B,4800);
232 	getval(B,9600);
233 	getval(B,19200);
234 	getval(B,38400);
235 	getval(B,57600);
236 	getval(B,115200);
237 	default: return B9600;	/* XXX */
238 	}
239 }
240 
241 
242 static void
svr4_to_bsd_termios(st,bt,new)243 svr4_to_bsd_termios(st, bt, new)
244 	const struct svr4_termios	*st;
245 	struct termios	 		*bt;
246 	int				 new;
247 {
248 	/* control characters */
249 	/*
250 	 * We process VMIN and VTIME first,
251 	 * because they are shared with VEOF and VEOL
252 	 */
253 	svr4_to_bsd_char(V,MIN);
254 	svr4_to_bsd_char(V,TIME);
255 
256 	svr4_to_bsd_char(V,INTR);
257 	svr4_to_bsd_char(V,QUIT);
258 	svr4_to_bsd_char(V,ERASE);
259 	svr4_to_bsd_char(V,KILL);
260 	svr4_to_bsd_char(V,EOF);
261 	svr4_to_bsd_char(V,EOL);
262 	svr4_to_bsd_char(V,EOL2);
263 	undefined_char(V,SWTCH);
264 	svr4_to_bsd_char(V,START);
265 	svr4_to_bsd_char(V,STOP);
266 	svr4_to_bsd_char(V,SUSP);
267 	svr4_to_bsd_char(V,DSUSP);
268 	svr4_to_bsd_char(V,REPRINT);
269 	svr4_to_bsd_char(V,DISCARD);
270 	svr4_to_bsd_char(V,WERASE);
271 	svr4_to_bsd_char(V,LNEXT);
272 
273 	/* Input modes */
274 	svr4_to_bsd_flag1(c_iflag,I,GNBRK);
275 	svr4_to_bsd_flag1(c_iflag,B,RKINT);
276 	svr4_to_bsd_flag1(c_iflag,I,GNPAR);
277 	svr4_to_bsd_flag1(c_iflag,P,ARMRK);
278 	svr4_to_bsd_flag1(c_iflag,I,NPCK);
279 	svr4_to_bsd_flag1(c_iflag,I,STRIP);
280 	svr4_to_bsd_flag1(c_iflag,I,NLCR);
281 	svr4_to_bsd_flag1(c_iflag,I,GNCR);
282 	svr4_to_bsd_flag1(c_iflag,I,CRNL);
283 	undefined_flag1(c_iflag,I,UCLC);
284 	svr4_to_bsd_flag1(c_iflag,I,XON);
285 	svr4_to_bsd_flag1(c_iflag,I,XANY);
286 	svr4_to_bsd_flag1(c_iflag,I,XOFF);
287 	svr4_to_bsd_flag1(c_iflag,I,MAXBEL);
288 	undefined_flag1(c_iflag,D,OSMODE);
289 
290 	/* Output modes */
291 	svr4_to_bsd_flag1(c_oflag,O,POST);
292 	undefined_flag1(c_oflag,O,LCUC);
293 	svr4_to_bsd_flag1(c_oflag,O,NLCR);
294 	undefined_flag1(c_oflag,O,CRNL);
295 	undefined_flag1(c_oflag,O,NOCR);
296 	undefined_flag1(c_oflag,O,NLRET);
297 	undefined_flag1(c_oflag,O,FILL);
298 	undefined_flag1(c_oflag,O,FDEL);
299 	undefined_flag2(c_oflag,N,LDLY,N,L0,N,L1);
300 	undefined_flag4(c_oflag,C,RDLY,C,R0,C,R1,C,R2,C,R3);
301 	undefined_flag4(c_oflag,T,ABDLY,T,AB0,T,AB1,T,AB2,T,AB3);
302 	undefined_flag2(c_oflag,B,SDLY,B,S0,B,S1);
303 	undefined_flag2(c_oflag,V,TDLY,V,T0,V,T1);
304 	undefined_flag2(c_oflag,F,FDLY,F,F0,F,F1);
305 	undefined_flag1(c_oflag,P,AGEOUT);
306 	undefined_flag1(c_oflag,W,RAP);
307 
308 	/* Control modes */
309 	bt->c_ospeed = svr4_to_bsd_speed(st->c_cflag, SVR4_CBAUD);
310 	svr4_to_bsd_flag4(c_cflag,C,SIZE,C,S5,C,S6,C,S7,C,S8)
311 	svr4_to_bsd_flag1(c_cflag,C,STOPB);
312 	svr4_to_bsd_flag1(c_cflag,C,READ);
313 	svr4_to_bsd_flag1(c_cflag,P,ARENB);
314 	svr4_to_bsd_flag1(c_cflag,P,ARODD);
315 	svr4_to_bsd_flag1(c_cflag,H,UPCL);
316 	svr4_to_bsd_flag1(c_cflag,C,LOCAL);
317 	undefined_flag1(c_cflag,R,CV1EN);
318 	undefined_flag1(c_cflag,X,MT1EN);
319 	undefined_flag1(c_cflag,L,OBLK);
320 	undefined_flag1(c_cflag,X,CLUDE);
321 	bt->c_ispeed = svr4_to_bsd_speed(st->c_cflag, SVR4_CIBAUD);
322 	undefined_flag1(c_cflag,P,AREXT);
323 
324 	/* line discipline modes */
325 	svr4_to_bsd_flag1(c_lflag,I,SIG);
326 	svr4_to_bsd_flag1(c_lflag,I,CANON);
327 	undefined_flag1(c_lflag,X,CASE);
328 	svr4_to_bsd_flag1(c_lflag,E,CHO);
329 	svr4_to_bsd_flag1(c_lflag,E,CHOE);
330 	svr4_to_bsd_flag1(c_lflag,E,CHOK);
331 	svr4_to_bsd_flag1(c_lflag,E,CHONL);
332 	svr4_to_bsd_flag1(c_lflag,N,OFLSH);
333 	svr4_to_bsd_flag1(c_lflag,T,OSTOP);
334 	svr4_to_bsd_flag1(c_lflag,E,CHOCTL);
335 	svr4_to_bsd_flag1(c_lflag,E,CHOPRT);
336 	svr4_to_bsd_flag1(c_lflag,E,CHOKE);
337 	undefined_flag1(c_lflag,D,EFECHO);
338 	svr4_to_bsd_flag1(c_lflag,F,LUSHO);
339 	svr4_to_bsd_flag1(c_lflag,P,ENDIN);
340 	svr4_to_bsd_flag1(c_lflag,I,EXTEN);
341 }
342 
343 
344 static void
bsd_to_svr4_termios(bt,st)345 bsd_to_svr4_termios(bt, st)
346 	const struct termios 	*bt;
347 	struct svr4_termios	*st;
348 {
349 	/* control characters */
350 	/*
351 	 * We process VMIN and VTIME first,
352 	 * because they are shared with VEOF and VEOL
353 	 */
354 	bsd_to_svr4_char(V,MIN);
355 	bsd_to_svr4_char(V,TIME);
356 	bsd_to_svr4_char(V,INTR);
357 	bsd_to_svr4_char(V,QUIT);
358 	bsd_to_svr4_char(V,ERASE);
359 	bsd_to_svr4_char(V,KILL);
360 	bsd_to_svr4_char(V,EOF);
361 	bsd_to_svr4_char(V,EOL);
362 	bsd_to_svr4_char(V,EOL2);
363 	undefined_char(V,SWTCH);
364 	bsd_to_svr4_char(V,START);
365 	bsd_to_svr4_char(V,STOP);
366 	bsd_to_svr4_char(V,SUSP);
367 	bsd_to_svr4_char(V,DSUSP);
368 	bsd_to_svr4_char(V,REPRINT);
369 	bsd_to_svr4_char(V,DISCARD);
370 	bsd_to_svr4_char(V,WERASE);
371 	bsd_to_svr4_char(V,LNEXT);
372 
373 	/* Input modes */
374 	bsd_to_svr4_flag1(c_iflag,I,GNBRK);
375 	bsd_to_svr4_flag1(c_iflag,B,RKINT);
376 	bsd_to_svr4_flag1(c_iflag,I,GNPAR);
377 	bsd_to_svr4_flag1(c_iflag,P,ARMRK);
378 	bsd_to_svr4_flag1(c_iflag,I,NPCK);
379 	bsd_to_svr4_flag1(c_iflag,I,STRIP);
380 	bsd_to_svr4_flag1(c_iflag,I,NLCR);
381 	bsd_to_svr4_flag1(c_iflag,I,GNCR);
382 	bsd_to_svr4_flag1(c_iflag,I,CRNL);
383 	undefined_flag1(c_iflag,I,UCLC);
384 	bsd_to_svr4_flag1(c_iflag,I,XON);
385 	bsd_to_svr4_flag1(c_iflag,I,XANY);
386 	bsd_to_svr4_flag1(c_iflag,I,XOFF);
387 	bsd_to_svr4_flag1(c_iflag,I,MAXBEL);
388 	undefined_flag1(c_iflag,D,OSMODE);
389 
390 	/* Output modes */
391 	bsd_to_svr4_flag1(c_oflag,O,POST);
392 	undefined_flag1(c_oflag,O,LCUC);
393 	bsd_to_svr4_flag1(c_oflag,O,NLCR);
394 	undefined_flag1(c_oflag,O,CRNL);
395 	undefined_flag1(c_oflag,O,NOCR);
396 	undefined_flag1(c_oflag,O,NLRET);
397 	undefined_flag1(c_oflag,O,FILL);
398 	undefined_flag1(c_oflag,O,FDEL);
399 	undefined_flag2(c_oflag,N,LDLY,N,L0,N,L1);
400 	undefined_flag4(c_oflag,C,RDLY,C,R0,C,R1,C,R2,C,R3);
401 	undefined_flag4(c_oflag,T,ABDLY,T,AB0,T,AB1,T,AB2,T,AB3);
402 	undefined_flag2(c_oflag,B,SDLY,B,S0,B,S1);
403 	undefined_flag2(c_oflag,V,TDLY,V,T0,V,T1);
404 	undefined_flag2(c_oflag,F,FDLY,F,F0,F,F1);
405 	undefined_flag1(c_oflag,P,AGEOUT);
406 	undefined_flag1(c_oflag,W,RAP);
407 
408 	/* Control modes */
409 	st->c_cflag &= ~SVR4_CBAUD;
410 	st->c_cflag |= bsd_to_svr4_speed(bt->c_ospeed, SVR4_CBAUD);
411 	bsd_to_svr4_flag4(c_cflag,C,SIZE,C,S5,C,S6,C,S7,C,S8)
412 	bsd_to_svr4_flag1(c_cflag,C,STOPB);
413 	bsd_to_svr4_flag1(c_cflag,C,READ);
414 	bsd_to_svr4_flag1(c_cflag,P,ARENB);
415 	bsd_to_svr4_flag1(c_cflag,P,ARODD);
416 	bsd_to_svr4_flag1(c_cflag,H,UPCL);
417 	bsd_to_svr4_flag1(c_cflag,C,LOCAL);
418 	undefined_flag1(c_cflag,R,CV1EN);
419 	undefined_flag1(c_cflag,X,MT1EN);
420 	undefined_flag1(c_cflag,L,OBLK);
421 	undefined_flag1(c_cflag,X,CLUDE);
422 	st->c_cflag &= ~SVR4_CIBAUD;
423 	st->c_cflag |= bsd_to_svr4_speed(bt->c_ispeed, SVR4_CIBAUD);
424 
425 	undefined_flag1(c_oflag,P,AREXT);
426 
427 	/* line discipline modes */
428 	bsd_to_svr4_flag1(c_lflag,I,SIG);
429 	bsd_to_svr4_flag1(c_lflag,I,CANON);
430 	undefined_flag1(c_lflag,X,CASE);
431 	bsd_to_svr4_flag1(c_lflag,E,CHO);
432 	bsd_to_svr4_flag1(c_lflag,E,CHOE);
433 	bsd_to_svr4_flag1(c_lflag,E,CHOK);
434 	bsd_to_svr4_flag1(c_lflag,E,CHONL);
435 	bsd_to_svr4_flag1(c_lflag,N,OFLSH);
436 	bsd_to_svr4_flag1(c_lflag,T,OSTOP);
437 	bsd_to_svr4_flag1(c_lflag,E,CHOCTL);
438 	bsd_to_svr4_flag1(c_lflag,E,CHOPRT);
439 	bsd_to_svr4_flag1(c_lflag,E,CHOKE);
440 	undefined_flag1(c_lflag,D,EFECHO);
441 	bsd_to_svr4_flag1(c_lflag,F,LUSHO);
442 	bsd_to_svr4_flag1(c_lflag,P,ENDIN);
443 	bsd_to_svr4_flag1(c_lflag,I,EXTEN);
444 }
445 
446 
447 static void
svr4_termio_to_termios(t,ts)448 svr4_termio_to_termios(t, ts)
449 	const struct svr4_termio	*t;
450 	struct svr4_termios		*ts;
451 {
452 	int i;
453 
454 	ts->c_iflag = (svr4_tcflag_t) t->c_iflag;
455 	ts->c_oflag = (svr4_tcflag_t) t->c_oflag;
456 	ts->c_cflag = (svr4_tcflag_t) t->c_cflag;
457 	ts->c_lflag = (svr4_tcflag_t) t->c_lflag;
458 
459 	for (i = 0; i < SVR4_NCC; i++)
460 		ts->c_cc[i] = (svr4_cc_t) t->c_cc[i];
461 }
462 
463 
464 static void
svr4_termios_to_termio(ts,t)465 svr4_termios_to_termio(ts, t)
466 	const struct svr4_termios	*ts;
467 	struct svr4_termio		*t;
468 {
469 	int i;
470 
471 	t->c_iflag = (u_short) ts->c_iflag;
472 	t->c_oflag = (u_short) ts->c_oflag;
473 	t->c_cflag = (u_short) ts->c_cflag;
474 	t->c_lflag = (u_short) ts->c_lflag;
475 	t->c_line = 0;	/* XXX */
476 
477 	for (i = 0; i < SVR4_NCC; i++)
478 		t->c_cc[i] = (u_char) ts->c_cc[i];
479 }
480 
481 int
svr4_term_ioctl(fp,td,retval,fd,cmd,data)482 svr4_term_ioctl(fp, td, retval, fd, cmd, data)
483 	struct file *fp;
484 	struct thread *td;
485 	register_t *retval;
486 	int fd;
487 	u_long cmd;
488 	caddr_t data;
489 {
490 	struct termios 		bt;
491 	struct svr4_termios	st;
492 	struct svr4_termio	t;
493 	int			error, new;
494 
495 	*retval = 0;
496 
497 	DPRINTF(("TERM ioctl %lx\n", cmd));
498 
499 	switch (cmd) {
500 	case SVR4_TCGETA:
501 	case SVR4_TCGETS:
502 		DPRINTF(("ioctl(TCGET%c);\n", cmd == SVR4_TCGETA ? 'A' : 'S'));
503 		if ((error = fo_ioctl(fp, TIOCGETA, (caddr_t) &bt,
504 		    td->td_ucred, td)) != 0)
505 			return error;
506 
507 		memset(&st, 0, sizeof(st));
508 		bsd_to_svr4_termios(&bt, &st);
509 
510 #ifdef DEBUG_SVR4
511 		print_bsd_termios(&bt);
512 		print_svr4_termios(&st);
513 #endif /* DEBUG_SVR4 */
514 
515 		if (cmd == SVR4_TCGETA) {
516 		    svr4_termios_to_termio(&st, &t);
517 		    return copyout(&t, data, sizeof(t));
518 		}
519 		else  {
520 		    return copyout(&st, data, sizeof(st));
521 		}
522 
523 	case SVR4_TCSETA:
524 	case SVR4_TCSETS:
525 	case SVR4_TCSETAW:
526 	case SVR4_TCSETSW:
527 	case SVR4_TCSETAF:
528 	case SVR4_TCSETSF:
529 	        DPRINTF(("TCSET{A,S,AW,SW,AF,SF}\n"));
530 		/* get full BSD termios so we don't lose information */
531 		if ((error = fo_ioctl(fp, TIOCGETA, (caddr_t) &bt,
532 		    td->td_ucred, td)) != 0)
533 			return error;
534 
535 		switch (cmd) {
536 		case SVR4_TCSETS:
537 		case SVR4_TCSETSW:
538 		case SVR4_TCSETSF:
539 			if ((error = copyin(data, &st, sizeof(st))) != 0)
540 				return error;
541 			new = 1;
542 			break;
543 
544 		case SVR4_TCSETA:
545 		case SVR4_TCSETAW:
546 		case SVR4_TCSETAF:
547 			if ((error = copyin(data, &t, sizeof(t))) != 0)
548 				return error;
549 
550 			svr4_termio_to_termios(&t, &st);
551 			new = 0;
552 			break;
553 
554 		default:
555 			return EINVAL;
556 		}
557 
558 		svr4_to_bsd_termios(&st, &bt, new);
559 
560 		switch (cmd) {
561 		case SVR4_TCSETA:
562 		case SVR4_TCSETS:
563 			DPRINTF(("ioctl(TCSET[A|S]);\n"));
564 			cmd = TIOCSETA;
565 			break;
566 		case SVR4_TCSETAW:
567 		case SVR4_TCSETSW:
568 			DPRINTF(("ioctl(TCSET[A|S]W);\n"));
569 			cmd = TIOCSETAW;
570 			break;
571 		case SVR4_TCSETAF:
572 		case SVR4_TCSETSF:
573 			DPRINTF(("ioctl(TCSET[A|S]F);\n"));
574 			cmd = TIOCSETAF;
575 			break;
576 		}
577 
578 #ifdef DEBUG_SVR4
579 		print_bsd_termios(&bt);
580 		print_svr4_termios(&st);
581 #endif /* DEBUG_SVR4 */
582 
583 		return fo_ioctl(fp, cmd, (caddr_t) &bt, td->td_ucred, td);
584 
585 	case SVR4_TIOCGWINSZ:
586 	        DPRINTF(("TIOCGWINSZ\n"));
587 		{
588 			struct svr4_winsize ws;
589 
590 			error = fo_ioctl(fp, TIOCGWINSZ, (caddr_t) &ws,
591 			    td->td_ucred, td);
592 			if (error)
593 				return error;
594 			return copyout(&ws, data, sizeof(ws));
595 		}
596 
597 	case SVR4_TIOCSWINSZ:
598 	        DPRINTF(("TIOCSWINSZ\n"));
599 		{
600 			struct svr4_winsize ws;
601 
602 			if ((error = copyin(data, &ws, sizeof(ws))) != 0)
603 				return error;
604 			return fo_ioctl(fp, TIOCSWINSZ, (caddr_t) &ws,
605 			    td->td_ucred, td);
606 		}
607 
608 	default:
609 	        DPRINTF(("teleport to STREAMS ioctls...\n"));
610 		return svr4_stream_ti_ioctl(fp, td, retval, fd, cmd, data);
611 	}
612 }
613