1 /* $NetBSD: ibcs2_ioctl.c,v 1.44 2008/04/30 14:07:13 ad Exp $ */
4 * Copyright (c) 1994, 1995 Scott Bartram
7 * based on compat/sunos/sun_ioctl.c
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission
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.
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: ibcs2_ioctl.c,v 1.44 2008/04/30 14:07:13 ad Exp $");
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/namei.h>
35 #include <sys/dirent.h>
39 #include <sys/filedesc.h>
40 #include <sys/ioctl.h>
41 #include <sys/kernel.h>
44 #include <sys/mount.h>
45 #include <sys/reboot.h>
46 #include <sys/resource.h>
47 #include <sys/resourcevar.h>
48 #include <sys/signal.h>
49 #include <sys/signalvar.h>
50 #include <sys/socket.h>
51 #include <sys/termios.h>
53 #include <sys/times.h>
55 #include <sys/vnode.h>
58 #include <sys/utsname.h>
59 #include <sys/unistd.h>
62 #include <sys/syscallargs.h>
64 #include <compat/ibcs2/ibcs2_types.h>
65 #include <compat/ibcs2/ibcs2_signal.h>
66 #include <compat/ibcs2/ibcs2_socksys.h>
67 #include <compat/ibcs2/ibcs2_stropts.h>
68 #include <compat/ibcs2/ibcs2_syscallargs.h>
69 #include <compat/ibcs2/ibcs2_termios.h>
70 #include <compat/ibcs2/ibcs2_util.h>
76 static const struct speedtab sptab
[] = {
97 static const u_long s2btab
[] = {
116 static void stios2btios(struct ibcs2_termios
*, struct termios
*);
117 static void btios2stios(struct termios
*, struct ibcs2_termios
*);
118 static void stios2stio(struct ibcs2_termios
*, struct ibcs2_termio
*);
119 static void stio2stios(struct ibcs2_termio
*, struct ibcs2_termios
*);
122 stios2btios(struct ibcs2_termios
*st
, struct termios
*bt
)
126 l
= st
->c_iflag
; r
= 0;
127 if (l
& IBCS2_IGNBRK
) r
|= IGNBRK
;
128 if (l
& IBCS2_BRKINT
) r
|= BRKINT
;
129 if (l
& IBCS2_IGNPAR
) r
|= IGNPAR
;
130 if (l
& IBCS2_PARMRK
) r
|= PARMRK
;
131 if (l
& IBCS2_INPCK
) r
|= INPCK
;
132 if (l
& IBCS2_ISTRIP
) r
|= ISTRIP
;
133 if (l
& IBCS2_INLCR
) r
|= INLCR
;
134 if (l
& IBCS2_IGNCR
) r
|= IGNCR
;
135 if (l
& IBCS2_ICRNL
) r
|= ICRNL
;
136 if (l
& IBCS2_IXON
) r
|= IXON
;
137 if (l
& IBCS2_IXANY
) r
|= IXANY
;
138 if (l
& IBCS2_IXOFF
) r
|= IXOFF
;
139 if (l
& IBCS2_IMAXBEL
) r
|= IMAXBEL
;
142 l
= st
->c_oflag
; r
= 0;
143 if (l
& IBCS2_OPOST
) r
|= OPOST
;
144 if (l
& IBCS2_ONLCR
) r
|= ONLCR
;
145 if (l
& IBCS2_TAB3
) r
|= OXTABS
;
148 l
= st
->c_cflag
; r
= 0;
149 switch (l
& IBCS2_CSIZE
) {
150 case IBCS2_CS5
: r
|= CS5
; break;
151 case IBCS2_CS6
: r
|= CS6
; break;
152 case IBCS2_CS7
: r
|= CS7
; break;
153 case IBCS2_CS8
: r
|= CS8
; break;
155 if (l
& IBCS2_CSTOPB
) r
|= CSTOPB
;
156 if (l
& IBCS2_CREAD
) r
|= CREAD
;
157 if (l
& IBCS2_PARENB
) r
|= PARENB
;
158 if (l
& IBCS2_PARODD
) r
|= PARODD
;
159 if (l
& IBCS2_HUPCL
) r
|= HUPCL
;
160 if (l
& IBCS2_CLOCAL
) r
|= CLOCAL
;
162 bt
->c_ispeed
= bt
->c_ospeed
= s2btab
[l
& 0x0f];
164 l
= st
->c_lflag
; r
= 0;
165 if (l
& IBCS2_ISIG
) r
|= ISIG
;
166 if (l
& IBCS2_ICANON
) r
|= ICANON
;
167 if (l
& IBCS2_ECHO
) r
|= ECHO
;
168 if (l
& IBCS2_ECHOE
) r
|= ECHOE
;
169 if (l
& IBCS2_ECHOK
) r
|= ECHOK
;
170 if (l
& IBCS2_ECHONL
) r
|= ECHONL
;
171 if (l
& IBCS2_NOFLSH
) r
|= NOFLSH
;
172 if (l
& IBCS2_TOSTOP
) r
|= TOSTOP
;
176 st
->c_cc
[IBCS2_VINTR
] ? st
->c_cc
[IBCS2_VINTR
] : _POSIX_VDISABLE
;
178 st
->c_cc
[IBCS2_VQUIT
] ? st
->c_cc
[IBCS2_VQUIT
] : _POSIX_VDISABLE
;
180 st
->c_cc
[IBCS2_VERASE
] ? st
->c_cc
[IBCS2_VERASE
] : _POSIX_VDISABLE
;
182 st
->c_cc
[IBCS2_VKILL
] ? st
->c_cc
[IBCS2_VKILL
] : _POSIX_VDISABLE
;
183 if (bt
->c_lflag
& ICANON
) {
185 st
->c_cc
[IBCS2_VEOF
] ? st
->c_cc
[IBCS2_VEOF
] : _POSIX_VDISABLE
;
187 st
->c_cc
[IBCS2_VEOL
] ? st
->c_cc
[IBCS2_VEOL
] : _POSIX_VDISABLE
;
189 bt
->c_cc
[VMIN
] = st
->c_cc
[IBCS2_VMIN
];
190 bt
->c_cc
[VTIME
] = st
->c_cc
[IBCS2_VTIME
];
193 st
->c_cc
[IBCS2_VEOL2
] ? st
->c_cc
[IBCS2_VEOL2
] : _POSIX_VDISABLE
;
196 st
->c_cc
[IBCS2_VSWTCH
] ? st
->c_cc
[IBCS2_VSWTCH
] : _POSIX_VDISABLE
;
199 st
->c_cc
[IBCS2_VSTART
] ? st
->c_cc
[IBCS2_VSTART
] : _POSIX_VDISABLE
;
201 st
->c_cc
[IBCS2_VSTOP
] ? st
->c_cc
[IBCS2_VSTOP
] : _POSIX_VDISABLE
;
203 st
->c_cc
[IBCS2_VSUSP
] ? st
->c_cc
[IBCS2_VSUSP
] : _POSIX_VDISABLE
;
204 bt
->c_cc
[VDSUSP
] = _POSIX_VDISABLE
;
205 bt
->c_cc
[VREPRINT
] = _POSIX_VDISABLE
;
206 bt
->c_cc
[VDISCARD
] = _POSIX_VDISABLE
;
207 bt
->c_cc
[VWERASE
] = _POSIX_VDISABLE
;
208 bt
->c_cc
[VLNEXT
] = _POSIX_VDISABLE
;
209 bt
->c_cc
[VSTATUS
] = _POSIX_VDISABLE
;
213 btios2stios(struct termios
*bt
, struct ibcs2_termios
*st
)
218 l
= bt
->c_iflag
; r
= 0;
219 if (l
& IGNBRK
) r
|= IBCS2_IGNBRK
;
220 if (l
& BRKINT
) r
|= IBCS2_BRKINT
;
221 if (l
& IGNPAR
) r
|= IBCS2_IGNPAR
;
222 if (l
& PARMRK
) r
|= IBCS2_PARMRK
;
223 if (l
& INPCK
) r
|= IBCS2_INPCK
;
224 if (l
& ISTRIP
) r
|= IBCS2_ISTRIP
;
225 if (l
& INLCR
) r
|= IBCS2_INLCR
;
226 if (l
& IGNCR
) r
|= IBCS2_IGNCR
;
227 if (l
& ICRNL
) r
|= IBCS2_ICRNL
;
228 if (l
& IXON
) r
|= IBCS2_IXON
;
229 if (l
& IXANY
) r
|= IBCS2_IXANY
;
230 if (l
& IXOFF
) r
|= IBCS2_IXOFF
;
231 if (l
& IMAXBEL
) r
|= IBCS2_IMAXBEL
;
234 l
= bt
->c_oflag
; r
= 0;
235 if (l
& OPOST
) r
|= IBCS2_OPOST
;
236 if (l
& ONLCR
) r
|= IBCS2_ONLCR
;
237 if (l
& OXTABS
) r
|= IBCS2_TAB3
;
240 l
= bt
->c_cflag
; r
= 0;
242 case CS5
: r
|= IBCS2_CS5
; break;
243 case CS6
: r
|= IBCS2_CS6
; break;
244 case CS7
: r
|= IBCS2_CS7
; break;
245 case CS8
: r
|= IBCS2_CS8
; break;
247 if (l
& CSTOPB
) r
|= IBCS2_CSTOPB
;
248 if (l
& CREAD
) r
|= IBCS2_CREAD
;
249 if (l
& PARENB
) r
|= IBCS2_PARENB
;
250 if (l
& PARODD
) r
|= IBCS2_PARODD
;
251 if (l
& HUPCL
) r
|= IBCS2_HUPCL
;
252 if (l
& CLOCAL
) r
|= IBCS2_CLOCAL
;
255 l
= bt
->c_lflag
; r
= 0;
256 if (l
& ISIG
) r
|= IBCS2_ISIG
;
257 if (l
& ICANON
) r
|= IBCS2_ICANON
;
258 if (l
& ECHO
) r
|= IBCS2_ECHO
;
259 if (l
& ECHOE
) r
|= IBCS2_ECHOE
;
260 if (l
& ECHOK
) r
|= IBCS2_ECHOK
;
261 if (l
& ECHONL
) r
|= IBCS2_ECHONL
;
262 if (l
& NOFLSH
) r
|= IBCS2_NOFLSH
;
263 if (l
& TOSTOP
) r
|= IBCS2_TOSTOP
;
266 i
= ttspeedtab(bt
->c_ospeed
, sptab
);
270 st
->c_cc
[IBCS2_VINTR
] =
271 bt
->c_cc
[VINTR
] != _POSIX_VDISABLE
? bt
->c_cc
[VINTR
] : 0;
272 st
->c_cc
[IBCS2_VQUIT
] =
273 bt
->c_cc
[VQUIT
] != _POSIX_VDISABLE
? bt
->c_cc
[VQUIT
] : 0;
274 st
->c_cc
[IBCS2_VERASE
] =
275 bt
->c_cc
[VERASE
] != _POSIX_VDISABLE
? bt
->c_cc
[VERASE
] : 0;
276 st
->c_cc
[IBCS2_VKILL
] =
277 bt
->c_cc
[VKILL
] != _POSIX_VDISABLE
? bt
->c_cc
[VKILL
] : 0;
278 if (bt
->c_lflag
& ICANON
) {
279 st
->c_cc
[IBCS2_VEOF
] =
280 bt
->c_cc
[VEOF
] != _POSIX_VDISABLE
? bt
->c_cc
[VEOF
] : 0;
281 st
->c_cc
[IBCS2_VEOL
] =
282 bt
->c_cc
[VEOL
] != _POSIX_VDISABLE
? bt
->c_cc
[VEOL
] : 0;
284 st
->c_cc
[IBCS2_VMIN
] = bt
->c_cc
[VMIN
];
285 st
->c_cc
[IBCS2_VTIME
] = bt
->c_cc
[VTIME
];
287 st
->c_cc
[IBCS2_VEOL2
] =
288 bt
->c_cc
[VEOL2
] != _POSIX_VDISABLE
? bt
->c_cc
[VEOL2
] : 0;
289 st
->c_cc
[IBCS2_VSWTCH
] =
291 st
->c_cc
[IBCS2_VSUSP
] =
292 bt
->c_cc
[VSUSP
] != _POSIX_VDISABLE
? bt
->c_cc
[VSUSP
] : 0;
293 st
->c_cc
[IBCS2_VSTART
] =
294 bt
->c_cc
[VSTART
] != _POSIX_VDISABLE
? bt
->c_cc
[VSTART
] : 0;
295 st
->c_cc
[IBCS2_VSTOP
] =
296 bt
->c_cc
[VSTOP
] != _POSIX_VDISABLE
? bt
->c_cc
[VSTOP
] : 0;
302 stios2stio(struct ibcs2_termios
*ts
, struct ibcs2_termio
*t
)
305 t
->c_iflag
= ts
->c_iflag
;
306 t
->c_oflag
= ts
->c_oflag
;
307 t
->c_cflag
= ts
->c_cflag
;
308 t
->c_lflag
= ts
->c_lflag
;
309 t
->c_line
= ts
->c_line
;
310 memcpy(t
->c_cc
, ts
->c_cc
, IBCS2_NCC
);
314 stio2stios(struct ibcs2_termio
*t
, struct ibcs2_termios
*ts
)
317 ts
->c_iflag
= t
->c_iflag
;
318 ts
->c_oflag
= t
->c_oflag
;
319 ts
->c_cflag
= t
->c_cflag
;
320 ts
->c_lflag
= t
->c_lflag
;
321 ts
->c_line
= t
->c_line
;
322 memcpy(ts
->c_cc
, t
->c_cc
, IBCS2_NCC
);
326 ibcs2_sys_ioctl(struct lwp
*l
, const struct ibcs2_sys_ioctl_args
*uap
, register_t
*retval
)
331 syscallarg(void *) data;
333 struct proc
*p
= l
->l_proc
;
335 int (*ctl
)(struct file
*, u_long
, void *);
337 struct ibcs2_termios sts
;
338 struct ibcs2_termio st
;
339 struct sys_ioctl_args bsd_ua
;
342 SCARG(&bsd_ua
, fd
) = SCARG(uap
, fd
);
343 SCARG(&bsd_ua
, data
) = SCARG(uap
, data
);
345 /* Handle the easy ones first */
346 switch ((unsigned long)SCARG(uap
, cmd
)) {
347 case IBCS2_TIOCGWINSZ
:
348 SCARG(&bsd_ua
, com
) = TIOCGWINSZ
;
349 return sys_ioctl(l
, &bsd_ua
, retval
);
351 case IBCS2_TIOCSWINSZ
:
352 SCARG(&bsd_ua
, com
) = TIOCSWINSZ
;
353 return sys_ioctl(l
, &bsd_ua
, retval
);
355 case IBCS2_TIOCGPGRP
:
356 return copyout(&p
->p_pgrp
->pg_id
, SCARG(uap
, data
),
357 sizeof(p
->p_pgrp
->pg_id
));
359 case IBCS2_TIOCSPGRP
: /* XXX - is uap->data a pointer to pgid? */
361 struct sys_setpgid_args sa
;
364 SCARG(&sa
, pgid
) = (int)SCARG(uap
, data
);
365 if ((error
= sys_setpgid(l
, &sa
, retval
)) != 0)
370 case IBCS2_TCGETSC
: /* SCO console - get scancode flags */
371 case IBCS2_TCSETSC
: /* SCO console - set scancode flags */
374 case IBCS2_SIOCSOCKSYS
:
375 return ibcs2_socksys(l
, (const void *)uap
, retval
);
377 case IBCS2_I_NREAD
: /* STREAMS */
378 SCARG(&bsd_ua
, com
) = FIONREAD
;
379 return sys_ioctl(l
, &bsd_ua
, retval
);
384 if ((fp
= fd_getfile(SCARG(uap
, fd
))) == NULL
) {
385 DPRINTF(("ibcs2_ioctl(%d): bad fd %d ", p
->p_pid
,
390 if ((fp
->f_flag
& (FREAD
|FWRITE
)) == 0) {
391 DPRINTF(("ibcs2_ioctl(%d): bad fp flag ", p
->p_pid
));
396 ctl
= fp
->f_ops
->fo_ioctl
;
398 switch ((unsigned long)SCARG(uap
, cmd
)) {
402 if ((error
= (*ctl
)(fp
, TIOCGETA
, &bts
)) != 0)
405 btios2stios(&bts
, &sts
);
406 if (SCARG(uap
, cmd
) == IBCS2_TCGETA
) {
407 stios2stio(&sts
, &st
);
408 error
= copyout(&st
, SCARG(uap
, data
), sizeof(st
));
410 DPRINTF(("ibcs2_ioctl(%d): copyout failed ",
413 error
= copyout(&sts
, SCARG(uap
, data
), sizeof(sts
));
419 if ((error
= copyin(SCARG(uap
, data
), &st
, sizeof(st
))) != 0) {
420 DPRINTF(("ibcs2_ioctl(%d): TCSET copyin failed ",
425 /* get full BSD termios so we don't lose information */
426 if ((error
= (*ctl
)(fp
, TIOCGETA
, &bts
)) != 0) {
427 DPRINTF(("ibcs2_ioctl(%d): TCSET ctl failed fd %d ",
428 p
->p_pid
, SCARG(uap
, fd
)));
433 * convert to iBCS2 termios, copy in information from
434 * termio, and convert back, then set new values.
436 btios2stios(&bts
, &sts
);
437 stio2stios(&st
, &sts
);
438 stios2btios(&sts
, &bts
);
440 t
= SCARG(uap
, cmd
) - IBCS2_TCSETA
+ TIOCSETA
;
441 error
= (*ctl
)(fp
, t
, &bts
);
447 if ((error
= copyin(SCARG(uap
, data
), &sts
, sizeof(sts
))) != 0)
450 stios2btios(&sts
, &bts
);
451 t
= SCARG(uap
, cmd
) - IBCS2_XCSETA
+ TIOCSETA
;
452 error
= (*ctl
)(fp
, t
, &bts
);
458 if ((error
= copyin(SCARG(uap
, data
), &sts
, sizeof(sts
))) != 0)
460 stios2btios(&sts
, &bts
);
461 t
= SCARG(uap
, cmd
) - IBCS2_OXCSETA
+ TIOCSETA
;
462 error
= (*ctl
)(fp
, t
, &bts
);
466 t
= (int) SCARG(uap
, data
);
467 t
= (t
? t
: 1) * hz
* 4;
469 if ((error
= (*ctl
)(fp
, TIOCSBRK
, NULL
)) != 0)
471 error
= tsleep(&t
, PZERO
| PCATCH
, "ibcs2_tcsbrk", t
);
472 if (error
== EINTR
|| error
== ERESTART
) {
473 (void)(*ctl
)(fp
, TIOCCBRK
, NULL
);
476 error
= (*ctl
)(fp
, TIOCCBRK
, NULL
);
480 switch ((int)SCARG(uap
, data
)) {
483 DPRINTF(("ibcs2_ioctl(%d): TCXONC ", p
->p_pid
));
487 error
= (*ctl
)(fp
, TIOCSTOP
, NULL
);
490 error
= (*ctl
)(fp
, TIOCSTART
, (void *)1);
499 switch ((int)SCARG(uap
, data
)) {
513 error
= (*ctl
)(fp
, TIOCFLUSH
, &t
);
517 if ((error
= copyin(SCARG(uap
, data
), &t
, sizeof(t
))) != 0)
519 error
= (*ctl
)(fp
, FIONBIO
, (void *)&t
);
523 DPRINTF(("ibcs2_ioctl(%d): unknown cmd 0x%x ",
524 p
->p_pid
, SCARG(uap
, cmd
)));
529 fd_putfile(SCARG(uap
, fd
));
534 ibcs2_sys_gtty(struct lwp
*l
, const struct ibcs2_sys_gtty_args
*uap
, register_t
*retval
)
538 syscallarg(struct sgttyb *) tb;
542 struct ibcs2_sgttyb itb
;
545 if ((fp
= fd_getfile(SCARG(uap
, fd
))) == NULL
) {
546 DPRINTF(("ibcs2_sys_gtty(%d): bad fd %d ", curproc
->p_pid
,
550 if ((fp
->f_flag
& (FREAD
|FWRITE
)) == 0) {
551 DPRINTF(("ibcs2_sys_gtty(%d): bad fp flag ", curproc
->p_pid
));
556 error
= (*fp
->f_ops
->fo_ioctl
)(fp
, TIOCGETP
, (void *)&tb
);
560 fd_putfile(SCARG(uap
, fd
));
562 itb
.sg_ispeed
= tb
.sg_ispeed
;
563 itb
.sg_ospeed
= tb
.sg_ospeed
;
564 itb
.sg_erase
= tb
.sg_erase
;
565 itb
.sg_kill
= tb
.sg_kill
;
566 itb
.sg_flags
= tb
.sg_flags
& ~(IBCS2_GHUPCL
|IBCS2_GXTABS
);
567 return copyout((void *)&itb
, SCARG(uap
, tb
), sizeof(itb
));
569 fd_putfile(SCARG(uap
, fd
));