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