1 /* $NetBSD: tty_43.c,v 1.18 2004/04/25 06:23:40 matt 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.18 2004/04/25 06:23:40 matt 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, p) 99 struct tty *tp; 100 u_long com; 101 caddr_t data; 102 int flag; 103 struct proc *p; 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, p)); 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, p)); 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) ? tp->t_linesw->l_no : 2; 229 break; 230 231 case OTIOCSETD: { 232 int ldisczero = 0; 233 234 return (ttioctl(tp, TIOCSETD, 235 *(int *)data == 2 ? (caddr_t)&ldisczero : data, flag, 236 p)); 237 } 238 239 case OTIOCCONS: 240 *(int *)data = 1; 241 return (ttioctl(tp, TIOCCONS, data, flag, p)); 242 243 case TIOCHPCL: 244 SET(tp->t_cflag, HUPCL); 245 break; 246 247 case TIOCGSID: 248 if (tp->t_session == NULL) 249 return ENOTTY; 250 251 if (tp->t_session->s_leader == NULL) 252 return ENOTTY; 253 254 *(int *) data = tp->t_session->s_leader->p_pid; 255 break; 256 257 default: 258 return (EPASSTHROUGH); 259 } 260 return (0); 261 } 262 263 int 264 ttcompatgetflags(tp) 265 struct tty *tp; 266 { 267 tcflag_t iflag = tp->t_iflag; 268 tcflag_t lflag = tp->t_lflag; 269 tcflag_t oflag = tp->t_oflag; 270 tcflag_t cflag = tp->t_cflag; 271 int flags = 0; 272 273 if (ISSET(iflag, IXOFF)) 274 SET(flags, TANDEM); 275 if (ISSET(iflag, ICRNL) || ISSET(oflag, ONLCR)) 276 SET(flags, CRMOD); 277 if (ISSET(cflag, PARENB)) { 278 if (ISSET(iflag, INPCK)) { 279 if (ISSET(cflag, PARODD)) 280 SET(flags, ODDP); 281 else 282 SET(flags, EVENP); 283 } else 284 SET(flags, ANYP); 285 } 286 287 if (!ISSET(lflag, ICANON)) { 288 /* fudge */ 289 if (ISSET(iflag, IXON) || ISSET(lflag, ISIG|IEXTEN) || 290 ISSET(cflag, PARENB)) 291 SET(flags, CBREAK); 292 else 293 SET(flags, RAW); 294 } 295 296 if (ISSET(flags, RAW)) 297 SET(flags, ISSET(tp->t_flags, LITOUT|PASS8)); 298 else if (ISSET(cflag, CSIZE) == CS8) { 299 if (!ISSET(oflag, OPOST)) 300 SET(flags, LITOUT); 301 if (!ISSET(iflag, ISTRIP)) 302 SET(flags, PASS8); 303 } 304 305 if (ISSET(cflag, MDMBUF)) 306 SET(flags, MDMBUF); 307 if (!ISSET(cflag, HUPCL)) 308 SET(flags, NOHANG); 309 if (ISSET(oflag, OXTABS)) 310 SET(flags, XTABS); 311 if (ISSET(lflag, ECHOE)) 312 SET(flags, CRTERA|CRTBS); 313 if (ISSET(lflag, ECHOKE)) 314 SET(flags, CRTKIL|CRTBS); 315 if (ISSET(lflag, ECHOPRT)) 316 SET(flags, PRTERA); 317 if (ISSET(lflag, ECHOCTL)) 318 SET(flags, CTLECH); 319 if (!ISSET(iflag, IXANY)) 320 SET(flags, DECCTQ); 321 SET(flags, ISSET(lflag, ECHO|TOSTOP|FLUSHO|PENDIN|NOFLSH)); 322 if (ttydebug) 323 printf("getflags: %x\n", flags); 324 return (flags); 325 } 326 327 void 328 ttcompatsetflags(tp, t) 329 struct tty *tp; 330 struct termios *t; 331 { 332 int flags = tp->t_flags; 333 tcflag_t iflag = t->c_iflag; 334 tcflag_t oflag = t->c_oflag; 335 tcflag_t lflag = t->c_lflag; 336 tcflag_t cflag = t->c_cflag; 337 338 if (ISSET(flags, TANDEM)) 339 SET(iflag, IXOFF); 340 else 341 CLR(iflag, IXOFF); 342 if (ISSET(flags, ECHO)) 343 SET(lflag, ECHO); 344 else 345 CLR(lflag, ECHO); 346 if (ISSET(flags, CRMOD)) { 347 SET(iflag, ICRNL); 348 SET(oflag, ONLCR); 349 } else { 350 CLR(iflag, ICRNL); 351 CLR(oflag, ONLCR); 352 } 353 if (ISSET(flags, XTABS)) 354 SET(oflag, OXTABS); 355 else 356 CLR(oflag, OXTABS); 357 358 359 if (ISSET(flags, RAW)) { 360 iflag &= IXOFF; 361 CLR(lflag, ISIG|ICANON|IEXTEN); 362 CLR(cflag, PARENB); 363 } else { 364 SET(iflag, BRKINT|IXON|IMAXBEL); 365 SET(lflag, ISIG|IEXTEN); 366 if (ISSET(flags, CBREAK)) 367 CLR(lflag, ICANON); 368 else 369 SET(lflag, ICANON); 370 switch (ISSET(flags, ANYP)) { 371 case 0: 372 CLR(cflag, PARENB); 373 break; 374 case ANYP: 375 SET(cflag, PARENB); 376 CLR(iflag, INPCK); 377 break; 378 case EVENP: 379 SET(cflag, PARENB); 380 SET(iflag, INPCK); 381 CLR(cflag, PARODD); 382 break; 383 case ODDP: 384 SET(cflag, PARENB); 385 SET(iflag, INPCK); 386 SET(cflag, PARODD); 387 break; 388 } 389 } 390 391 if (ISSET(flags, RAW|LITOUT|PASS8)) { 392 CLR(cflag, CSIZE); 393 SET(cflag, CS8); 394 if (!ISSET(flags, RAW|PASS8)) 395 SET(iflag, ISTRIP); 396 else 397 CLR(iflag, ISTRIP); 398 if (!ISSET(flags, RAW|LITOUT)) 399 SET(oflag, OPOST); 400 else 401 CLR(oflag, OPOST); 402 } else { 403 CLR(cflag, CSIZE); 404 SET(cflag, CS7); 405 SET(iflag, ISTRIP); 406 SET(oflag, OPOST); 407 } 408 409 t->c_iflag = iflag; 410 t->c_oflag = oflag; 411 t->c_lflag = lflag; 412 t->c_cflag = cflag; 413 } 414 415 void 416 ttcompatsetlflags(tp, t) 417 struct tty *tp; 418 struct termios *t; 419 { 420 int flags = tp->t_flags; 421 tcflag_t iflag = t->c_iflag; 422 tcflag_t oflag = t->c_oflag; 423 tcflag_t lflag = t->c_lflag; 424 tcflag_t cflag = t->c_cflag; 425 426 /* Nothing we can do with CRTBS. */ 427 if (ISSET(flags, PRTERA)) 428 SET(lflag, ECHOPRT); 429 else 430 CLR(lflag, ECHOPRT); 431 if (ISSET(flags, CRTERA)) 432 SET(lflag, ECHOE); 433 else 434 CLR(lflag, ECHOE); 435 /* Nothing we can do with TILDE. */ 436 if (ISSET(flags, MDMBUF)) 437 SET(cflag, MDMBUF); 438 else 439 CLR(cflag, MDMBUF); 440 if (ISSET(flags, NOHANG)) 441 CLR(cflag, HUPCL); 442 else 443 SET(cflag, HUPCL); 444 if (ISSET(flags, CRTKIL)) 445 SET(lflag, ECHOKE); 446 else 447 CLR(lflag, ECHOKE); 448 if (ISSET(flags, CTLECH)) 449 SET(lflag, ECHOCTL); 450 else 451 CLR(lflag, ECHOCTL); 452 if (!ISSET(flags, DECCTQ)) 453 SET(iflag, IXANY); 454 else 455 CLR(iflag, IXANY); 456 CLR(lflag, TOSTOP|FLUSHO|PENDIN|NOFLSH); 457 SET(lflag, ISSET(flags, TOSTOP|FLUSHO|PENDIN|NOFLSH)); 458 459 if (ISSET(flags, RAW|LITOUT|PASS8)) { 460 CLR(cflag, CSIZE); 461 SET(cflag, CS8); 462 if (!ISSET(flags, RAW|PASS8)) 463 SET(iflag, ISTRIP); 464 else 465 CLR(iflag, ISTRIP); 466 if (!ISSET(flags, RAW|LITOUT)) 467 SET(oflag, OPOST); 468 else 469 CLR(oflag, OPOST); 470 } else { 471 CLR(cflag, CSIZE); 472 SET(cflag, CS7); 473 SET(iflag, ISTRIP); 474 SET(oflag, OPOST); 475 } 476 477 t->c_iflag = iflag; 478 t->c_oflag = oflag; 479 t->c_lflag = lflag; 480 t->c_cflag = cflag; 481 } 482 483 #endif /* COMPAT_OLDTTY */ 484