1 /* $NetBSD: tty_43.c,v 1.20 2005/12/11 12:19:56 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.20 2005/12/11 12:19:56 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 /* Macros to clear/set/test flags. */ 88 #define SET(t, f) (t) |= (f) 89 #define CLR(t, f) (t) &= ~(f) 90 #define ISSET(t, f) ((t) & (f)) 91 92 int ttcompatgetflags __P((struct tty *)); 93 void ttcompatsetflags __P((struct tty *, struct termios *)); 94 void ttcompatsetlflags __P((struct tty *, struct termios *)); 95 96 /*ARGSUSED*/ 97 int 98 ttcompat(tp, com, data, flag, l) 99 struct tty *tp; 100 u_long com; 101 caddr_t data; 102 int flag; 103 struct lwp *l; 104 { 105 106 switch (com) { 107 case TIOCGETP: { 108 struct sgttyb *sg = (struct sgttyb *)data; 109 u_char *cc = tp->t_cc; 110 int speed; 111 112 speed = ttspeedtab(tp->t_ospeed, compatspeeds); 113 sg->sg_ospeed = (speed == -1) ? MAX_SPEED : speed; 114 if (tp->t_ispeed == 0) 115 sg->sg_ispeed = sg->sg_ospeed; 116 else { 117 speed = ttspeedtab(tp->t_ispeed, compatspeeds); 118 sg->sg_ispeed = (speed == -1) ? MAX_SPEED : speed; 119 } 120 sg->sg_erase = cc[VERASE]; 121 sg->sg_kill = cc[VKILL]; 122 sg->sg_flags = ttcompatgetflags(tp); 123 break; 124 } 125 126 case TIOCSETP: 127 case TIOCSETN: { 128 struct sgttyb *sg = (struct sgttyb *)data; 129 struct termios term; 130 int speed; 131 132 term = tp->t_termios; 133 if ((speed = sg->sg_ispeed) > MAX_SPEED || speed < 0) 134 term.c_ispeed = speed; 135 else 136 term.c_ispeed = compatspcodes[speed]; 137 if ((speed = sg->sg_ospeed) > MAX_SPEED || speed < 0) 138 term.c_ospeed = speed; 139 else 140 term.c_ospeed = compatspcodes[speed]; 141 term.c_cc[VERASE] = sg->sg_erase; 142 term.c_cc[VKILL] = sg->sg_kill; 143 tp->t_flags = (ttcompatgetflags(tp)&0xffff0000) | (sg->sg_flags&0xffff); 144 ttcompatsetflags(tp, &term); 145 return (ttioctl(tp, com == TIOCSETP ? TIOCSETAF : TIOCSETA, 146 (caddr_t)&term, flag, l)); 147 } 148 149 case TIOCGETC: { 150 struct tchars *tc = (struct tchars *)data; 151 u_char *cc = tp->t_cc; 152 153 tc->t_intrc = cc[VINTR]; 154 tc->t_quitc = cc[VQUIT]; 155 tc->t_startc = cc[VSTART]; 156 tc->t_stopc = cc[VSTOP]; 157 tc->t_eofc = cc[VEOF]; 158 tc->t_brkc = cc[VEOL]; 159 break; 160 } 161 case TIOCSETC: { 162 struct tchars *tc = (struct tchars *)data; 163 u_char *cc = tp->t_cc; 164 165 cc[VINTR] = tc->t_intrc; 166 cc[VQUIT] = tc->t_quitc; 167 cc[VSTART] = tc->t_startc; 168 cc[VSTOP] = tc->t_stopc; 169 cc[VEOF] = tc->t_eofc; 170 cc[VEOL] = tc->t_brkc; 171 if (tc->t_brkc == (char)-1) 172 cc[VEOL2] = _POSIX_VDISABLE; 173 break; 174 } 175 case TIOCSLTC: { 176 struct ltchars *ltc = (struct ltchars *)data; 177 u_char *cc = tp->t_cc; 178 179 cc[VSUSP] = ltc->t_suspc; 180 cc[VDSUSP] = ltc->t_dsuspc; 181 cc[VREPRINT] = ltc->t_rprntc; 182 cc[VDISCARD] = ltc->t_flushc; 183 cc[VWERASE] = ltc->t_werasc; 184 cc[VLNEXT] = ltc->t_lnextc; 185 break; 186 } 187 case TIOCGLTC: { 188 struct ltchars *ltc = (struct ltchars *)data; 189 u_char *cc = tp->t_cc; 190 191 ltc->t_suspc = cc[VSUSP]; 192 ltc->t_dsuspc = cc[VDSUSP]; 193 ltc->t_rprntc = cc[VREPRINT]; 194 ltc->t_flushc = cc[VDISCARD]; 195 ltc->t_werasc = cc[VWERASE]; 196 ltc->t_lnextc = cc[VLNEXT]; 197 break; 198 } 199 case TIOCLBIS: 200 case TIOCLBIC: 201 case TIOCLSET: { 202 struct termios term; 203 int flags; 204 205 term = tp->t_termios; 206 flags = ttcompatgetflags(tp); 207 switch (com) { 208 case TIOCLSET: 209 tp->t_flags = (flags&0xffff) | (*(int *)data<<16); 210 break; 211 case TIOCLBIS: 212 tp->t_flags = flags | (*(int *)data<<16); 213 break; 214 case TIOCLBIC: 215 tp->t_flags = flags & ~(*(int *)data<<16); 216 break; 217 } 218 ttcompatsetlflags(tp, &term); 219 return (ttioctl(tp, TIOCSETA, (caddr_t)&term, flag, l)); 220 } 221 case TIOCLGET: 222 *(int *)data = ttcompatgetflags(tp)>>16; 223 if (ttydebug) 224 printf("CLGET: returning %x\n", *(int *)data); 225 break; 226 227 case OTIOCGETD: 228 *(int *)data = (tp->t_linesw == NULL) ? 229 2 /* XXX old NTTYDISC */ : tp->t_linesw->l_no; 230 break; 231 232 case OTIOCSETD: { 233 int ldisczero = 0; 234 235 return (ttioctl(tp, TIOCSETD, 236 *(int *)data == 2 ? (caddr_t)&ldisczero : data, flag, 237 l)); 238 } 239 240 case OTIOCCONS: 241 *(int *)data = 1; 242 return (ttioctl(tp, TIOCCONS, data, flag, l)); 243 244 case TIOCHPCL: 245 SET(tp->t_cflag, HUPCL); 246 break; 247 248 case TIOCGSID: 249 if (tp->t_session == NULL) 250 return ENOTTY; 251 252 if (tp->t_session->s_leader == NULL) 253 return ENOTTY; 254 255 *(int *) data = tp->t_session->s_leader->p_pid; 256 break; 257 258 default: 259 return (EPASSTHROUGH); 260 } 261 return (0); 262 } 263 264 int 265 ttcompatgetflags(tp) 266 struct tty *tp; 267 { 268 tcflag_t iflag = tp->t_iflag; 269 tcflag_t lflag = tp->t_lflag; 270 tcflag_t oflag = tp->t_oflag; 271 tcflag_t cflag = tp->t_cflag; 272 int flags = 0; 273 274 if (ISSET(iflag, IXOFF)) 275 SET(flags, TANDEM); 276 if (ISSET(iflag, ICRNL) || ISSET(oflag, ONLCR)) 277 SET(flags, CRMOD); 278 if (ISSET(cflag, PARENB)) { 279 if (ISSET(iflag, INPCK)) { 280 if (ISSET(cflag, PARODD)) 281 SET(flags, ODDP); 282 else 283 SET(flags, EVENP); 284 } else 285 SET(flags, ANYP); 286 } 287 288 if (!ISSET(lflag, ICANON)) { 289 /* fudge */ 290 if (ISSET(iflag, IXON) || ISSET(lflag, ISIG|IEXTEN) || 291 ISSET(cflag, PARENB)) 292 SET(flags, CBREAK); 293 else 294 SET(flags, RAW); 295 } 296 297 if (ISSET(flags, RAW)) 298 SET(flags, ISSET(tp->t_flags, LITOUT|PASS8)); 299 else if (ISSET(cflag, CSIZE) == CS8) { 300 if (!ISSET(oflag, OPOST)) 301 SET(flags, LITOUT); 302 if (!ISSET(iflag, ISTRIP)) 303 SET(flags, PASS8); 304 } 305 306 if (ISSET(cflag, MDMBUF)) 307 SET(flags, MDMBUF); 308 if (!ISSET(cflag, HUPCL)) 309 SET(flags, NOHANG); 310 if (ISSET(oflag, OXTABS)) 311 SET(flags, XTABS); 312 if (ISSET(lflag, ECHOE)) 313 SET(flags, CRTERA|CRTBS); 314 if (ISSET(lflag, ECHOKE)) 315 SET(flags, CRTKIL|CRTBS); 316 if (ISSET(lflag, ECHOPRT)) 317 SET(flags, PRTERA); 318 if (ISSET(lflag, ECHOCTL)) 319 SET(flags, CTLECH); 320 if (!ISSET(iflag, IXANY)) 321 SET(flags, DECCTQ); 322 SET(flags, ISSET(lflag, ECHO|TOSTOP|FLUSHO|PENDIN|NOFLSH)); 323 if (ttydebug) 324 printf("getflags: %x\n", flags); 325 return (flags); 326 } 327 328 void 329 ttcompatsetflags(tp, t) 330 struct tty *tp; 331 struct termios *t; 332 { 333 int flags = tp->t_flags; 334 tcflag_t iflag = t->c_iflag; 335 tcflag_t oflag = t->c_oflag; 336 tcflag_t lflag = t->c_lflag; 337 tcflag_t cflag = t->c_cflag; 338 339 if (ISSET(flags, TANDEM)) 340 SET(iflag, IXOFF); 341 else 342 CLR(iflag, IXOFF); 343 if (ISSET(flags, ECHO)) 344 SET(lflag, ECHO); 345 else 346 CLR(lflag, ECHO); 347 if (ISSET(flags, CRMOD)) { 348 SET(iflag, ICRNL); 349 SET(oflag, ONLCR); 350 } else { 351 CLR(iflag, ICRNL); 352 CLR(oflag, ONLCR); 353 } 354 if (ISSET(flags, XTABS)) 355 SET(oflag, OXTABS); 356 else 357 CLR(oflag, OXTABS); 358 359 360 if (ISSET(flags, RAW)) { 361 iflag &= IXOFF; 362 CLR(lflag, ISIG|ICANON|IEXTEN); 363 CLR(cflag, PARENB); 364 } else { 365 SET(iflag, BRKINT|IXON|IMAXBEL); 366 SET(lflag, ISIG|IEXTEN); 367 if (ISSET(flags, CBREAK)) 368 CLR(lflag, ICANON); 369 else 370 SET(lflag, ICANON); 371 switch (ISSET(flags, ANYP)) { 372 case 0: 373 CLR(cflag, PARENB); 374 break; 375 case ANYP: 376 SET(cflag, PARENB); 377 CLR(iflag, INPCK); 378 break; 379 case EVENP: 380 SET(cflag, PARENB); 381 SET(iflag, INPCK); 382 CLR(cflag, PARODD); 383 break; 384 case ODDP: 385 SET(cflag, PARENB); 386 SET(iflag, INPCK); 387 SET(cflag, PARODD); 388 break; 389 } 390 } 391 392 if (ISSET(flags, RAW|LITOUT|PASS8)) { 393 CLR(cflag, CSIZE); 394 SET(cflag, CS8); 395 if (!ISSET(flags, RAW|PASS8)) 396 SET(iflag, ISTRIP); 397 else 398 CLR(iflag, ISTRIP); 399 if (!ISSET(flags, RAW|LITOUT)) 400 SET(oflag, OPOST); 401 else 402 CLR(oflag, OPOST); 403 } else { 404 CLR(cflag, CSIZE); 405 SET(cflag, CS7); 406 SET(iflag, ISTRIP); 407 SET(oflag, OPOST); 408 } 409 410 t->c_iflag = iflag; 411 t->c_oflag = oflag; 412 t->c_lflag = lflag; 413 t->c_cflag = cflag; 414 } 415 416 void 417 ttcompatsetlflags(tp, t) 418 struct tty *tp; 419 struct termios *t; 420 { 421 int flags = tp->t_flags; 422 tcflag_t iflag = t->c_iflag; 423 tcflag_t oflag = t->c_oflag; 424 tcflag_t lflag = t->c_lflag; 425 tcflag_t cflag = t->c_cflag; 426 427 /* Nothing we can do with CRTBS. */ 428 if (ISSET(flags, PRTERA)) 429 SET(lflag, ECHOPRT); 430 else 431 CLR(lflag, ECHOPRT); 432 if (ISSET(flags, CRTERA)) 433 SET(lflag, ECHOE); 434 else 435 CLR(lflag, ECHOE); 436 /* Nothing we can do with TILDE. */ 437 if (ISSET(flags, MDMBUF)) 438 SET(cflag, MDMBUF); 439 else 440 CLR(cflag, MDMBUF); 441 if (ISSET(flags, NOHANG)) 442 CLR(cflag, HUPCL); 443 else 444 SET(cflag, HUPCL); 445 if (ISSET(flags, CRTKIL)) 446 SET(lflag, ECHOKE); 447 else 448 CLR(lflag, ECHOKE); 449 if (ISSET(flags, CTLECH)) 450 SET(lflag, ECHOCTL); 451 else 452 CLR(lflag, ECHOCTL); 453 if (!ISSET(flags, DECCTQ)) 454 SET(iflag, IXANY); 455 else 456 CLR(iflag, IXANY); 457 CLR(lflag, TOSTOP|FLUSHO|PENDIN|NOFLSH); 458 SET(lflag, ISSET(flags, TOSTOP|FLUSHO|PENDIN|NOFLSH)); 459 460 if (ISSET(flags, RAW|LITOUT|PASS8)) { 461 CLR(cflag, CSIZE); 462 SET(cflag, CS8); 463 if (!ISSET(flags, RAW|PASS8)) 464 SET(iflag, ISTRIP); 465 else 466 CLR(iflag, ISTRIP); 467 if (!ISSET(flags, RAW|LITOUT)) 468 SET(oflag, OPOST); 469 else 470 CLR(oflag, OPOST); 471 } else { 472 CLR(cflag, CSIZE); 473 SET(cflag, CS7); 474 SET(iflag, ISTRIP); 475 SET(oflag, OPOST); 476 } 477 478 t->c_iflag = iflag; 479 t->c_oflag = oflag; 480 t->c_lflag = lflag; 481 t->c_cflag = cflag; 482 } 483 484 #endif /* COMPAT_OLDTTY */ 485