1 /* $NetBSD: tty_43.c,v 1.30 2014/05/22 16:31:19 dholland Exp $ */ 2 3 /*- 4 * Copyright (c) 2008 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /*- 30 * Copyright (c) 1982, 1986, 1991, 1993 31 * The Regents of the University of California. All rights reserved. 32 * 33 * Redistribution and use in source and binary forms, with or without 34 * modification, are permitted provided that the following conditions 35 * are met: 36 * 1. Redistributions of source code must retain the above copyright 37 * notice, this list of conditions and the following disclaimer. 38 * 2. Redistributions in binary form must reproduce the above copyright 39 * notice, this list of conditions and the following disclaimer in the 40 * documentation and/or other materials provided with the distribution. 41 * 3. Neither the name of the University nor the names of its contributors 42 * may be used to endorse or promote products derived from this software 43 * without specific prior written permission. 44 * 45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 55 * SUCH DAMAGE. 56 * 57 * @(#)tty_compat.c 8.2 (Berkeley) 1/9/95 58 */ 59 60 /* 61 * mapping routines for old line discipline (yuck) 62 */ 63 64 #include <sys/cdefs.h> 65 __KERNEL_RCSID(0, "$NetBSD: tty_43.c,v 1.30 2014/05/22 16:31:19 dholland Exp $"); 66 67 #include <sys/param.h> 68 #include <sys/systm.h> 69 #include <sys/ioctl.h> 70 #include <sys/proc.h> 71 #include <sys/conf.h> 72 #include <sys/tty.h> 73 #include <sys/termios.h> 74 #include <sys/file.h> 75 #include <sys/kernel.h> 76 #include <sys/syslog.h> 77 #include <sys/ioctl_compat.h> 78 79 int ttydebug = 0; 80 81 static const struct speedtab compatspeeds[] = { 82 #define MAX_SPEED 17 83 { 115200, 17 }, 84 { 57600, 16 }, 85 { 38400, 15 }, 86 { 19200, 14 }, 87 { 9600, 13 }, 88 { 4800, 12 }, 89 { 2400, 11 }, 90 { 1800, 10 }, 91 { 1200, 9 }, 92 { 600, 8 }, 93 { 300, 7 }, 94 { 200, 6 }, 95 { 150, 5 }, 96 { 134, 4 }, 97 { 110, 3 }, 98 { 75, 2 }, 99 { 50, 1 }, 100 { 0, 0 }, 101 { -1, -1 }, 102 }; 103 static const int compatspcodes[] = { 104 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 105 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200 106 }; 107 108 static int ttcompatgetflags(struct tty *); 109 static void ttcompatsetflags(struct tty *, struct termios *); 110 static void ttcompatsetlflags(struct tty *, struct termios *); 111 int ttcompat(struct tty *, u_long, void *, int, struct lwp *); 112 113 /*ARGSUSED*/ 114 int 115 ttcompat(struct tty *tp, u_long com, void *data, int flag, struct lwp *l) 116 { 117 118 switch (com) { 119 case TIOCGETP: { 120 struct sgttyb *sg = (struct sgttyb *)data; 121 int speed; 122 123 mutex_spin_enter(&tty_lock); 124 speed = ttspeedtab(tp->t_ospeed, compatspeeds); 125 sg->sg_ospeed = (speed == -1) ? MAX_SPEED : speed; 126 if (tp->t_ispeed == 0) 127 sg->sg_ispeed = sg->sg_ospeed; 128 else { 129 speed = ttspeedtab(tp->t_ispeed, compatspeeds); 130 sg->sg_ispeed = (speed == -1) ? MAX_SPEED : speed; 131 } 132 sg->sg_erase = tty_getctrlchar(tp, VERASE); 133 sg->sg_kill = tty_getctrlchar(tp, VKILL); 134 sg->sg_flags = ttcompatgetflags(tp); 135 mutex_spin_exit(&tty_lock); 136 break; 137 } 138 139 case TIOCSETP: 140 case TIOCSETN: { 141 struct sgttyb *sg = (struct sgttyb *)data; 142 struct termios term; 143 int speed; 144 145 mutex_spin_enter(&tty_lock); 146 term = tp->t_termios; 147 if ((speed = sg->sg_ispeed) > MAX_SPEED || speed < 0) 148 term.c_ispeed = speed; 149 else 150 term.c_ispeed = compatspcodes[speed]; 151 if ((speed = sg->sg_ospeed) > MAX_SPEED || speed < 0) 152 term.c_ospeed = speed; 153 else 154 term.c_ospeed = compatspcodes[speed]; 155 term.c_cc[VERASE] = sg->sg_erase; 156 term.c_cc[VKILL] = sg->sg_kill; 157 tp->t_flags = (ttcompatgetflags(tp)&0xffff0000) | (sg->sg_flags&0xffff); 158 ttcompatsetflags(tp, &term); 159 mutex_spin_exit(&tty_lock); 160 return (ttioctl(tp, com == TIOCSETP ? TIOCSETAF : TIOCSETA, 161 (void *)&term, flag, l)); 162 } 163 164 case TIOCGETC: { 165 struct tchars *tc = (struct tchars *)data; 166 167 tc->t_intrc = tty_getctrlchar(tp, VINTR); 168 tc->t_quitc = tty_getctrlchar(tp, VQUIT); 169 tc->t_startc = tty_getctrlchar(tp, VSTART); 170 tc->t_stopc = tty_getctrlchar(tp, VSTOP); 171 tc->t_eofc = tty_getctrlchar(tp, VEOF); 172 tc->t_brkc = tty_getctrlchar(tp, VEOL); 173 break; 174 } 175 case TIOCSETC: { 176 struct tchars *tc = (struct tchars *)data; 177 178 tty_setctrlchar(tp, VINTR, tc->t_intrc); 179 tty_setctrlchar(tp, VQUIT, tc->t_quitc); 180 tty_setctrlchar(tp, VSTART, tc->t_startc); 181 tty_setctrlchar(tp, VSTOP, tc->t_stopc); 182 tty_setctrlchar(tp, VEOF, tc->t_eofc); 183 tty_setctrlchar(tp, VEOL, tc->t_brkc); 184 if (tc->t_brkc == (char)-1) 185 tty_setctrlchar(tp, VEOL2, _POSIX_VDISABLE); 186 break; 187 } 188 case TIOCSLTC: { 189 struct ltchars *ltc = (struct ltchars *)data; 190 191 tty_setctrlchar(tp, VSUSP, ltc->t_suspc); 192 tty_setctrlchar(tp, VDSUSP, ltc->t_dsuspc); 193 tty_setctrlchar(tp, VREPRINT, ltc->t_rprntc); 194 tty_setctrlchar(tp, VDISCARD, ltc->t_flushc); 195 tty_setctrlchar(tp, VWERASE, ltc->t_werasc); 196 tty_setctrlchar(tp, VLNEXT, ltc->t_lnextc); 197 break; 198 } 199 case TIOCGLTC: { 200 struct ltchars *ltc = (struct ltchars *)data; 201 202 ltc->t_suspc = tty_getctrlchar(tp, VSUSP); 203 ltc->t_dsuspc = tty_getctrlchar(tp, VDSUSP); 204 ltc->t_rprntc = tty_getctrlchar(tp, VREPRINT); 205 ltc->t_flushc = tty_getctrlchar(tp, VDISCARD); 206 ltc->t_werasc = tty_getctrlchar(tp, VWERASE); 207 ltc->t_lnextc = tty_getctrlchar(tp, VLNEXT); 208 break; 209 } 210 case TIOCLBIS: 211 case TIOCLBIC: 212 case TIOCLSET: { 213 struct termios term; 214 int flags; 215 216 mutex_spin_enter(&tty_lock); 217 term = tp->t_termios; 218 flags = ttcompatgetflags(tp); 219 switch (com) { 220 case TIOCLSET: 221 tp->t_flags = (flags&0xffff) | (*(int *)data<<16); 222 break; 223 case TIOCLBIS: 224 tp->t_flags = flags | (*(int *)data<<16); 225 break; 226 case TIOCLBIC: 227 tp->t_flags = flags & ~(*(int *)data<<16); 228 break; 229 } 230 ttcompatsetlflags(tp, &term); 231 mutex_spin_exit(&tty_lock); 232 return (ttioctl(tp, TIOCSETA, (void *)&term, flag, l)); 233 } 234 case TIOCLGET: 235 mutex_spin_enter(&tty_lock); 236 *(int *)data = ttcompatgetflags(tp)>>16; 237 mutex_spin_exit(&tty_lock); 238 if (ttydebug) 239 printf("CLGET: returning %x\n", *(int *)data); 240 break; 241 242 case OTIOCGETD: 243 mutex_spin_enter(&tty_lock); 244 *(int *)data = (tp->t_linesw == NULL) ? 245 2 /* XXX old NTTYDISC */ : tp->t_linesw->l_no; 246 mutex_spin_exit(&tty_lock); 247 break; 248 249 case OTIOCSETD: { 250 int ldisczero = 0; 251 252 return (ttioctl(tp, TIOCSETD, 253 *(int *)data == 2 ? (void *)&ldisczero : data, flag, 254 l)); 255 } 256 257 case OTIOCCONS: 258 *(int *)data = 1; 259 return (ttioctl(tp, TIOCCONS, data, flag, l)); 260 261 case TIOCHPCL: 262 mutex_spin_enter(&tty_lock); 263 SET(tp->t_cflag, HUPCL); 264 mutex_spin_exit(&tty_lock); 265 break; 266 267 case TIOCGSID: 268 mutex_enter(proc_lock); 269 if (tp->t_session == NULL) { 270 mutex_exit(proc_lock); 271 return ENOTTY; 272 } 273 if (tp->t_session->s_leader == NULL) { 274 mutex_exit(proc_lock); 275 return ENOTTY; 276 } 277 *(int *) data = tp->t_session->s_leader->p_pid; 278 mutex_exit(proc_lock); 279 break; 280 281 default: 282 return (EPASSTHROUGH); 283 } 284 return (0); 285 } 286 287 static int 288 ttcompatgetflags(struct tty *tp) 289 { 290 tcflag_t iflag = tp->t_iflag; 291 tcflag_t lflag = tp->t_lflag; 292 tcflag_t oflag = tp->t_oflag; 293 tcflag_t cflag = tp->t_cflag; 294 int flags = 0; 295 296 KASSERT(mutex_owned(&tty_lock)); 297 298 if (ISSET(iflag, IXOFF)) 299 SET(flags, TANDEM); 300 if (ISSET(iflag, ICRNL) || ISSET(oflag, ONLCR)) 301 SET(flags, CRMOD); 302 if (ISSET(cflag, PARENB)) { 303 if (ISSET(iflag, INPCK)) { 304 if (ISSET(cflag, PARODD)) 305 SET(flags, ODDP); 306 else 307 SET(flags, EVENP); 308 } else 309 SET(flags, ANYP); 310 } 311 312 if (!ISSET(lflag, ICANON)) { 313 /* fudge */ 314 if (ISSET(iflag, IXON) || ISSET(lflag, ISIG|IEXTEN) || 315 ISSET(cflag, PARENB)) 316 SET(flags, CBREAK); 317 else 318 SET(flags, RAW); 319 } 320 321 if (ISSET(flags, RAW)) 322 SET(flags, ISSET(tp->t_flags, LITOUT|PASS8)); 323 else if (ISSET(cflag, CSIZE) == CS8) { 324 if (!ISSET(oflag, OPOST)) 325 SET(flags, LITOUT); 326 if (!ISSET(iflag, ISTRIP)) 327 SET(flags, PASS8); 328 } 329 330 if (ISSET(cflag, MDMBUF)) 331 SET(flags, MDMBUF); 332 if (!ISSET(cflag, HUPCL)) 333 SET(flags, NOHANG); 334 if (ISSET(oflag, OXTABS)) 335 SET(flags, XTABS); 336 if (ISSET(lflag, ECHOE)) 337 SET(flags, CRTERA|CRTBS); 338 if (ISSET(lflag, ECHOKE)) 339 SET(flags, CRTKIL|CRTBS); 340 if (ISSET(lflag, ECHOPRT)) 341 SET(flags, PRTERA); 342 if (ISSET(lflag, ECHOCTL)) 343 SET(flags, CTLECH); 344 if (!ISSET(iflag, IXANY)) 345 SET(flags, DECCTQ); 346 SET(flags, ISSET(lflag, ECHO|TOSTOP|FLUSHO|PENDIN|NOFLSH)); 347 if (ttydebug) 348 printf("getflags: %x\n", flags); 349 return (flags); 350 } 351 352 static void 353 ttcompatsetflags(struct tty *tp, struct termios *t) 354 { 355 int flags = tp->t_flags; 356 357 KASSERT(mutex_owned(&tty_lock)); 358 359 tcflag_t iflag = t->c_iflag; 360 tcflag_t oflag = t->c_oflag; 361 tcflag_t lflag = t->c_lflag; 362 tcflag_t cflag = t->c_cflag; 363 364 if (ISSET(flags, TANDEM)) 365 SET(iflag, IXOFF); 366 else 367 CLR(iflag, IXOFF); 368 if (ISSET(flags, ECHO)) 369 SET(lflag, ECHO); 370 else 371 CLR(lflag, ECHO); 372 if (ISSET(flags, CRMOD)) { 373 SET(iflag, ICRNL); 374 SET(oflag, ONLCR); 375 } else { 376 CLR(iflag, ICRNL); 377 CLR(oflag, ONLCR); 378 } 379 if (ISSET(flags, XTABS)) 380 SET(oflag, OXTABS); 381 else 382 CLR(oflag, OXTABS); 383 384 385 if (ISSET(flags, RAW)) { 386 iflag &= IXOFF; 387 CLR(lflag, ISIG|ICANON|IEXTEN); 388 CLR(cflag, PARENB); 389 } else { 390 SET(iflag, BRKINT|IXON|IMAXBEL); 391 SET(lflag, ISIG|IEXTEN); 392 if (ISSET(flags, CBREAK)) 393 CLR(lflag, ICANON); 394 else 395 SET(lflag, ICANON); 396 switch (ISSET(flags, ANYP)) { 397 case 0: 398 CLR(cflag, PARENB); 399 break; 400 case ANYP: 401 SET(cflag, PARENB); 402 CLR(iflag, INPCK); 403 break; 404 case EVENP: 405 SET(cflag, PARENB); 406 SET(iflag, INPCK); 407 CLR(cflag, PARODD); 408 break; 409 case ODDP: 410 SET(cflag, PARENB); 411 SET(iflag, INPCK); 412 SET(cflag, PARODD); 413 break; 414 } 415 } 416 417 if (ISSET(flags, RAW|LITOUT|PASS8)) { 418 CLR(cflag, CSIZE); 419 SET(cflag, CS8); 420 if (!ISSET(flags, RAW|PASS8)) 421 SET(iflag, ISTRIP); 422 else 423 CLR(iflag, ISTRIP); 424 if (!ISSET(flags, RAW|LITOUT)) 425 SET(oflag, OPOST); 426 else 427 CLR(oflag, OPOST); 428 } else { 429 CLR(cflag, CSIZE); 430 SET(cflag, CS7); 431 SET(iflag, ISTRIP); 432 SET(oflag, OPOST); 433 } 434 435 t->c_iflag = iflag; 436 t->c_oflag = oflag; 437 t->c_lflag = lflag; 438 t->c_cflag = cflag; 439 } 440 441 static void 442 ttcompatsetlflags(struct tty *tp, struct termios *t) 443 { 444 int flags = tp->t_flags; 445 tcflag_t iflag = t->c_iflag; 446 tcflag_t oflag = t->c_oflag; 447 tcflag_t lflag = t->c_lflag; 448 tcflag_t cflag = t->c_cflag; 449 450 KASSERT(mutex_owned(&tty_lock)); 451 452 /* Nothing we can do with CRTBS. */ 453 if (ISSET(flags, PRTERA)) 454 SET(lflag, ECHOPRT); 455 else 456 CLR(lflag, ECHOPRT); 457 if (ISSET(flags, CRTERA)) 458 SET(lflag, ECHOE); 459 else 460 CLR(lflag, ECHOE); 461 /* Nothing we can do with TILDE. */ 462 if (ISSET(flags, MDMBUF)) 463 SET(cflag, MDMBUF); 464 else 465 CLR(cflag, MDMBUF); 466 if (ISSET(flags, NOHANG)) 467 CLR(cflag, HUPCL); 468 else 469 SET(cflag, HUPCL); 470 if (ISSET(flags, CRTKIL)) 471 SET(lflag, ECHOKE); 472 else 473 CLR(lflag, ECHOKE); 474 if (ISSET(flags, CTLECH)) 475 SET(lflag, ECHOCTL); 476 else 477 CLR(lflag, ECHOCTL); 478 if (!ISSET(flags, DECCTQ)) 479 SET(iflag, IXANY); 480 else 481 CLR(iflag, IXANY); 482 CLR(lflag, TOSTOP|FLUSHO|PENDIN|NOFLSH); 483 SET(lflag, ISSET(flags, TOSTOP|FLUSHO|PENDIN|NOFLSH)); 484 485 if (ISSET(flags, RAW|LITOUT|PASS8)) { 486 CLR(cflag, CSIZE); 487 SET(cflag, CS8); 488 if (!ISSET(flags, RAW|PASS8)) 489 SET(iflag, ISTRIP); 490 else 491 CLR(iflag, ISTRIP); 492 if (!ISSET(flags, RAW|LITOUT)) 493 SET(oflag, OPOST); 494 else 495 CLR(oflag, OPOST); 496 } else { 497 CLR(cflag, CSIZE); 498 SET(cflag, CS7); 499 SET(iflag, ISTRIP); 500 SET(oflag, OPOST); 501 } 502 503 t->c_iflag = iflag; 504 t->c_oflag = oflag; 505 t->c_lflag = lflag; 506 t->c_cflag = cflag; 507 } 508