1 /*        $NetBSD: sunos32_ioctl.c,v 1.36 2021/09/07 11:43:05 riastradh Exp $   */
2 /* from: NetBSD: sunos_ioctl.c,v 1.35 2001/02/03 22:20:02 mrg Exp     */
3 
4 /*
5  * Copyright (c) 2001 Matthew R. Green
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
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,
22  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 /*
31  * Copyright (c) 1993 Markus Wild.
32  * All rights reserved.
33  *
34  * Redistribution and use in source and binary forms, with or without
35  * modification, are permitted provided that the following conditions
36  * are met:
37  * 1. Redistributions of source code must retain the above copyright
38  *    notice, this list of conditions and the following disclaimer.
39  * 2. The name of the author may not be used to endorse or promote products
40  *    derived from this software without specific prior written permission
41  *
42  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
43  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
44  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
45  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
46  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
47  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
48  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
49  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
50  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
51  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52  *
53  * loosely from: Header: sunos_ioctl.c,v 1.7 93/05/28 04:40:43 torek Exp
54  */
55 
56 #include <sys/cdefs.h>
57 __KERNEL_RCSID(0, "$NetBSD: sunos32_ioctl.c,v 1.36 2021/09/07 11:43:05 riastradh Exp $");
58 
59 #if defined(_KERNEL_OPT)
60 #include "opt_compat_netbsd32.h"
61 #include "opt_execfmt.h"
62 #endif
63 
64 #include <sys/param.h>
65 #include <sys/proc.h>
66 #include <sys/systm.h>
67 #include <sys/file.h>
68 #include <sys/filedesc.h>
69 #include <sys/ioctl.h>
70 #include <sys/termios.h>
71 #include <sys/tty.h>
72 #include <sys/socket.h>
73 #include <sys/audioio.h>
74 #include <sys/vnode.h>
75 #include <sys/mount.h>
76 #include <sys/disklabel.h>
77 #include <sys/syscallargs.h>
78 
79 #include <miscfs/specfs/specdev.h>
80 
81 #include <net/if.h>
82 
83 #include <dev/sun/disklabel.h>
84 
85 #include <compat/sys/sockio.h>
86 
87 #include <compat/sunos/sunos.h>
88 #include <compat/sunos/sunos_syscallargs.h>
89 #include <compat/netbsd32/netbsd32.h>
90 #include <compat/netbsd32/netbsd32_syscallargs.h>
91 #include <compat/sunos32/sunos32.h>
92 #include <compat/sunos32/sunos32_syscallargs.h>
93 #include <compat/common/compat_util.h>
94 
95 /*
96  * SunOS ioctl calls.
97  * This file is something of a hodge-podge.
98  * Support gets added as things turn up....
99  */
100 
101 static const struct speedtab sptab[] = {
102           { 0, 0 },
103           { 50, 1 },
104           { 75, 2 },
105           { 110, 3 },
106           { 134, 4 },
107           { 135, 4 },
108           { 150, 5 },
109           { 200, 6 },
110           { 300, 7 },
111           { 600, 8 },
112           { 1200, 9 },
113           { 1800, 10 },
114           { 2400, 11 },
115           { 4800, 12 },
116           { 9600, 13 },
117           { 19200, 14 },
118           { 38400, 15 },
119           { -1, -1 }
120 };
121 
122 static const netbsd32_u_long s2btab[] = {
123           0,
124           50,
125           75,
126           110,
127           134,
128           150,
129           200,
130           300,
131           600,
132           1200,
133           1800,
134           2400,
135           4800,
136           9600,
137           19200,
138           38400,
139 };
140 
141 static void stios2btios(struct sunos_termios *, struct termios *);
142 static void btios2stios(struct termios *, struct sunos_termios *);
143 static void stios2stio(struct sunos_termios *, struct sunos_termio *);
144 static void stio2stios(struct sunos_termio *, struct sunos_termios *);
145 
146 /*
147  * These two conversion functions have mostly been done
148  * with some perl cut&paste, then hand-edited to comment
149  * out what doesn't exist under NetBSD.
150  * A note from Markus's code:
151  *        (l & BITMASK1) / BITMASK1 * BITMASK2  is translated
152  *        optimally by gcc m68k, much better than any ?: stuff.
153  *        Code may vary with different architectures of course.
154  *
155  * I don't know what optimizer you used, but seeing divu's and
156  * bfextu's in the m68k assembly output did not encourage me...
157  * as well, gcc on the sparc definitely generates much better
158  * code with `?:'.
159  */
160 
161 static void
stios2btios(struct sunos_termios * st,struct termios * bt)162 stios2btios(struct sunos_termios *st, struct termios *bt)
163 {
164           netbsd32_u_long l, r;
165 
166           memset(bt, 0, sizeof(*bt));
167 
168           l = st->c_iflag;
169           r =       ((l & 0x00000001) ? IGNBRK    : 0);
170           r |=      ((l & 0x00000002) ? BRKINT    : 0);
171           r |=      ((l & 0x00000004) ? IGNPAR    : 0);
172           r |=      ((l & 0x00000008) ? PARMRK    : 0);
173           r |=      ((l & 0x00000010) ? INPCK     : 0);
174           r |=      ((l & 0x00000020) ? ISTRIP    : 0);
175           r |=      ((l & 0x00000040) ? INLCR     : 0);
176           r |=      ((l & 0x00000080) ? IGNCR     : 0);
177           r |=      ((l & 0x00000100) ? ICRNL     : 0);
178           /*        ((l & 0x00000200) ? IUCLC     : 0) */
179           r |=      ((l & 0x00000400) ? IXON      : 0);
180           r |=      ((l & 0x00000800) ? IXANY     : 0);
181           r |=      ((l & 0x00001000) ? IXOFF     : 0);
182           r |=      ((l & 0x00002000) ? IMAXBEL   : 0);
183           bt->c_iflag = r;
184 
185           l = st->c_oflag;
186           r =       ((l & 0x00000001) ? OPOST     : 0);
187           /*        ((l & 0x00000002) ? OLCUC     : 0) */
188           r |=      ((l & 0x00000004) ? ONLCR     : 0);
189           /*        ((l & 0x00000008) ? OCRNL     : 0) */
190           /*        ((l & 0x00000010) ? ONOCR     : 0) */
191           /*        ((l & 0x00000020) ? ONLRET    : 0) */
192           /*        ((l & 0x00000040) ? OFILL     : 0) */
193           /*        ((l & 0x00000080) ? OFDEL     : 0) */
194           /*        ((l & 0x00000100) ? NLDLY     : 0) */
195           /*        ((l & 0x00000100) ? NL1                 : 0) */
196           /*        ((l & 0x00000600) ? CRDLY     : 0) */
197           /*        ((l & 0x00000200) ? CR1                 : 0) */
198           /*        ((l & 0x00000400) ? CR2                 : 0) */
199           /*        ((l & 0x00000600) ? CR3                 : 0) */
200           /*        ((l & 0x00001800) ? TABDLY    : 0) */
201           /*        ((l & 0x00000800) ? TAB1      : 0) */
202           /*        ((l & 0x00001000) ? TAB2      : 0) */
203           r |=      ((l & 0x00001800) ? OXTABS    : 0);
204           /*        ((l & 0x00002000) ? BSDLY     : 0) */
205           /*        ((l & 0x00002000) ? BS1                 : 0) */
206           /*        ((l & 0x00004000) ? VTDLY     : 0) */
207           /*        ((l & 0x00004000) ? VT1                 : 0) */
208           /*        ((l & 0x00008000) ? FFDLY     : 0) */
209           /*        ((l & 0x00008000) ? FF1                 : 0) */
210           /*        ((l & 0x00010000) ? PAGEOUT   : 0) */
211           /*        ((l & 0x00020000) ? WRAP      : 0) */
212           bt->c_oflag = r;
213 
214           l = st->c_cflag;
215           switch (l & 0x00000030) {
216           case 0:
217                     r = CS5;
218                     break;
219           case 0x00000010:
220                     r = CS6;
221                     break;
222           case 0x00000020:
223                     r = CS7;
224                     break;
225           case 0x00000030:
226                     r = CS8;
227                     break;
228           }
229           r |=      ((l & 0x00000040) ? CSTOPB    : 0);
230           r |=      ((l & 0x00000080) ? CREAD     : 0);
231           r |=      ((l & 0x00000100) ? PARENB    : 0);
232           r |=      ((l & 0x00000200) ? PARODD    : 0);
233           r |=      ((l & 0x00000400) ? HUPCL     : 0);
234           r |=      ((l & 0x00000800) ? CLOCAL    : 0);
235           /*        ((l & 0x00001000) ? LOBLK     : 0) */
236           r |=      ((l & 0x80000000) ? (CRTS_IFLOW|CCTS_OFLOW) : 0);
237           bt->c_cflag = r;
238 
239           bt->c_ispeed = bt->c_ospeed = s2btab[l & 0x0000000f];
240 
241           l = st->c_lflag;
242           r =       ((l & 0x00000001) ? ISIG      : 0);
243           r |=      ((l & 0x00000002) ? ICANON    : 0);
244           /*        ((l & 0x00000004) ? XCASE     : 0) */
245           r |=      ((l & 0x00000008) ? ECHO      : 0);
246           r |=      ((l & 0x00000010) ? ECHOE     : 0);
247           r |=      ((l & 0x00000020) ? ECHOK     : 0);
248           r |=      ((l & 0x00000040) ? ECHONL    : 0);
249           r |=      ((l & 0x00000080) ? NOFLSH    : 0);
250           r |=      ((l & 0x00000100) ? TOSTOP    : 0);
251           r |=      ((l & 0x00000200) ? ECHOCTL   : 0);
252           r |=      ((l & 0x00000400) ? ECHOPRT   : 0);
253           r |=      ((l & 0x00000800) ? ECHOKE    : 0);
254           /*        ((l & 0x00001000) ? DEFECHO   : 0) */
255           r |=      ((l & 0x00002000) ? FLUSHO    : 0);
256           r |=      ((l & 0x00004000) ? PENDIN    : 0);
257           bt->c_lflag = r;
258 
259           bt->c_cc[VINTR]    = st->c_cc[0]  ? st->c_cc[0]  : _POSIX_VDISABLE;
260           bt->c_cc[VQUIT]    = st->c_cc[1]  ? st->c_cc[1]  : _POSIX_VDISABLE;
261           bt->c_cc[VERASE]   = st->c_cc[2]  ? st->c_cc[2]  : _POSIX_VDISABLE;
262           bt->c_cc[VKILL]    = st->c_cc[3]  ? st->c_cc[3]  : _POSIX_VDISABLE;
263           bt->c_cc[VEOF]     = st->c_cc[4]  ? st->c_cc[4]  : _POSIX_VDISABLE;
264           bt->c_cc[VEOL]     = st->c_cc[5]  ? st->c_cc[5]  : _POSIX_VDISABLE;
265           bt->c_cc[VEOL2]    = st->c_cc[6]  ? st->c_cc[6]  : _POSIX_VDISABLE;
266     /*    bt->c_cc[VSWTCH]   = st->c_cc[7]  ? st->c_cc[7]  : _POSIX_VDISABLE; */
267           bt->c_cc[VSTART]   = st->c_cc[8]  ? st->c_cc[8]  : _POSIX_VDISABLE;
268           bt->c_cc[VSTOP]    = st->c_cc[9]  ? st->c_cc[9]  : _POSIX_VDISABLE;
269           bt->c_cc[VSUSP]    = st->c_cc[10] ? st->c_cc[10] : _POSIX_VDISABLE;
270           bt->c_cc[VDSUSP]   = st->c_cc[11] ? st->c_cc[11] : _POSIX_VDISABLE;
271           bt->c_cc[VREPRINT] = st->c_cc[12] ? st->c_cc[12] : _POSIX_VDISABLE;
272           bt->c_cc[VDISCARD] = st->c_cc[13] ? st->c_cc[13] : _POSIX_VDISABLE;
273           bt->c_cc[VWERASE]  = st->c_cc[14] ? st->c_cc[14] : _POSIX_VDISABLE;
274           bt->c_cc[VLNEXT]   = st->c_cc[15] ? st->c_cc[15] : _POSIX_VDISABLE;
275           bt->c_cc[VSTATUS]  = st->c_cc[16] ? st->c_cc[16] : _POSIX_VDISABLE;
276 
277           /* if `raw mode', create native VMIN/VTIME from SunOS VEOF/VEOL */
278           bt->c_cc[VMIN]         = (bt->c_lflag & ICANON) ? 1 : bt->c_cc[VEOF];
279           bt->c_cc[VTIME]        = (bt->c_lflag & ICANON) ? 1 : bt->c_cc[VEOL];
280 }
281 
282 
283 static void
btios2stios(struct termios * bt,struct sunos_termios * st)284 btios2stios(struct termios *bt, struct sunos_termios *st)
285 {
286           netbsd32_u_long l, r;
287           int s;
288 
289           memset(st, 0, sizeof(*st));
290 
291           l = bt->c_iflag;
292           r =       ((l &  IGNBRK) ? 0x00000001   : 0);
293           r |=      ((l &  BRKINT) ? 0x00000002   : 0);
294           r |=      ((l &  IGNPAR) ? 0x00000004   : 0);
295           r |=      ((l &  PARMRK) ? 0x00000008   : 0);
296           r |=      ((l &   INPCK) ? 0x00000010   : 0);
297           r |=      ((l &  ISTRIP) ? 0x00000020   : 0);
298           r |=      ((l &   INLCR) ? 0x00000040   : 0);
299           r |=      ((l &   IGNCR) ? 0x00000080   : 0);
300           r |=      ((l &   ICRNL) ? 0x00000100   : 0);
301           /*        ((l &   IUCLC) ? 0x00000200   : 0) */
302           r |=      ((l &    IXON) ? 0x00000400   : 0);
303           r |=      ((l &   IXANY) ? 0x00000800   : 0);
304           r |=      ((l &   IXOFF) ? 0x00001000   : 0);
305           r |=      ((l & IMAXBEL) ? 0x00002000   : 0);
306           st->c_iflag = r;
307 
308           l = bt->c_oflag;
309           r =       ((l &   OPOST) ? 0x00000001   : 0);
310           /*        ((l &   OLCUC) ? 0x00000002   : 0) */
311           r |=      ((l &   ONLCR) ? 0x00000004   : 0);
312           /*        ((l &   OCRNL) ? 0x00000008   : 0) */
313           /*        ((l &   ONOCR) ? 0x00000010   : 0) */
314           /*        ((l &  ONLRET) ? 0x00000020   : 0) */
315           /*        ((l &   OFILL) ? 0x00000040   : 0) */
316           /*        ((l &   OFDEL) ? 0x00000080   : 0) */
317           /*        ((l &   NLDLY) ? 0x00000100   : 0) */
318           /*        ((l &     NL1) ? 0x00000100   : 0) */
319           /*        ((l &   CRDLY) ? 0x00000600   : 0) */
320           /*        ((l &     CR1) ? 0x00000200   : 0) */
321           /*        ((l &     CR2) ? 0x00000400   : 0) */
322           /*        ((l &     CR3) ? 0x00000600   : 0) */
323           /*        ((l &  TABDLY) ? 0x00001800   : 0) */
324           /*        ((l &    TAB1) ? 0x00000800   : 0) */
325           /*        ((l &    TAB2) ? 0x00001000   : 0) */
326           r |=      ((l &  OXTABS) ? 0x00001800   : 0);
327           /*        ((l &   BSDLY) ? 0x00002000   : 0) */
328           /*        ((l &     BS1) ? 0x00002000   : 0) */
329           /*        ((l &   VTDLY) ? 0x00004000   : 0) */
330           /*        ((l &     VT1) ? 0x00004000   : 0) */
331           /*        ((l &   FFDLY) ? 0x00008000   : 0) */
332           /*        ((l &     FF1) ? 0x00008000   : 0) */
333           /*        ((l & PAGEOUT) ? 0x00010000   : 0) */
334           /*        ((l &    WRAP) ? 0x00020000   : 0) */
335           st->c_oflag = r;
336 
337           l = bt->c_cflag;
338           switch (l & CSIZE) {
339           case CS5:
340                     r = 0;
341                     break;
342           case CS6:
343                     r = 0x00000010;
344                     break;
345           case CS7:
346                     r = 0x00000020;
347                     break;
348           case CS8:
349                     r = 0x00000030;
350                     break;
351           }
352           r |=      ((l &  CSTOPB) ? 0x00000040   : 0);
353           r |=      ((l &   CREAD) ? 0x00000080   : 0);
354           r |=      ((l &  PARENB) ? 0x00000100   : 0);
355           r |=      ((l &  PARODD) ? 0x00000200   : 0);
356           r |=      ((l &   HUPCL) ? 0x00000400   : 0);
357           r |=      ((l &  CLOCAL) ? 0x00000800   : 0);
358           /*        ((l &   LOBLK) ? 0x00001000   : 0) */
359           r |=      ((l & (CRTS_IFLOW|CCTS_OFLOW)) ? 0x80000000 : 0);
360           st->c_cflag = r;
361 
362           l = bt->c_lflag;
363           r =       ((l &    ISIG) ? 0x00000001   : 0);
364           r |=      ((l &  ICANON) ? 0x00000002   : 0);
365           /*        ((l &   XCASE) ? 0x00000004   : 0) */
366           r |=      ((l &    ECHO) ? 0x00000008   : 0);
367           r |=      ((l &   ECHOE) ? 0x00000010   : 0);
368           r |=      ((l &   ECHOK) ? 0x00000020   : 0);
369           r |=      ((l &  ECHONL) ? 0x00000040   : 0);
370           r |=      ((l &  NOFLSH) ? 0x00000080   : 0);
371           r |=      ((l &  TOSTOP) ? 0x00000100   : 0);
372           r |=      ((l & ECHOCTL) ? 0x00000200   : 0);
373           r |=      ((l & ECHOPRT) ? 0x00000400   : 0);
374           r |=      ((l &  ECHOKE) ? 0x00000800   : 0);
375           /*        ((l & DEFECHO) ? 0x00001000   : 0) */
376           r |=      ((l &  FLUSHO) ? 0x00002000   : 0);
377           r |=      ((l &  PENDIN) ? 0x00004000   : 0);
378           st->c_lflag = r;
379 
380           s = ttspeedtab(bt->c_ospeed, sptab);
381           if (s >= 0)
382                     st->c_cflag |= s;
383 
384           st->c_cc[0] = bt->c_cc[VINTR]   != _POSIX_VDISABLE? bt->c_cc[VINTR]:0;
385           st->c_cc[1] = bt->c_cc[VQUIT]   != _POSIX_VDISABLE? bt->c_cc[VQUIT]:0;
386           st->c_cc[2] = bt->c_cc[VERASE]  != _POSIX_VDISABLE? bt->c_cc[VERASE]:0;
387           st->c_cc[3] = bt->c_cc[VKILL]   != _POSIX_VDISABLE? bt->c_cc[VKILL]:0;
388           st->c_cc[4] = bt->c_cc[VEOF]    != _POSIX_VDISABLE? bt->c_cc[VEOF]:0;
389           st->c_cc[5] = bt->c_cc[VEOL]    != _POSIX_VDISABLE? bt->c_cc[VEOL]:0;
390           st->c_cc[6] = bt->c_cc[VEOL2]   != _POSIX_VDISABLE? bt->c_cc[VEOL2]:0;
391           st->c_cc[7] = 0;
392                     /*    bt->c_cc[VSWTCH]  != _POSIX_VDISABLE? bt->c_cc[VSWTCH]: */
393           st->c_cc[8] = bt->c_cc[VSTART]  != _POSIX_VDISABLE? bt->c_cc[VSTART]:0;
394           st->c_cc[9] = bt->c_cc[VSTOP]   != _POSIX_VDISABLE? bt->c_cc[VSTOP]:0;
395           st->c_cc[10]= bt->c_cc[VSUSP]   != _POSIX_VDISABLE? bt->c_cc[VSUSP]:0;
396           st->c_cc[11]= bt->c_cc[VDSUSP]  != _POSIX_VDISABLE? bt->c_cc[VDSUSP]:0;
397           st->c_cc[12]= bt->c_cc[VREPRINT]!= _POSIX_VDISABLE? bt->c_cc[VREPRINT]:0;
398           st->c_cc[13]= bt->c_cc[VDISCARD]!= _POSIX_VDISABLE? bt->c_cc[VDISCARD]:0;
399           st->c_cc[14]= bt->c_cc[VWERASE] != _POSIX_VDISABLE? bt->c_cc[VWERASE]:0;
400           st->c_cc[15]= bt->c_cc[VLNEXT]  != _POSIX_VDISABLE? bt->c_cc[VLNEXT]:0;
401           st->c_cc[16]= bt->c_cc[VSTATUS] != _POSIX_VDISABLE? bt->c_cc[VSTATUS]:0;
402 
403           if (!(bt->c_lflag & ICANON)) {
404                     /* SunOS stores VMIN/VTIME in VEOF/VEOL (if ICANON is off) */
405                     st->c_cc[4] = bt->c_cc[VMIN];
406                     st->c_cc[5] = bt->c_cc[VTIME];
407           }
408 
409           st->c_line = 0;
410 }
411 
412 static void
stios2stio(struct sunos_termios * ts,struct sunos_termio * t)413 stios2stio(struct sunos_termios *ts, struct sunos_termio *t)
414 {
415 
416           memset(t, 0, sizeof(*t));
417           t->c_iflag = ts->c_iflag;
418           t->c_oflag = ts->c_oflag;
419           t->c_cflag = ts->c_cflag;
420           t->c_lflag = ts->c_lflag;
421           t->c_line  = ts->c_line;
422           memcpy(t->c_cc, ts->c_cc, 8);
423 }
424 
425 static void
stio2stios(struct sunos_termio * t,struct sunos_termios * ts)426 stio2stios(struct sunos_termio *t, struct sunos_termios *ts)
427 {
428 
429           memset(ts, 0, sizeof(*ts));
430           ts->c_iflag = t->c_iflag;
431           ts->c_oflag = t->c_oflag;
432           ts->c_cflag = t->c_cflag;
433           ts->c_lflag = t->c_lflag;
434           ts->c_line  = t->c_line;
435           memcpy(ts->c_cc, t->c_cc, 8); /* don't touch the upper fields! */
436 }
437 
438 
439 static int
sunos32_do_ioctl(int fd,int cmd,void * arg,struct lwp * l)440 sunos32_do_ioctl(int fd, int cmd, void *arg, struct lwp *l)
441 {
442           file_t *fp;
443           struct vnode *vp;
444           int error;
445 
446           if ((error = fd_getvnode(fd, &fp)) != 0)
447                     return error;
448           if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
449                     fd_putfile(fd);
450                     return EBADF;
451           }
452           error = fp->f_ops->fo_ioctl(fp, cmd, arg);
453           if (error == EIO && cmd == TIOCGPGRP) {
454                     vp = fp->f_vnode;
455                     if (vp != NULL && vp->v_type == VCHR && major(vp->v_rdev) == 21)
456                               error = ENOTTY;
457           }
458           fd_putfile(fd);
459           return error;
460 }
461 
462 int
sunos32_sys_ioctl(struct lwp * l,const struct sunos32_sys_ioctl_args * uap,register_t * retval)463 sunos32_sys_ioctl(struct lwp *l, const struct sunos32_sys_ioctl_args *uap,
464     register_t *retval)
465 {
466           /* {
467                     int       fd;
468                     netbsd32_u_long     com;
469                     netbsd32_caddr_t    data;
470           } */
471           struct netbsd32_ioctl_args bsd_ua;
472           int error;
473 
474           SCARG(&bsd_ua, fd) = SCARG(uap, fd);
475           SCARG(&bsd_ua, com) = SCARG(uap, com);
476           SCARG(&bsd_ua, data) = SCARG(uap, data);
477 
478           switch (SCARG(uap, com)) {
479           case _IOR('t', 0, int):
480                     SCARG(&bsd_ua, com) = TIOCGETD;
481                     break;
482           case _IOW('t', 1, int):
483               {
484                     int disc;
485 
486                     if ((error = copyin(SCARG_P32(uap, data), &disc,
487                         sizeof disc)) != 0)
488                               return error;
489 
490                     /* map SunOS NTTYDISC into our termios discipline */
491                     if (disc == 2)
492                               disc = 0;
493                     /* all other disciplines are not supported by NetBSD */
494                     if (disc)
495                               return ENXIO;
496 
497                     return sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCSETD, &disc, l);
498               }
499           case _IOW('t', 101, int):     /* sun SUNOS_TIOCSSOFTCAR */
500               {
501                     int x;    /* unused */
502 
503                     return copyin(SCARG_P32(uap, data), &x, sizeof x);
504               }
505           case _IOR('t', 100, int):     /* sun SUNOS_TIOCSSOFTCAR */
506               {
507                     int x = 0;
508 
509                     return copyout(&x, SCARG_P32(uap, data), sizeof x);
510               }
511           case _IO('t', 36):            /* sun TIOCCONS, no parameters */
512               {
513                     int on = 1;
514                     return sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCCONS, &on, l);
515               }
516           case _IOW('t', 37, struct sunos_ttysize):
517               {
518                     struct winsize ws;
519                     struct sunos_ttysize ss;
520 
521                     error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCGWINSZ, &ws,
522                         l);
523                     if (error != 0)
524                               return error;
525 
526                     error = copyin(SCARG_P32(uap, data), &ss, sizeof(ss));
527                     if (error != 0)
528                               return error;
529 
530                     ws.ws_row = ss.ts_row;
531                     ws.ws_col = ss.ts_col;
532 
533                     return sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCSWINSZ, &ws, l);
534               }
535           case _IOW('t', 38, struct sunos_ttysize):
536               {
537                     struct winsize ws;
538                     struct sunos_ttysize ss;
539 
540                     error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCGWINSZ, &ws,
541                         l);
542                     if (error != 0)
543                               return error;
544 
545                     memset(&ss, 0, sizeof(ss));
546                     ss.ts_row = ws.ws_row;
547                     ss.ts_col = ws.ws_col;
548 
549                     return copyout(&ss, SCARG_P32(uap, data), sizeof(ss));
550               }
551           case _IOW('t', 130, int):     /* TIOCSETPGRP: posix variant */
552                     SCARG(&bsd_ua, com) = TIOCSPGRP;
553                     break;
554           case _IOR('t', 131, int):     /* TIOCGETPGRP: posix variant */
555               {
556                     /*
557                      * sigh, must do error translation on pty devices
558                      * (see also kern/tty_pty.c)
559                      */
560                     int pgrp;
561                     error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCGPGRP, &pgrp,
562                         l);
563                     if (error)
564                               return error;
565                     return copyout(&pgrp, SCARG_P32(uap, data), sizeof(pgrp));
566               }
567           case _IO('t', 132):
568                     SCARG(&bsd_ua, com) = TIOCSCTTY;
569                     break;
570           case SUNOS_TCGETA:
571           case SUNOS_TCGETS:
572               {
573                     struct termios bts;
574                     struct sunos_termios sts;
575                     struct sunos_termio st;
576 
577                     error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCGETA, &bts,
578                         l);
579                     if (error != 0)
580                               return error;
581 
582                     btios2stios (&bts, &sts);
583                     if (SCARG(uap, com) == SUNOS_TCGETA) {
584                               stios2stio (&sts, &st);
585                               return copyout(&st, SCARG_P32(uap, data), sizeof(st));
586                     } else
587                               return copyout(&sts, SCARG_P32(uap, data),
588                                   sizeof(sts));
589                     /*NOTREACHED*/
590               }
591           case SUNOS_TCSETA:
592           case SUNOS_TCSETAW:
593           case SUNOS_TCSETAF:
594               {
595                     struct termios bts;
596                     struct sunos_termios sts;
597                     struct sunos_termio st;
598 
599                     if ((error = copyin(SCARG_P32(uap, data), &st,
600                         sizeof(st))) != 0)
601                               return error;
602 
603                     /* get full BSD termios so we don't lose information */
604                     if ((error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCGETA,
605                         &bts, l)) != 0)
606                               return error;
607 
608                     /*
609                      * convert to sun termios, copy in information from
610                      * termio, and convert back, then set new values.
611                      */
612                     btios2stios(&bts, &sts);
613                     stio2stios(&st, &sts);
614                     stios2btios(&sts, &bts);
615 
616                     return sunos32_do_ioctl(SCARG(&bsd_ua, fd),
617                         SCARG(uap, com) - SUNOS_TCSETA + TIOCSETA, &bts, l);
618               }
619           case SUNOS_TCSETS:
620           case SUNOS_TCSETSW:
621           case SUNOS_TCSETSF:
622               {
623                     struct termios bts;
624                     struct sunos_termios sts;
625 
626                     if ((error = copyin(SCARG_P32(uap, data), &sts,
627                         sizeof(sts))) != 0)
628                               return error;
629                     stios2btios (&sts, &bts);
630                     return sunos32_do_ioctl(SCARG(&bsd_ua, fd),
631                         SCARG(uap, com) - SUNOS_TCSETS + TIOCSETA, &bts, l);
632               }
633 /*
634  * Pseudo-tty ioctl translations.
635  */
636           case _IOW('t', 32, int): {    /* TIOCTCNTL */
637                     int error1, on;
638 
639                     error1 = copyin(SCARG_P32(uap, data), &on, sizeof(on));
640                     if (error1)
641                               return error1;
642                     return sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCUCNTL, &on, l);
643           }
644           case _IOW('t', 33, int): {    /* TIOCSIGNAL */
645                     int error1, sig;
646 
647                     error1 = copyin(SCARG_P32(uap, data), &sig, sizeof(sig));
648                     if (error1)
649                               return error1;
650                     return sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCSIG, &sig, l);
651           }
652 
653 /*
654  * Socket ioctl translations.
655  */
656 #define IFREQ_IN(a) { \
657           struct oifreq ifreq; \
658           error = copyin(SCARG_P32(uap, data), &ifreq, sizeof(ifreq)); \
659           if (error) \
660                     return error; \
661           return sunos32_do_ioctl(SCARG(&bsd_ua, fd), a, &ifreq, l); \
662 }
663 #define IFREQ_INOUT(a) { \
664           struct oifreq ifreq; \
665           error = copyin(SCARG_P32(uap, data), &ifreq, sizeof(ifreq)); \
666           if (error) \
667                     return error; \
668           if ((error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), a, &ifreq, l)) != 0) \
669                     return error; \
670           return copyout(&ifreq, SCARG_P32(uap, data), sizeof(ifreq)); \
671 }
672 
673           case _IOW('i', 12, struct oifreq):
674                     /* SIOCSIFADDR */
675                     break;
676 
677           case _IOWR('i', 13, struct oifreq):
678                     IFREQ_INOUT(OOSIOCGIFADDR);
679 
680           case _IOW('i', 14, struct oifreq):
681                     /* SIOCSIFDSTADDR */
682                     break;
683 
684           case _IOWR('i', 15, struct oifreq):
685                     IFREQ_INOUT(OOSIOCGIFDSTADDR);
686 
687           case _IOW('i', 16, struct oifreq):
688                     /* SIOCSIFFLAGS */
689                     break;
690 
691           case _IOWR('i', 17, struct oifreq):
692                     /* SIOCGIFFLAGS */
693                     break;
694 
695           case _IOW('i', 21, struct oifreq):
696                     IFREQ_IN(SIOCSIFMTU);
697 
698           case _IOWR('i', 22, struct oifreq):
699                     IFREQ_INOUT(SIOCGIFMTU);
700 
701           case _IOWR('i', 23, struct oifreq):
702                     IFREQ_INOUT(SIOCGIFBRDADDR);
703 
704           case _IOW('i', 24, struct oifreq):
705                     IFREQ_IN(SIOCSIFBRDADDR);
706 
707           case _IOWR('i', 25, struct oifreq):
708                     IFREQ_INOUT(OOSIOCGIFNETMASK);
709 
710           case _IOW('i', 26, struct oifreq):
711                     IFREQ_IN(SIOCSIFNETMASK);
712 
713           case _IOWR('i', 27, struct oifreq):
714                     IFREQ_INOUT(SIOCGIFMETRIC);
715 
716           case _IOWR('i', 28, struct oifreq):
717                     IFREQ_IN(SIOCSIFMETRIC);
718 
719           case _IOW('i', 30, struct arpreq):
720                     /* SIOCSARP */
721                     break;
722 
723           case _IOWR('i', 31, struct arpreq):
724                     /* SIOCGARP */
725                     break;
726 
727           case _IOW('i', 32, struct arpreq):
728                     /* SIOCDARP */
729                     break;
730 
731           case _IOW('i', 18, struct oifreq):      /* SIOCSIFMEM */
732           case _IOWR('i', 19, struct oifreq):     /* SIOCGIFMEM */
733           case _IOW('i', 40, struct oifreq):      /* SIOCUPPER */
734           case _IOW('i', 41, struct oifreq):      /* SIOCLOWER */
735           case _IOW('i', 44, struct oifreq):      /* SIOCSETSYNC */
736           case _IOWR('i', 45, struct oifreq):     /* SIOCGETSYNC */
737           case _IOWR('i', 46, struct oifreq):     /* SIOCSDSTATS */
738           case _IOWR('i', 47, struct oifreq):     /* SIOCSESTATS */
739           case _IOW('i', 48, int):                /* SIOCSPROMISC */
740           case _IOW('i', 49, struct oifreq):      /* SIOCADDMULTI */
741           case _IOW('i', 50, struct oifreq):      /* SIOCDELMULTI */
742                     return EOPNOTSUPP;
743 
744           case _IOWR('i', 20, struct oifconf):    /* SIOCGIFCONF */
745               {
746                     struct oifconf ifcf;
747 
748                     /*
749                      * XXX: two more problems
750                      * 1. our sockaddr's are variable length, not always
751                      *    sizeof(sockaddr)
752                      * 2. this returns a name per protocol, ie. it returns two
753                      *    "lo0"'s
754                      */
755                     error = copyin(SCARG_P32(uap, data), &ifcf, sizeof(ifcf));
756                     if (error)
757                               return error;
758                     error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), OOSIOCGIFCONF,
759                         &ifcf, l);
760                     if (error)
761                               return error;
762                     return copyout(&ifcf, SCARG_P32(uap, data), sizeof(ifcf));
763               }
764 
765 /*
766  * Audio ioctl translations.
767  */
768           case _IOR('A', 1, struct sunos_audio_info):       /* AUDIO_GETINFO */
769           sunos_au_getinfo:
770               {
771                     struct audio_info aui;
772                     struct sunos_audio_info sunos_aui;
773 
774                     error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), AUDIO_GETINFO, &aui, l);
775                     if (error)
776                               return error;
777 
778                     memset(&sunos_aui, 0, sizeof(sunos_aui));
779 
780                     sunos_aui.play = *(struct sunos_audio_prinfo *)&aui.play;
781                     sunos_aui.record = *(struct sunos_audio_prinfo *)&aui.record;
782 
783                     /* `avail_ports' is `seek' in BSD */
784                     sunos_aui.play.avail_ports = AUDIO_SPEAKER | AUDIO_HEADPHONE;
785                     sunos_aui.record.avail_ports = AUDIO_SPEAKER | AUDIO_HEADPHONE;
786 
787                     sunos_aui.play.waiting = 0;
788                     sunos_aui.record.waiting = 0;
789                     sunos_aui.play.eof = 0;
790                     sunos_aui.record.eof = 0;
791                     sunos_aui.monitor_gain = 0; /* aui.__spare; XXX */
792                     /*XXXsunos_aui.output_muted = 0;*/
793                     /*XXX*/sunos_aui.reserved[0] = 0;
794                     /*XXX*/sunos_aui.reserved[1] = 0;
795                     /*XXX*/sunos_aui.reserved[2] = 0;
796                     /*XXX*/sunos_aui.reserved[3] = 0;
797 
798                     return copyout(&sunos_aui, SCARG_P32(uap, data),
799                                         sizeof(sunos_aui));
800               }
801 
802           case _IOWR('A', 2, struct sunos_audio_info):      /* AUDIO_SETINFO */
803               {
804                     struct audio_info aui;
805                     struct sunos_audio_info sunos_aui;
806 
807                     error = copyin(SCARG_P32(uap, data), &sunos_aui,
808                         sizeof(sunos_aui));
809                     if (error)
810                               return error;
811 
812                     aui.play = *(struct audio_prinfo *)&sunos_aui.play;
813                     aui.record = *(struct audio_prinfo *)&sunos_aui.record;
814                     /* aui.__spare = sunos_aui.monitor_gain; */
815                     aui.blocksize = ~0;
816                     aui.hiwat = ~0;
817                     aui.lowat = ~0;
818                     /* XXX somebody check this please. - is: aui.backlog = ~0; */
819                     aui.mode = ~0;
820                     /*
821                      * The bsd driver does not distinguish between paused and
822                      * active. (In the sun driver, not active means samples are
823                      * not output at all, but paused means the last streams buffer
824                      * is drained and then output stops.)  If either are 0, then
825                      * when stop output. Otherwise, if either are non-zero,
826                      * we resume.
827                      */
828                     if (sunos_aui.play.pause == 0 || sunos_aui.play.active == 0)
829                               aui.play.pause = 0;
830                     else if (sunos_aui.play.pause != (u_char)~0 ||
831                                sunos_aui.play.active != (u_char)~0)
832                               aui.play.pause = 1;
833                     if (sunos_aui.record.pause == 0 || sunos_aui.record.active == 0)
834                               aui.record.pause = 0;
835                     else if (sunos_aui.record.pause != (u_char)~0 ||
836                                sunos_aui.record.active != (u_char)~0)
837                               aui.record.pause = 1;
838 
839                     error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), AUDIO_SETINFO,
840                         &aui, l);
841                     if (error)
842                               return error;
843                     /* Return new state */
844                     goto sunos_au_getinfo;
845               }
846           case _IO('A', 3):   /* AUDIO_DRAIN */
847                     return sunos32_do_ioctl(SCARG(&bsd_ua, fd), AUDIO_DRAIN, NULL,
848                         l);
849           case _IOR('A', 4, int):       /* AUDIO_GETDEV */
850               {
851                     int devtype = SUNOS_AUDIO_DEV_AMD;
852                     return copyout(&devtype, SCARG_P32(uap, data),
853                         sizeof(devtype));
854               }
855 
856 /*
857  * Selected streams ioctls.
858  */
859 #define SUNOS_S_FLUSHR                  1
860 #define SUNOS_S_FLUSHW                  2
861 #define SUNOS_S_FLUSHRW                 3
862 
863 #define SUNOS_S_INPUT                   1
864 #define SUNOS_S_HIPRI                   2
865 #define SUNOS_S_OUTPUT                  4
866 #define SUNOS_S_MSG           8
867 
868           case _IO('S', 5):   /* I_FLUSH */
869               {
870                     int tmp = 0;
871                     switch ((intptr_t)SCARG_P32(uap, data)) {
872                     case SUNOS_S_FLUSHR:          tmp = FREAD; break;
873                     case SUNOS_S_FLUSHW:          tmp = FWRITE; break;
874                     case SUNOS_S_FLUSHRW:         tmp = FREAD|FWRITE; break;
875                     }
876                 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCFLUSH, &tmp, l);
877               }
878           case _IO('S', 9):   /* I_SETSIG */
879               {
880                     int on = 1;
881                     if (((intptr_t)SCARG_P32(uap, data) &
882                         (SUNOS_S_HIPRI|SUNOS_S_INPUT)) == SUNOS_S_HIPRI)
883                               return EOPNOTSUPP;
884                 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), FIOASYNC, &on, l);
885               }
886           /*
887            * SunOS disk ioctls, taken from arch/sparc/sparc/disksubr.c
888            * (which was from the old sparc/scsi/sun_disklabel.c), and
889            * modified to suite.
890            */
891           case SUN_DKIOCGGEOM:
892             {
893                     struct disklabel dl;
894 
895                     error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), DIOCGDINFO,
896                         &dl, l);
897                     if (error)
898                               return error;
899 
900 #define datageom    ((struct sun_dkgeom *)SCARG_P32(uap, data))
901                     /* XXX can't do memset() on a user address (dsl) */
902                     memset(SCARG_P32(uap, data), 0, sizeof(*datageom));
903 
904                     datageom->sdkc_ncylinders = dl.d_ncylinders;
905                     datageom->sdkc_acylinders = dl.d_acylinders;
906                     datageom->sdkc_ntracks = dl.d_ntracks;
907                     datageom->sdkc_nsectors = dl.d_nsectors;
908                     datageom->sdkc_interleave = dl.d_interleave;
909                     datageom->sdkc_sparespercyl = dl.d_sparespercyl;
910                     datageom->sdkc_rpm = dl.d_rpm;
911                     datageom->sdkc_pcylinders = dl.d_ncylinders + dl.d_acylinders;
912 #undef datageom
913                     break;
914               }
915 
916           case SUN_DKIOCINFO:
917                     /* Homey don't do DKIOCINFO */
918                     /* XXX can't do memset() on a user address (dsl) */
919                     memset(SCARG_P32(uap, data), 0, sizeof(struct sun_dkctlr));
920                     break;
921 
922           case SUN_DKIOCGPART:
923             {
924                     struct partinfo pi;
925                     struct disklabel label;
926                     int fd = SCARG(&bsd_ua, fd);
927 
928                     error = sunos32_do_ioctl(fd, DIOCGPARTINFO, &pi, l);
929                     if (error)
930                               return error;
931                     error = sunos32_do_ioctl(fd, DIOCGDINFO, &label, l);
932                     if (error)
933                               return error;
934 
935                     if (label.d_secpercyl == 0)
936                               return ERANGE;      /* XXX */
937                     if (pi.pi_offset % label.d_secpercyl != 0)
938                               return ERANGE;      /* XXX */
939                     /* XXX can't do direct writes to a user address (dsl) */
940 #define datapart    ((struct sun_dkpart *)SCARG_P32(uap, data))
941                     datapart->sdkp_cyloffset = pi.pi_offset / label.d_secpercyl;
942                     datapart->sdkp_nsectors = pi.pi_size;
943 #undef datapart
944               }
945 
946           }
947           return netbsd32_ioctl(l, &bsd_ua, retval);
948 }
949 
950 /* SunOS fcntl(2) cmds not implemented */
951 #define SUN_F_RGETLK          10
952 #define SUN_F_RSETLK          11
953 #define SUN_F_CNVT  12
954 #define SUN_F_RSETLKW         13
955 
956 /* SunOS flock translation */
957 struct sunos_flock {
958           short     l_type;
959           short     l_whence;
960           netbsd32_long       l_start;
961           netbsd32_long       l_len;
962           short     l_pid;
963           short     l_xxx;
964 };
965 
966 static void bsd_to_sunos_flock(struct flock *, struct sunos_flock *);
967 static void sunos_to_bsd_flock(struct sunos_flock *, struct flock *);
968 
969 #define SUNOS_F_RDLCK         1
970 #define   SUNOS_F_WRLCK       2
971 #define SUNOS_F_UNLCK         3
972 
973 static void
bsd_to_sunos_flock(struct flock * iflp,struct sunos_flock * oflp)974 bsd_to_sunos_flock(struct flock *iflp, struct sunos_flock *oflp)
975 {
976 
977           memset(oflp, 0, sizeof(*oflp));
978 
979           switch (iflp->l_type) {
980           case F_RDLCK:
981                     oflp->l_type = SUNOS_F_RDLCK;
982                     break;
983           case F_WRLCK:
984                     oflp->l_type = SUNOS_F_WRLCK;
985                     break;
986           case F_UNLCK:
987                     oflp->l_type = SUNOS_F_UNLCK;
988                     break;
989           default:
990                     oflp->l_type = -1;
991                     break;
992           }
993 
994           oflp->l_whence = (short)iflp->l_whence;
995           oflp->l_start = (netbsd32_long)iflp->l_start;
996           oflp->l_len = (netbsd32_long)iflp->l_len;
997           oflp->l_pid = (short)iflp->l_pid;
998           oflp->l_xxx = 0;
999 }
1000 
1001 
1002 static void
sunos_to_bsd_flock(struct sunos_flock * iflp,struct flock * oflp)1003 sunos_to_bsd_flock(struct sunos_flock *iflp, struct flock *oflp)
1004 {
1005 
1006           memset(oflp, 0, sizeof(*oflp));
1007 
1008           switch (iflp->l_type) {
1009           case SUNOS_F_RDLCK:
1010                     oflp->l_type = F_RDLCK;
1011                     break;
1012           case SUNOS_F_WRLCK:
1013                     oflp->l_type = F_WRLCK;
1014                     break;
1015           case SUNOS_F_UNLCK:
1016                     oflp->l_type = F_UNLCK;
1017                     break;
1018           default:
1019                     oflp->l_type = -1;
1020                     break;
1021           }
1022 
1023           oflp->l_whence = iflp->l_whence;
1024           oflp->l_start = (off_t) iflp->l_start;
1025           oflp->l_len = (off_t) iflp->l_len;
1026           oflp->l_pid = (pid_t) iflp->l_pid;
1027 
1028 }
1029 static struct {
1030           netbsd32_long       sun_flg;
1031           netbsd32_long       bsd_flg;
1032 } sunfcntl_flgtab[] = {
1033           /* F_[GS]ETFLags that differ: */
1034 #define SUN_FSETBLK 0x0010
1035 #define SUN_SHLOCK  0x0080
1036 #define SUN_EXLOCK  0x0100
1037 #define SUN_FNBIO   0x1000
1038 #define SUN_FSYNC   0x2000
1039 #define SUN_NONBLOCK          0x4000
1040 #define SUN_FNOCTTY 0x8000
1041           { SUN_NONBLOCK, O_NONBLOCK },
1042           { SUN_FNBIO, O_NONBLOCK },
1043           { SUN_SHLOCK, O_SHLOCK },
1044           { SUN_EXLOCK, O_EXLOCK },
1045           { SUN_FSYNC, O_FSYNC },
1046           { SUN_FSETBLK, 0 },
1047           { SUN_FNOCTTY, 0 }
1048 };
1049 
1050 int
sunos32_sys_fcntl(struct lwp * l,const struct sunos32_sys_fcntl_args * uap,register_t * retval)1051 sunos32_sys_fcntl(struct lwp *l, const struct sunos32_sys_fcntl_args *uap,
1052     register_t *retval)
1053 {
1054           /* {
1055                     syscallarg(int) fd;
1056                     syscallarg(int) cmd;
1057                     syscallarg(netbsd32_voidp) arg;
1058           } */
1059           struct sys_fcntl_args bsd_ua;
1060           uintptr_t flg;
1061           int n, ret;
1062 
1063           SCARG(&bsd_ua, fd) = SCARG(uap, fd);
1064           SCARG(&bsd_ua, cmd) = SCARG(uap, cmd);
1065           SCARG(&bsd_ua, arg) = SCARG_P32(uap, arg);
1066 
1067           switch (SCARG(uap, cmd)) {
1068           case F_SETFL:
1069                     flg = (intptr_t)SCARG_P32(uap, arg);
1070                     n = sizeof(sunfcntl_flgtab) / sizeof(sunfcntl_flgtab[0]);
1071                     while (--n >= 0) {
1072                               if (flg & sunfcntl_flgtab[n].sun_flg) {
1073                                         flg &= ~sunfcntl_flgtab[n].sun_flg;
1074                                         flg |= sunfcntl_flgtab[n].bsd_flg;
1075                               }
1076                     }
1077                     SCARG(&bsd_ua, arg) = (void *)flg;
1078                     break;
1079 
1080           case F_GETLK:
1081           case F_SETLK:
1082           case F_SETLKW:
1083                     {
1084                               int error;
1085                               struct sunos_flock  ifl;
1086                               struct flock                  fl;
1087 
1088                               error = copyin(SCARG_P32(uap, arg), &ifl, sizeof ifl);
1089                               if (error)
1090                                         return error;
1091                               sunos_to_bsd_flock(&ifl, &fl);
1092 
1093                               error = do_fcntl_lock(SCARG(uap, fd), SCARG(uap, cmd),
1094                                   &fl);
1095                               if (error || SCARG(uap, cmd) != F_GETLK)
1096                                         return error;
1097 
1098                               bsd_to_sunos_flock(&fl, &ifl);
1099                               return copyout(&ifl, SCARG_P32(uap, arg), sizeof ifl);
1100                     }
1101                     break;
1102           case SUN_F_RGETLK:
1103           case SUN_F_RSETLK:
1104           case SUN_F_CNVT:
1105           case SUN_F_RSETLKW:
1106                     return EOPNOTSUPP;
1107           }
1108 
1109           ret = sys_fcntl(l, &bsd_ua, retval);
1110           if (ret != 0)
1111                     return ret;
1112 
1113           switch (SCARG(uap, cmd)) {
1114           case F_GETFL:
1115                     n = sizeof(sunfcntl_flgtab) / sizeof(sunfcntl_flgtab[0]);
1116                     ret = *retval;
1117                     while (--n >= 0) {
1118                               if (ret & sunfcntl_flgtab[n].bsd_flg) {
1119                                         ret &= ~sunfcntl_flgtab[n].bsd_flg;
1120                                         ret |= sunfcntl_flgtab[n].sun_flg;
1121                               }
1122                     }
1123                     *retval = ret;
1124                     break;
1125           }
1126 
1127           return 0;
1128 }
1129