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