xref: /netbsd-src/sys/compat/sunos/sunos_ioctl.c (revision ae1bfcddc410612bc8c58b807e1830becb69a24c)
1 /*
2  * Copyright (c) 1993 Markus Wild.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. The name of the author may not be used to endorse or promote products
11  *    derived from this software without specific prior written permission
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  * loosely from: Header: sun_ioctl.c,v 1.7 93/05/28 04:40:43 torek Exp
25  * $Id: sunos_ioctl.c,v 1.10 1994/05/21 08:22:08 deraadt Exp $
26  */
27 
28 #include <sys/param.h>
29 #include <sys/proc.h>
30 #include <sys/file.h>
31 #include <sys/filedesc.h>
32 #include <sys/ioctl.h>
33 #include <sys/termios.h>
34 #include <sys/tty.h>
35 #include <sys/socket.h>
36 #include <sys/ioctl.h>
37 #include <net/if.h>
38 
39 /*
40  * SunOS ioctl calls.
41  * This file is something of a hodge-podge.
42  * Support gets added as things turn up....
43  */
44 
45 struct sun_ttysize {
46 	int	ts_row;
47 	int	ts_col;
48 };
49 
50 struct sun_termio {
51 	u_short	c_iflag;
52 	u_short	c_oflag;
53 	u_short	c_cflag;
54 	u_short	c_lflag;
55 	char	c_line;
56 	unsigned char c_cc[8];
57 };
58 #define SUN_TCGETA	_IOR('T', 1, struct sun_termio)
59 #define SUN_TCSETA	_IOW('T', 2, struct sun_termio)
60 #define SUN_TCSETAW	_IOW('T', 3, struct sun_termio)
61 #define SUN_TCSETAF	_IOW('T', 4, struct sun_termio)
62 #define SUN_TCSBRK	_IO('T', 5)
63 
64 struct sun_termios {
65 	u_long	c_iflag;
66 	u_long	c_oflag;
67 	u_long	c_cflag;
68 	u_long	c_lflag;
69 	char	c_line;
70 	u_char	c_cc[17];
71 };
72 #define SUN_TCXONC	_IO('T', 6)
73 #define SUN_TCFLSH	_IO('T', 7)
74 #define SUN_TCGETS	_IOR('T', 8, struct sun_termios)
75 #define SUN_TCSETS	_IOW('T', 9, struct sun_termios)
76 #define SUN_TCSETSW	_IOW('T', 10, struct sun_termios)
77 #define SUN_TCSETSF	_IOW('T', 11, struct sun_termios)
78 #define SUN_TCSNDBRK	_IO('T', 12)
79 #define SUN_TCDRAIN	_IO('T', 13)
80 
81 static struct speedtab sptab[] = {
82 	{ 0, 0 },
83 	{ 50, 1 },
84 	{ 75, 2 },
85 	{ 110, 3 },
86 	{ 134, 4 },
87 	{ 135, 4 },
88 	{ 150, 5 },
89 	{ 200, 6 },
90 	{ 300, 7 },
91 	{ 600, 8 },
92 	{ 1200, 9 },
93 	{ 1800, 10 },
94 	{ 2400, 11 },
95 	{ 4800, 12 },
96 	{ 9600, 13 },
97 	{ 19200, 14 },
98 	{ 38400, 15 },
99 	{ -1, -1 }
100 };
101 
102 static u_long s2btab[] = {
103 	0,
104 	50,
105 	75,
106 	110,
107 	134,
108 	150,
109 	200,
110 	300,
111 	600,
112 	1200,
113 	1800,
114 	2400,
115 	4800,
116 	9600,
117 	19200,
118 	38400,
119 };
120 
121 /*
122  * these two conversion functions have mostly been done
123  * with some perl cut&paste, then handedited to comment
124  * out what doesn't exist under NetBSD.
125  * A note from Markus's code:
126  *	(l & BITMASK1) / BITMASK1 * BITMASK2  is translated
127  *	optimally by gcc m68k, much better than any ?: stuff.
128  *	Code may vary with different architectures of course.
129  *
130  * I don't know what optimizer you used, but seeing divu's and
131  * bfextu's in the m68k assembly output did not encourage me...
132  * as well, gcc on the sparc definately generates much better
133  * code with ?:.
134  */
135 
136 static void
137 stios2btios(st, bt)
138 	struct sun_termios *st;
139 	struct termios *bt;
140 {
141 	register u_long l, r;
142 
143 	l = st->c_iflag;
144 	r = 	((l & 0x00000001) ? IGNBRK	: 0);
145 	r |=	((l & 0x00000002) ? BRKINT	: 0);
146 	r |=	((l & 0x00000004) ? IGNPAR	: 0);
147 	r |=	((l & 0x00000008) ? PARMRK	: 0);
148 	r |=	((l & 0x00000010) ? INPCK	: 0);
149 	r |=	((l & 0x00000020) ? ISTRIP	: 0);
150 	r |= 	((l & 0x00000040) ? INLCR	: 0);
151 	r |=	((l & 0x00000080) ? IGNCR	: 0);
152 	r |=	((l & 0x00000100) ? ICRNL	: 0);
153 	/*	((l & 0x00000200) ? IUCLC	: 0) */
154 	r |=	((l & 0x00000400) ? IXON	: 0);
155 	r |=	((l & 0x00000800) ? IXANY	: 0);
156 	r |=	((l & 0x00001000) ? IXOFF	: 0);
157 	r |=	((l & 0x00002000) ? IMAXBEL	: 0);
158 	bt->c_iflag = r;
159 
160 	l = st->c_oflag;
161 	r = 	((l & 0x00000001) ? OPOST	: 0);
162 	/*	((l & 0x00000002) ? OLCUC	: 0) */
163 	r |=	((l & 0x00000004) ? ONLCR	: 0);
164 	/*	((l & 0x00000008) ? OCRNL	: 0) */
165 	/*	((l & 0x00000010) ? ONOCR	: 0) */
166 	/*	((l & 0x00000020) ? ONLRET	: 0) */
167 	/*	((l & 0x00000040) ? OFILL	: 0) */
168 	/*	((l & 0x00000080) ? OFDEL	: 0) */
169 	/*	((l & 0x00000100) ? NLDLY	: 0) */
170 	/*	((l & 0x00000100) ? NL1		: 0) */
171 	/*	((l & 0x00000600) ? CRDLY	: 0) */
172 	/*	((l & 0x00000200) ? CR1		: 0) */
173 	/*	((l & 0x00000400) ? CR2		: 0) */
174 	/*	((l & 0x00000600) ? CR3		: 0) */
175 	/*	((l & 0x00001800) ? TABDLY	: 0) */
176 	/*	((l & 0x00000800) ? TAB1	: 0) */
177 	/*	((l & 0x00001000) ? TAB2	: 0) */
178 	r |=	((l & 0x00001800) ? OXTABS	: 0);
179 	/*	((l & 0x00002000) ? BSDLY	: 0) */
180 	/*	((l & 0x00002000) ? BS1		: 0) */
181 	/*	((l & 0x00004000) ? VTDLY	: 0) */
182 	/*	((l & 0x00004000) ? VT1		: 0) */
183 	/*	((l & 0x00008000) ? FFDLY	: 0) */
184 	/*	((l & 0x00008000) ? FF1		: 0) */
185 	/*	((l & 0x00010000) ? PAGEOUT	: 0) */
186 	/*	((l & 0x00020000) ? WRAP	: 0) */
187 	bt->c_oflag = r;
188 
189 	l = st->c_cflag;
190 	r = 	((l & 0x00000010) ? CS6		: 0);
191 	r |=	((l & 0x00000020) ? CS7		: 0);
192 	r |=	((l & 0x00000030) ? CS8		: 0);
193 	r |=	((l & 0x00000040) ? CSTOPB	: 0);
194 	r |=	((l & 0x00000080) ? CREAD	: 0);
195 	r |= 	((l & 0x00000100) ? PARENB	: 0);
196 	r |=	((l & 0x00000200) ? PARODD	: 0);
197 	r |=	((l & 0x00000400) ? HUPCL	: 0);
198 	r |=	((l & 0x00000800) ? CLOCAL	: 0);
199 	/*	((l & 0x00001000) ? LOBLK	: 0) */
200 	r |=	((l & 0x80000000) ? (CRTS_IFLOW|CCTS_OFLOW) : 0);
201 	bt->c_cflag = r;
202 
203 	bt->c_ispeed = bt->c_ospeed = s2btab[l & 0x0000000f];
204 
205 	l = st->c_lflag;
206 	r = 	((l & 0x00000001) ? ISIG	: 0);
207 	r |=	((l & 0x00000002) ? ICANON	: 0);
208 	/*	((l & 0x00000004) ? XCASE	: 0) */
209 	r |=	((l & 0x00000008) ? ECHO	: 0);
210 	r |=	((l & 0x00000010) ? ECHOE	: 0);
211 	r |=	((l & 0x00000020) ? ECHOK	: 0);
212 	r |=	((l & 0x00000040) ? ECHONL	: 0);
213 	r |= 	((l & 0x00000080) ? NOFLSH	: 0);
214 	r |=	((l & 0x00000100) ? TOSTOP	: 0);
215 	r |=	((l & 0x00000200) ? ECHOCTL	: 0);
216 	r |=	((l & 0x00000400) ? ECHOPRT	: 0);
217 	r |=	((l & 0x00000800) ? ECHOKE	: 0);
218 	/*	((l & 0x00001000) ? DEFECHO	: 0) */
219 	r |=	((l & 0x00002000) ? FLUSHO	: 0);
220 	r |=	((l & 0x00004000) ? PENDIN	: 0);
221 	bt->c_lflag = r;
222 
223 	bt->c_cc[VINTR]    = st->c_cc[0]  ? st->c_cc[0]  : _POSIX_VDISABLE;
224 	bt->c_cc[VQUIT]    = st->c_cc[1]  ? st->c_cc[1]  : _POSIX_VDISABLE;
225 	bt->c_cc[VERASE]   = st->c_cc[2]  ? st->c_cc[2]  : _POSIX_VDISABLE;
226 	bt->c_cc[VKILL]    = st->c_cc[3]  ? st->c_cc[3]  : _POSIX_VDISABLE;
227 	bt->c_cc[VEOF]     = st->c_cc[4]  ? st->c_cc[4]  : _POSIX_VDISABLE;
228 	bt->c_cc[VEOL]     = st->c_cc[5]  ? st->c_cc[5]  : _POSIX_VDISABLE;
229 	bt->c_cc[VEOL2]    = st->c_cc[6]  ? st->c_cc[6]  : _POSIX_VDISABLE;
230     /*	bt->c_cc[VSWTCH]   = st->c_cc[7]  ? st->c_cc[7]  : _POSIX_VDISABLE; */
231 	bt->c_cc[VSTART]   = st->c_cc[8]  ? st->c_cc[8]  : _POSIX_VDISABLE;
232 	bt->c_cc[VSTOP]    = st->c_cc[9]  ? st->c_cc[9]  : _POSIX_VDISABLE;
233 	bt->c_cc[VSUSP]    = st->c_cc[10] ? st->c_cc[10] : _POSIX_VDISABLE;
234 	bt->c_cc[VDSUSP]   = st->c_cc[11] ? st->c_cc[11] : _POSIX_VDISABLE;
235 	bt->c_cc[VREPRINT] = st->c_cc[12] ? st->c_cc[12] : _POSIX_VDISABLE;
236 	bt->c_cc[VDISCARD] = st->c_cc[13] ? st->c_cc[13] : _POSIX_VDISABLE;
237 	bt->c_cc[VWERASE]  = st->c_cc[14] ? st->c_cc[14] : _POSIX_VDISABLE;
238 	bt->c_cc[VLNEXT]   = st->c_cc[15] ? st->c_cc[15] : _POSIX_VDISABLE;
239 	bt->c_cc[VSTATUS]  = st->c_cc[16] ? st->c_cc[16] : _POSIX_VDISABLE;
240 }
241 
242 
243 static void
244 btios2stios(bt, st)
245 	struct termios *bt;
246 	struct sun_termios *st;
247 {
248 	register u_long l, r;
249 
250 	l = bt->c_iflag;
251 	r = 	((l &  IGNBRK) ? 0x00000001	: 0);
252 	r |=	((l &  BRKINT) ? 0x00000002	: 0);
253 	r |=	((l &  IGNPAR) ? 0x00000004	: 0);
254 	r |=	((l &  PARMRK) ? 0x00000008	: 0);
255 	r |=	((l &   INPCK) ? 0x00000010	: 0);
256 	r |=	((l &  ISTRIP) ? 0x00000020	: 0);
257 	r |=	((l &   INLCR) ? 0x00000040	: 0);
258 	r |=	((l &   IGNCR) ? 0x00000080	: 0);
259 	r |=	((l &   ICRNL) ? 0x00000100	: 0);
260 	/*	((l &   IUCLC) ? 0x00000200	: 0) */
261 	r |=	((l &    IXON) ? 0x00000400	: 0);
262 	r |=	((l &   IXANY) ? 0x00000800	: 0);
263 	r |=	((l &   IXOFF) ? 0x00001000	: 0);
264 	r |=	((l & IMAXBEL) ? 0x00002000	: 0);
265 	st->c_iflag = r;
266 
267 	l = bt->c_oflag;
268 	r =	((l &   OPOST) ? 0x00000001	: 0);
269 	/*	((l &   OLCUC) ? 0x00000002	: 0) */
270 	r |=	((l &   ONLCR) ? 0x00000004	: 0);
271 	/*	((l &   OCRNL) ? 0x00000008	: 0) */
272 	/*	((l &   ONOCR) ? 0x00000010	: 0) */
273 	/*	((l &  ONLRET) ? 0x00000020	: 0) */
274 	/*	((l &   OFILL) ? 0x00000040	: 0) */
275 	/*	((l &   OFDEL) ? 0x00000080	: 0) */
276 	/*	((l &   NLDLY) ? 0x00000100	: 0) */
277 	/*	((l &     NL1) ? 0x00000100	: 0) */
278 	/*	((l &   CRDLY) ? 0x00000600	: 0) */
279 	/*	((l &     CR1) ? 0x00000200	: 0) */
280 	/*	((l &     CR2) ? 0x00000400	: 0) */
281 	/*	((l &     CR3) ? 0x00000600	: 0) */
282 	/*	((l &  TABDLY) ? 0x00001800	: 0) */
283 	/*	((l &    TAB1) ? 0x00000800	: 0) */
284 	/*	((l &    TAB2) ? 0x00001000	: 0) */
285 	r |=	((l &  OXTABS) ? 0x00001800	: 0);
286 	/*	((l &   BSDLY) ? 0x00002000	: 0) */
287 	/*	((l &     BS1) ? 0x00002000	: 0) */
288 	/*	((l &   VTDLY) ? 0x00004000	: 0) */
289 	/*	((l &     VT1) ? 0x00004000	: 0) */
290 	/*	((l &   FFDLY) ? 0x00008000	: 0) */
291 	/*	((l &     FF1) ? 0x00008000	: 0) */
292 	/*	((l & PAGEOUT) ? 0x00010000	: 0) */
293 	/*	((l &    WRAP) ? 0x00020000	: 0) */
294 	st->c_oflag = r;
295 
296 	l = bt->c_cflag;
297 	r = 	((l &     CS6) ? 0x00000010	: 0);
298 	r |=	((l &     CS7) ? 0x00000020	: 0);
299 	r |=	((l &     CS8) ? 0x00000030	: 0);
300 	r |=	((l &  CSTOPB) ? 0x00000040	: 0);
301 	r |=	((l &   CREAD) ? 0x00000080	: 0);
302 	r |=	((l &  PARENB) ? 0x00000100	: 0);
303 	r |=	((l &  PARODD) ? 0x00000200	: 0);
304 	r |=	((l &   HUPCL) ? 0x00000400	: 0);
305 	r |=	((l &  CLOCAL) ? 0x00000800	: 0);
306 	/*	((l &   LOBLK) ? 0x00001000	: 0) */
307 	r |=	((l & (CRTS_IFLOW|CCTS_OFLOW)) ? 0x80000000 : 0);
308 	st->c_cflag = r;
309 
310 	l = bt->c_lflag;
311 	r =	((l &    ISIG) ? 0x00000001	: 0);
312 	r |=	((l &  ICANON) ? 0x00000002	: 0);
313 	/*	((l &   XCASE) ? 0x00000004	: 0) */
314 	r |=	((l &    ECHO) ? 0x00000008	: 0);
315 	r |=	((l &   ECHOE) ? 0x00000010	: 0);
316 	r |=	((l &   ECHOK) ? 0x00000020	: 0);
317 	r |=	((l &  ECHONL) ? 0x00000040	: 0);
318 	r |=	((l &  NOFLSH) ? 0x00000080	: 0);
319 	r |=	((l &  TOSTOP) ? 0x00000100	: 0);
320 	r |=	((l & ECHOCTL) ? 0x00000200	: 0);
321 	r |=	((l & ECHOPRT) ? 0x00000400	: 0);
322 	r |=	((l &  ECHOKE) ? 0x00000800	: 0);
323 	/*	((l & DEFECHO) ? 0x00001000	: 0) */
324 	r |=	((l &  FLUSHO) ? 0x00002000	: 0);
325 	r |=	((l &  PENDIN) ? 0x00004000	: 0);
326 	st->c_lflag = r;
327 
328 	l = ttspeedtab(bt->c_ospeed, sptab);
329 	if (l >= 0)
330 		st->c_cflag |= l;
331 
332 	st->c_cc[0] = bt->c_cc[VINTR]   != _POSIX_VDISABLE? bt->c_cc[VINTR]:0;
333 	st->c_cc[1] = bt->c_cc[VQUIT]   != _POSIX_VDISABLE? bt->c_cc[VQUIT]:0;
334 	st->c_cc[2] = bt->c_cc[VERASE]  != _POSIX_VDISABLE? bt->c_cc[VERASE]:0;
335 	st->c_cc[3] = bt->c_cc[VKILL]   != _POSIX_VDISABLE? bt->c_cc[VKILL]:0;
336 	st->c_cc[4] = bt->c_cc[VEOF]    != _POSIX_VDISABLE? bt->c_cc[VEOF]:0;
337 	st->c_cc[5] = bt->c_cc[VEOL]    != _POSIX_VDISABLE? bt->c_cc[VEOL]:0;
338 	st->c_cc[6] = bt->c_cc[VEOL2]   != _POSIX_VDISABLE? bt->c_cc[VEOL2]:0;
339 	st->c_cc[7] = 0;
340 		/*    bt->c_cc[VSWTCH]  != _POSIX_VDISABLE? bt->c_cc[VSWTCH]: */
341 	st->c_cc[8] = bt->c_cc[VSTART]  != _POSIX_VDISABLE? bt->c_cc[VSTART]:0;
342 	st->c_cc[9] = bt->c_cc[VSTOP]   != _POSIX_VDISABLE? bt->c_cc[VSTOP]:0;
343 	st->c_cc[10]= bt->c_cc[VSUSP]   != _POSIX_VDISABLE? bt->c_cc[VSUSP]:0;
344 	st->c_cc[11]= bt->c_cc[VDSUSP]  != _POSIX_VDISABLE? bt->c_cc[VDSUSP]:0;
345 	st->c_cc[12]= bt->c_cc[VREPRINT]!= _POSIX_VDISABLE? bt->c_cc[VREPRINT]:0;
346 	st->c_cc[13]= bt->c_cc[VDISCARD]!= _POSIX_VDISABLE? bt->c_cc[VDISCARD]:0;
347 	st->c_cc[14]= bt->c_cc[VWERASE] != _POSIX_VDISABLE? bt->c_cc[VWERASE]:0;
348 	st->c_cc[15]= bt->c_cc[VLNEXT]  != _POSIX_VDISABLE? bt->c_cc[VLNEXT]:0;
349 	st->c_cc[16]= bt->c_cc[VSTATUS] != _POSIX_VDISABLE? bt->c_cc[VSTATUS]:0;
350 
351 	st->c_line = 0;
352 }
353 
354 static void
355 stios2stio(ts, t)
356 	struct sun_termios *ts;
357 	struct sun_termio *t;
358 {
359 	t->c_iflag = ts->c_iflag;
360 	t->c_oflag = ts->c_oflag;
361 	t->c_cflag = ts->c_cflag;
362 	t->c_lflag = ts->c_lflag;
363 	t->c_line  = ts->c_line;
364 	bcopy(ts->c_cc, t->c_cc, 8);
365 }
366 
367 static void
368 stio2stios(t, ts)
369 	struct sun_termio *t;
370 	struct sun_termios *ts;
371 {
372 	ts->c_iflag = t->c_iflag;
373 	ts->c_oflag = t->c_oflag;
374 	ts->c_cflag = t->c_cflag;
375 	ts->c_lflag = t->c_lflag;
376 	ts->c_line  = t->c_line;
377 	bcopy(t->c_cc, ts->c_cc, 8); /* don't touch the upper fields! */
378 }
379 
380 struct sun_ioctl_args {
381 	int	fd;
382 	int	cmd;
383 	caddr_t	data;
384 };
385 
386 int
387 sun_ioctl(p, uap, retval)
388 	register struct proc *p;
389 	register struct sun_ioctl_args *uap;
390 	int *retval;
391 {
392 	register struct filedesc *fdp = p->p_fd;
393 	register struct file *fp;
394 	register int (*ctl)();
395 	int error;
396 
397 	if ( (unsigned)uap->fd >= fdp->fd_nfiles ||
398 	    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
399 		return EBADF;
400 
401 	if ((fp->f_flag & (FREAD|FWRITE)) == 0)
402 		return EBADF;
403 
404 	ctl = fp->f_ops->fo_ioctl;
405 
406 	switch (uap->cmd) {
407 	case _IOR('t', 0, int):
408 		uap->cmd = TIOCGETD;
409 		break;
410 	case _IOW('t', 1, int):
411 	    {
412 		int disc;
413 
414 		if ((error = copyin(uap->data, (caddr_t)&disc,
415 		    sizeof disc)) != 0)
416 			return error;
417 
418 		/* map SunOS NTTYDISC into our termios discipline */
419 		if (disc == 2)
420 			disc = 0;
421 		/* all other disciplines are not supported by NetBSD */
422 		if (disc)
423 			return ENXIO;
424 
425 		return (*ctl)(fp, TIOCSETD, (caddr_t)&disc, p);
426 	    }
427 	case _IOW('t', 101, int):	/* sun SUN_TIOCSSOFTCAR */
428 	    {
429 		int x;	/* unused */
430 
431 		return copyin((caddr_t)&x, uap->data, sizeof x);
432 	    }
433 	case _IOR('t', 100, int):	/* sun SUN_TIOCSSOFTCAR */
434 	    {
435 		int x = 0;
436 
437 		return copyout((caddr_t)&x, uap->data, sizeof x);
438 	    }
439 	case _IO('t', 36): 		/* sun TIOCCONS, no parameters */
440 	    {
441 		int on = 1;
442 		return (*ctl)(fp, TIOCCONS, (caddr_t)&on, p);
443 	    }
444 	case _IOW('t', 37, struct sun_ttysize):
445 	    {
446 		struct winsize ws;
447 		struct sun_ttysize ss;
448 
449 		if ((error = (*ctl)(fp, TIOCGWINSZ, (caddr_t)&ws, p)) != 0)
450 			return (error);
451 
452 		if ((error = copyin (uap->data, &ss, sizeof (ss))) != 0)
453 			return error;
454 
455 		ws.ws_row = ss.ts_row;
456 		ws.ws_col = ss.ts_col;
457 
458 		return ((*ctl)(fp, TIOCSWINSZ, (caddr_t)&ws, p));
459 	    }
460 	case _IOW('t', 38, struct sun_ttysize):
461 	    {
462 		struct winsize ws;
463 		struct sun_ttysize ss;
464 
465 		if ((error = (*ctl)(fp, TIOCGWINSZ, (caddr_t)&ws, p)) != 0)
466 			return (error);
467 
468 		ss.ts_row = ws.ws_row;
469 		ss.ts_col = ws.ws_col;
470 
471 		return copyout ((caddr_t)&ss, uap->data, sizeof (ss));
472 	    }
473 	case _IOW('t', 130, int):
474 		uap->cmd = TIOCSPGRP;
475 		break;
476 	case _IOR('t', 131, int):
477 		uap->cmd = TIOCGPGRP;
478 		break;
479 	case _IO('t', 132):
480 		uap->cmd = TIOCSCTTY;
481 		break;
482 	case SUN_TCGETA:
483 	case SUN_TCGETS:
484 	    {
485 		struct termios bts;
486 		struct sun_termios sts;
487 		struct sun_termio st;
488 
489 		if ((error = (*ctl)(fp, TIOCGETA, (caddr_t)&bts, p)) != 0)
490 			return error;
491 
492 		btios2stios (&bts, &sts);
493 		if (uap->cmd == SUN_TCGETA) {
494 			stios2stio (&sts, &st);
495 			return copyout((caddr_t)&st, uap->data, sizeof (st));
496 		} else
497 			return copyout((caddr_t)&sts, uap->data, sizeof (sts));
498 		/*NOTREACHED*/
499 	    }
500 	case SUN_TCSETA:
501 	case SUN_TCSETAW:
502 	case SUN_TCSETAF:
503 	    {
504 		struct termios bts;
505 		struct sun_termios sts;
506 		struct sun_termio st;
507 
508 		if ((error = copyin(uap->data, (caddr_t)&st,
509 		    sizeof (st))) != 0)
510 			return error;
511 
512 		/* get full BSD termios so we don't lose information */
513 		if ((error = (*ctl)(fp, TIOCGETA, (caddr_t)&bts, p)) != 0)
514 			return error;
515 
516 		/*
517 		 * convert to sun termios, copy in information from
518 		 * termio, and convert back, then set new values.
519 		 */
520 		btios2stios(&bts, &sts);
521 		stio2stios(&st, &sts);
522 		stios2btios(&sts, &bts);
523 
524 		return (*ctl)(fp, uap->cmd - SUN_TCSETA + TIOCSETA,
525 		    (caddr_t)&bts, p);
526 	    }
527 	case SUN_TCSETS:
528 	case SUN_TCSETSW:
529 	case SUN_TCSETSF:
530 	    {
531 		struct termios bts;
532 		struct sun_termios sts;
533 
534 		if ((error = copyin (uap->data, (caddr_t)&sts,
535 		    sizeof (sts))) != 0)
536 			return error;
537 		stios2btios (&sts, &bts);
538 		return (*ctl)(fp, uap->cmd - SUN_TCSETS + TIOCSETA,
539 		    (caddr_t)&bts, p);
540 	    }
541 /*
542  * Pseudo-tty ioctl translations.
543  */
544 	case _IOW('t', 32, int): {	/* TIOCTCNTL */
545 		int error, on;
546 
547 		if (error = copyin (uap->data, (caddr_t)&on, sizeof (on)))
548 			return error;
549 		return (*ctl)(fp, TIOCUCNTL, (caddr_t)&on, p);
550 	}
551 	case _IOW('t', 33, int): {	/* TIOCSIGNAL */
552 		int error, sig;
553 
554 		if (error = copyin (uap->data, (caddr_t)&sig, sizeof (sig)))
555 			return error;
556 		return (*ctl)(fp, TIOCSIG, (caddr_t)&sig, p);
557 	}
558 
559 /*
560  * Socket ioctl translations.
561  */
562 #define IFREQ_IN(a) { \
563 	struct ifreq ifreq; \
564 	if (error = copyin (uap->data, (caddr_t)&ifreq, sizeof (ifreq))) \
565 		return error; \
566 	return (*ctl)(fp, a, (caddr_t)&ifreq, p); \
567 }
568 #define IFREQ_INOUT(a) { \
569 	struct ifreq ifreq; \
570 	if (error = copyin (uap->data, (caddr_t)&ifreq, sizeof (ifreq))) \
571 		return error; \
572 	if (error = (*ctl)(fp, a, (caddr_t)&ifreq, p)) \
573 		return error; \
574 	return copyout ((caddr_t)&ifreq, uap->data, sizeof (ifreq)); \
575 }
576 
577 	case _IOW('i', 12, struct ifreq):
578 		/* SIOCSIFADDR */
579 		break;
580 
581 	case _IOWR('i', 13, struct ifreq):
582 		IFREQ_INOUT(OSIOCGIFADDR);
583 
584 	case _IOW('i', 14, struct ifreq):
585 		/* SIOCSIFDSTADDR */
586 		break;
587 
588 	case _IOWR('i', 15, struct ifreq):
589 		IFREQ_INOUT(OSIOCGIFDSTADDR);
590 
591 	case _IOW('i', 16, struct ifreq):
592 		/* SIOCSIFFLAGS */
593 		break;
594 
595 	case _IOWR('i', 17, struct ifreq):
596 		/* SIOCGIFFLAGS */
597 		break;
598 
599 	case _IOW('i', 21, struct ifreq):
600 		IFREQ_IN(SIOCSIFMTU);
601 
602 	case _IOWR('i', 22, struct ifreq):
603 		IFREQ_INOUT(SIOCGIFMTU);
604 
605 	case _IOWR('i', 23, struct ifreq):
606 		IFREQ_INOUT(SIOCGIFBRDADDR);
607 
608 	case _IOW('i', 24, struct ifreq):
609 		IFREQ_IN(SIOCSIFBRDADDR);
610 
611 	case _IOWR('i', 25, struct ifreq):
612 		IFREQ_INOUT(OSIOCGIFNETMASK);
613 
614 	case _IOW('i', 26, struct ifreq):
615 		IFREQ_IN(SIOCSIFNETMASK);
616 
617 	case _IOWR('i', 27, struct ifreq):
618 		IFREQ_INOUT(SIOCGIFMETRIC);
619 
620 	case _IOWR('i', 28, struct ifreq):
621 		IFREQ_IN(SIOCSIFMETRIC);
622 
623 	case _IOW('i', 30, struct arpreq):
624 		/* SIOCSARP */
625 		break;
626 
627 	case _IOWR('i', 31, struct arpreq):
628 		/* SIOCGARP */
629 		break;
630 
631 	case _IOW('i', 32, struct arpreq):
632 		/* SIOCDARP */
633 		break;
634 
635 	case _IOW('i', 18, struct ifreq):	/* SIOCSIFMEM */
636 	case _IOWR('i', 19, struct ifreq):	/* SIOCGIFMEM */
637 	case _IOW('i', 40, struct ifreq):	/* SIOCUPPER */
638 	case _IOW('i', 41, struct ifreq):	/* SIOCLOWER */
639 	case _IOW('i', 44, struct ifreq):	/* SIOCSETSYNC */
640 	case _IOWR('i', 45, struct ifreq):	/* SIOCGETSYNC */
641 	case _IOWR('i', 46, struct ifreq):	/* SIOCSDSTATS */
642 	case _IOWR('i', 47, struct ifreq):	/* SIOCSESTATS */
643 	case _IOW('i', 48, int):		/* SIOCSPROMISC */
644 	case _IOW('i', 49, struct ifreq):	/* SIOCADDMULTI */
645 	case _IOW('i', 50, struct ifreq):	/* SIOCDELMULTI */
646 		return EOPNOTSUPP;
647 
648 	case _IOWR('i', 20, struct ifconf):	/* SIOCGIFCONF */
649 	    {
650 		struct ifconf ifconf;
651 
652 		/*
653 		 * XXX: two more problems
654 		 * 1. our sockaddr's are variable length, not always sizeof(sockaddr)
655 		 * 2. this returns a name per protocol, ie. it returns two "lo0"'s
656 		 */
657 		if (error = copyin (uap->data, (caddr_t)&ifconf, sizeof (ifconf)))
658 			return error;
659 		if (error = (*ctl)(fp, OSIOCGIFCONF, (caddr_t)&ifconf, p))
660 			return error;
661 		return copyout ((caddr_t)&ifconf, uap->data, sizeof (ifconf));
662 	    }
663 	}
664 	return (ioctl(p, uap, retval));
665 }
666