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