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