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