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