1 /* $NetBSD: linux32_termios.c,v 1.11 2008/03/22 01:24:23 bjs Exp $ */ 2 3 /*- 4 * Copyright (c) 1995-2006, 2008 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Frank van der Linden, Eric Haszlakiewicz, and Emmanuel Dreyfus. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <sys/cdefs.h> 40 __KERNEL_RCSID(0, "$NetBSD: linux32_termios.c,v 1.11 2008/03/22 01:24:23 bjs Exp $"); 41 42 #include "opt_compat_linux32.h" 43 44 #include <sys/types.h> 45 #include <sys/param.h> 46 #include <sys/time.h> 47 #include <sys/ucred.h> 48 #include <sys/proc.h> 49 #include <sys/lwp.h> 50 #include <sys/file.h> 51 #include <sys/filedesc.h> 52 #include <sys/fcntl.h> 53 #include <sys/termios.h> 54 55 #include <compat/netbsd32/netbsd32.h> 56 #include <compat/netbsd32/netbsd32_syscallargs.h> 57 58 #include <compat/linux32/common/linux32_types.h> 59 #include <compat/linux32/common/linux32_signal.h> 60 #include <compat/linux32/common/linux32_ioctl.h> 61 #include <compat/linux32/common/linux32_machdep.h> 62 #include <compat/linux32/common/linux32_termios.h> 63 #include <compat/linux32/linux32_syscallargs.h> 64 65 #include <compat/linux/common/linux_types.h> 66 #include <compat/linux/common/linux_signal.h> 67 #include <compat/linux/common/linux_util.h> 68 #include <compat/linux/common/linux_termios.h> 69 #include <compat/linux/linux_syscallargs.h> 70 71 int 72 linux32_ioctl_termios(struct lwp *l, const struct linux32_sys_ioctl_args *uap, register_t *retval) 73 { 74 /* { 75 syscallarg(int) fd; 76 syscallarg(netbsd32_u_long) com; 77 syscallarg(netbsd32_charp) data; 78 } */ 79 file_t *fp; 80 u_long com; 81 struct linux32_termio tmplt; 82 struct linux32_termios tmplts; 83 struct termios tmpbts; 84 int idat; 85 struct netbsd32_ioctl_args ia; 86 int error; 87 char tioclinux; 88 int (*bsdioctl)(file_t *, u_long, void *); 89 90 if ((fp = fd_getfile(SCARG(uap, fd))) == NULL) 91 return (EBADF); 92 93 if ((fp->f_flag & (FREAD | FWRITE)) == 0) { 94 fd_putfile(SCARG(uap, fd)); 95 error = EBADF; 96 goto out; 97 } 98 99 bsdioctl = fp->f_ops->fo_ioctl; 100 com = SCARG(uap, com); 101 retval[0] = 0; 102 103 switch (com) { 104 case LINUX32_TCGETS: 105 error = (*bsdioctl)(fp, TIOCGETA, &tmpbts); 106 if (error) 107 goto out; 108 bsd_termios_to_linux32_termios(&tmpbts, &tmplts); 109 error = copyout(&tmplts, SCARG_P32(uap, data), sizeof tmplts); 110 goto out; 111 case LINUX32_TCSETS: 112 case LINUX32_TCSETSW: 113 case LINUX32_TCSETSF: 114 /* 115 * First fill in all fields, so that we keep the current 116 * values for fields that Linux doesn't know about. 117 */ 118 error = (*bsdioctl)(fp, TIOCGETA, &tmpbts); 119 if (error) 120 goto out; 121 if ((error = copyin(SCARG_P32(uap, data), 122 &tmplts, sizeof tmplts)) != 0) 123 goto out; 124 linux32_termios_to_bsd_termios(&tmplts, &tmpbts); 125 switch (com) { 126 case LINUX32_TCSETS: 127 com = TIOCSETA; 128 break; 129 case LINUX32_TCSETSW: 130 com = TIOCSETAW; 131 break; 132 case LINUX32_TCSETSF: 133 com = TIOCSETAF; 134 break; 135 } 136 error = (*bsdioctl)(fp, com, &tmpbts); 137 goto out; 138 case LINUX32_TCGETA: 139 error = (*bsdioctl)(fp, TIOCGETA, &tmpbts); 140 if (error) 141 goto out; 142 bsd_termios_to_linux32_termio(&tmpbts, &tmplt); 143 error = copyout(&tmplt, SCARG_P32(uap, data), sizeof tmplt); 144 goto out; 145 case LINUX32_TCSETA: 146 case LINUX32_TCSETAW: 147 case LINUX32_TCSETAF: 148 /* 149 * First fill in all fields, so that we keep the current 150 * values for fields that Linux doesn't know about. 151 */ 152 error = (*bsdioctl)(fp, TIOCGETA, &tmpbts); 153 if (error) 154 goto out; 155 if ((error = copyin(SCARG_P32(uap, data), 156 &tmplt, sizeof tmplt)) != 0) 157 goto out; 158 linux32_termio_to_bsd_termios(&tmplt, &tmpbts); 159 switch (com) { 160 case LINUX32_TCSETA: 161 com = TIOCSETA; 162 break; 163 case LINUX32_TCSETAW: 164 com = TIOCSETAW; 165 break; 166 case LINUX32_TCSETAF: 167 com = TIOCSETAF; 168 break; 169 } 170 error = (*bsdioctl)(fp, com, &tmpbts); 171 goto out; 172 case LINUX32_TCFLSH: 173 switch((u_long)SCARG_P32(uap, data)) { 174 case 0: 175 idat = FREAD; 176 break; 177 case 1: 178 idat = FWRITE; 179 break; 180 case 2: 181 idat = 0; 182 break; 183 default: 184 error = EINVAL; 185 goto out; 186 } 187 error = (*bsdioctl)(fp, TIOCFLUSH, &idat); 188 goto out; 189 case LINUX32_TIOCGETD: 190 error = (*bsdioctl)(fp, TIOCGETD, &idat); 191 if (error) 192 goto out; 193 switch (idat) { 194 case TTYDISC: 195 idat = LINUX_N_TTY; 196 break; 197 case SLIPDISC: 198 idat = LINUX_N_SLIP; 199 break; 200 case PPPDISC: 201 idat = LINUX_N_PPP; 202 break; 203 case STRIPDISC: 204 idat = LINUX_N_STRIP; 205 break; 206 /* 207 * Linux does not have the tablet line discipline. 208 */ 209 case TABLDISC: 210 default: 211 idat = -1; /* XXX What should this be? */ 212 break; 213 } 214 error = copyout(&idat, SCARG_P32(uap, data), sizeof idat); 215 goto out; 216 case LINUX32_TIOCSETD: 217 if ((error = copyin(SCARG_P32(uap, data), 218 &idat, sizeof idat)) != 0) 219 goto out; 220 switch (idat) { 221 case LINUX_N_TTY: 222 idat = TTYDISC; 223 break; 224 case LINUX_N_SLIP: 225 idat = SLIPDISC; 226 break; 227 case LINUX_N_PPP: 228 idat = PPPDISC; 229 break; 230 case LINUX_N_STRIP: 231 idat = STRIPDISC; 232 break; 233 /* 234 * We can't handle the mouse line discipline Linux has. 235 */ 236 case LINUX_N_MOUSE: 237 case LINUX_N_AX25: 238 case LINUX_N_X25: 239 case LINUX_N_6PACK: 240 default: 241 error = EINVAL; 242 goto out; 243 } 244 error = (*bsdioctl)(fp, TIOCSETD, &idat); 245 goto out; 246 case LINUX32_TIOCLINUX: 247 if ((error = copyin(SCARG_P32(uap, data), 248 &tioclinux, sizeof tioclinux)) != 0) 249 goto out; 250 switch (tioclinux) { 251 case LINUX_TIOCLINUX_KERNMSG: 252 /* 253 * XXX needed to not fail for some things. Could 254 * try to use TIOCCONS, but the char argument 255 * specifies the VT #, not an fd. 256 */ 257 error = 0; 258 goto out; 259 case LINUX_TIOCLINUX_COPY: 260 case LINUX_TIOCLINUX_PASTE: 261 case LINUX_TIOCLINUX_UNBLANK: 262 case LINUX_TIOCLINUX_LOADLUT: 263 case LINUX_TIOCLINUX_READSHIFT: 264 case LINUX_TIOCLINUX_READMOUSE: 265 case LINUX_TIOCLINUX_VESABLANK: 266 case LINUX_TIOCLINUX_CURCONS: /* could use VT_GETACTIVE */ 267 error = EINVAL; 268 goto out; 269 } 270 break; 271 case LINUX32_TIOCGWINSZ: 272 SCARG(&ia, com) = TIOCGWINSZ; 273 break; 274 case LINUX32_TIOCSWINSZ: 275 SCARG(&ia, com) = TIOCSWINSZ; 276 break; 277 case LINUX32_TIOCGPGRP: 278 SCARG(&ia, com) = TIOCGPGRP; 279 break; 280 case LINUX32_TIOCSPGRP: 281 SCARG(&ia, com) = TIOCSPGRP; 282 break; 283 case LINUX32_FIONREAD: 284 SCARG(&ia, com) = FIONREAD; 285 break; 286 case LINUX32_FIONBIO: 287 SCARG(&ia, com) = FIONBIO; 288 break; 289 case LINUX32_FIOASYNC: 290 SCARG(&ia, com) = FIOASYNC; 291 break; 292 case LINUX32_TIOCEXCL: 293 SCARG(&ia, com) = TIOCEXCL; 294 break; 295 case LINUX32_TIOCNXCL: 296 SCARG(&ia, com) = TIOCNXCL; 297 break; 298 case LINUX32_TIOCCONS: 299 SCARG(&ia, com) = TIOCCONS; 300 break; 301 case LINUX32_TIOCNOTTY: 302 SCARG(&ia, com) = TIOCNOTTY; 303 break; 304 case LINUX32_TCSBRK: 305 SCARG(&ia, com) = SCARG_P32(uap, data) ? TIOCDRAIN : TIOCSBRK; 306 break; 307 case LINUX32_TIOCMGET: 308 SCARG(&ia, com) = TIOCMGET; 309 break; 310 case LINUX32_TIOCMSET: 311 SCARG(&ia, com) = TIOCMSET; 312 break; 313 case LINUX32_TIOCMBIC: 314 SCARG(&ia, com) = TIOCMBIC; 315 break; 316 case LINUX32_TIOCMBIS: 317 SCARG(&ia, com) = TIOCMBIS; 318 break; 319 #ifdef LINUX32_TIOCGPTN 320 case LINUX32_TIOCGPTN: 321 #ifndef NO_DEV_PTM 322 { 323 struct ptmget ptm; 324 325 error = (*bsdioctl)(fp, TIOCPTSNAME, &ptm); 326 if (error != 0) 327 goto out; 328 329 error = copyout(&ptm.sfd, SCARG_P32(uap, data), 330 sizeof(ptm.sfd)); 331 goto out; 332 } 333 #endif /* NO_DEV_PTM */ 334 #endif /* LINUX32_TIOCGPTN */ 335 default: 336 error = EINVAL; 337 goto out; 338 } 339 340 SCARG(&ia, fd) = SCARG(uap, fd); 341 SCARG(&ia, data) = SCARG(uap, data); 342 error = netbsd32_ioctl(curlwp, &ia, retval); 343 out: 344 fd_putfile(SCARG(uap, fd)); 345 return error; 346 } 347