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