1 /* tty.c 4.4 03/09/81 */ 2 3 /* 4 * TTY subroutines common to more than one line discipline 5 */ 6 #include "../h/param.h" 7 #include "../h/systm.h" 8 #include "../h/dir.h" 9 #include "../h/user.h" 10 #include "../h/tty.h" 11 #include "../h/proc.h" 12 #include "../h/mx.h" 13 #include "../h/inode.h" 14 #include "../h/file.h" 15 #include "../h/reg.h" 16 #include "../h/conf.h" 17 #include "../h/buf.h" 18 #include "../h/dk.h" 19 20 char partab[]; 21 22 /* 23 * Input mapping table-- if an entry is non-zero, when the 24 * corresponding character is typed preceded by "\" the escape 25 * sequence is replaced by the table value. Mostly used for 26 * upper-case only terminals. 27 */ 28 29 char maptab[] ={ 30 000,000,000,000,000,000,000,000, 31 000,000,000,000,000,000,000,000, 32 000,000,000,000,000,000,000,000, 33 000,000,000,000,000,000,000,000, 34 000,'|',000,000,000,000,000,'`', 35 '{','}',000,000,000,000,000,000, 36 000,000,000,000,000,000,000,000, 37 000,000,000,000,000,000,000,000, 38 000,000,000,000,000,000,000,000, 39 000,000,000,000,000,000,000,000, 40 000,000,000,000,000,000,000,000, 41 000,000,000,000,000,000,'~',000, 42 000,'A','B','C','D','E','F','G', 43 'H','I','J','K','L','M','N','O', 44 'P','Q','R','S','T','U','V','W', 45 'X','Y','Z',000,000,000,000,000, 46 }; 47 48 short tthiwat[16] = 49 { 100,100,100,100,100,100,100,200,200,400,400,400,650,650,650,650 }; 50 short ttlowat[16] = 51 { 30, 30, 30, 30, 30, 30, 30, 50, 50,120,120,120,125,125,125,125 }; 52 53 #define OBUFSIZ 100 54 55 /* 56 * set default control characters. 57 */ 58 ttychars(tp) 59 register struct tty *tp; 60 { 61 62 tun.t_intrc = CINTR; 63 tun.t_quitc = CQUIT; 64 tun.t_startc = CSTART; 65 tun.t_stopc = CSTOP; 66 tun.t_eofc = CEOT; 67 tun.t_brkc = CBRK; 68 tp->t_erase = CERASE; 69 tp->t_kill = CKILL; 70 /* begin local */ 71 tlun.t_suspc = CTRL(z); 72 tlun.t_dsuspc = CTRL(y); 73 tlun.t_rprntc = CTRL(r); 74 tlun.t_flushc = CTRL(o); 75 tlun.t_werasc = CTRL(w); 76 tlun.t_lnextc = CTRL(v); 77 tp->t_local = 0; 78 tp->t_lstate = 0; 79 /* end local */ 80 } 81 82 /* 83 * Wait for output to drain, then flush input waiting. 84 */ 85 wflushtty(tp) 86 register struct tty *tp; 87 { 88 89 (void) spl5(); 90 while (tp->t_outq.c_cc && tp->t_state&CARR_ON) { 91 (*tp->t_oproc)(tp); 92 tp->t_state |= ASLEEP; 93 sleep((caddr_t)&tp->t_outq, TTOPRI); 94 } 95 flushtty(tp, FREAD|FWRITE); 96 (void) spl0(); 97 } 98 99 /* 100 * flush all TTY queues 101 */ 102 flushtty(tp, rw) 103 register struct tty *tp; 104 { 105 register s; 106 107 if (tp->t_line == NETLDISC) 108 return; 109 s = spl6(); 110 if (rw & FREAD) { 111 while (getc(&tp->t_canq) >= 0) 112 ; 113 wakeup((caddr_t)&tp->t_rawq); 114 } 115 if (rw & FWRITE) { 116 wakeup((caddr_t)&tp->t_outq); 117 tp->t_state &= ~TTSTOP; 118 (*cdevsw[major(tp->t_dev)].d_stop)(tp); 119 while (getc(&tp->t_outq) >= 0) 120 ; 121 } 122 if (rw & FREAD) { 123 while (getc(&tp->t_rawq) >= 0) 124 ; 125 tp->t_delct = 0; 126 tp->t_rocount = 0; /* local */ 127 tp->t_rocol = 0; 128 tp->t_lstate = 0; 129 } 130 splx(s); 131 } 132 133 /* 134 * Send stop character on input overflow. 135 */ 136 ttyblock(tp) 137 register struct tty *tp; 138 { 139 register x; 140 x = tp->t_rawq.c_cc + tp->t_canq.c_cc; 141 if (tp->t_rawq.c_cc > TTYHOG) { 142 flushtty(tp, FREAD|FWRITE); 143 tp->t_state &= ~TBLOCK; 144 } 145 if (x >= TTYHOG/2) { 146 if (putc(tun.t_stopc, &tp->t_outq)==0) { 147 tp->t_state |= TBLOCK; 148 tp->t_char++; 149 ttstart(tp); 150 } 151 } 152 } 153 154 /* 155 * Restart typewriter output following a delay 156 * timeout. 157 * The name of the routine is passed to the timeout 158 * subroutine and it is called during a clock interrupt. 159 */ 160 ttrstrt(tp) 161 register struct tty *tp; 162 { 163 164 tp->t_state &= ~TIMEOUT; 165 ttstart(tp); 166 } 167 168 /* 169 * Start output on the typewriter. It is used from the top half 170 * after some characters have been put on the output queue, 171 * from the interrupt routine to transmit the next 172 * character, and after a timeout has finished. 173 */ 174 ttstart(tp) 175 register struct tty *tp; 176 { 177 register s; 178 179 s = spl5(); 180 if((tp->t_state&(TIMEOUT|TTSTOP|BUSY)) == 0) 181 (*tp->t_oproc)(tp); 182 splx(s); 183 } 184 185 /* 186 * Common code for tty ioctls. 187 */ 188 /*ARGSUSED*/ 189 ttioctl(tp, com, addr, flag) 190 register struct tty *tp; 191 caddr_t addr; 192 { 193 int dev; 194 unsigned t; 195 struct sgttyb iocb; 196 struct clist tq; 197 extern int nldisp; 198 register c; 199 int temp; 200 201 /* 202 * This is especially so that isatty() will 203 * fail when carrier is gone. 204 */ 205 if ((tp->t_state&CARR_ON) == 0) { 206 u.u_error = EBADF; 207 return (1); 208 } 209 210 dev = tp->t_dev; 211 /* 212 * If the ioctl involves modification, 213 * insist on being able to write the device, 214 * and hang if in the background. 215 */ 216 switch(com) { 217 218 case TIOCSETD: 219 case TIOCSETP: 220 case TIOCSETN: 221 case TIOCFLUSH: 222 case TIOCSETC: 223 case TIOCSLTC: 224 case TIOCSPGRP: 225 case TIOCLBIS: 226 case TIOCLBIC: 227 case TIOCLSET: 228 case TIOCSTI: 229 /* this is reasonable, but impractical... 230 if ((flag & FWRITE) == 0) { 231 u.u_error = EBADF; 232 return (1); 233 } 234 */ 235 while (tp->t_line == NTTYDISC && 236 u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp && 237 (u.u_procp->p_flag&SVFORK) == 0 && 238 u.u_signal[SIGTTOU] != SIG_IGN && 239 u.u_signal[SIGTTOU] != SIG_HOLD && 240 (u.u_procp->p_flag&SDETACH)==0) { 241 gsignal(u.u_procp->p_pgrp, SIGTTOU); 242 sleep((caddr_t)&lbolt, TTOPRI); 243 } 244 break; 245 } 246 247 /* 248 * Process the ioctl. 249 */ 250 switch(com) { 251 252 /* 253 * Get discipline number 254 */ 255 case TIOCGETD: 256 t = tp->t_line; 257 if (copyout((caddr_t)&t, addr, sizeof(t))) 258 u.u_error = EFAULT; 259 break; 260 261 /* 262 * Set line discipline 263 */ 264 case TIOCSETD: 265 if (copyin(addr, (caddr_t)&t, sizeof(t))) { 266 u.u_error = EFAULT; 267 break; 268 } 269 if (t >= nldisp) { 270 u.u_error = ENXIO; 271 break; 272 } 273 (void) spl5(); 274 if (tp->t_line) 275 (*linesw[tp->t_line].l_close)(tp); 276 if (t) 277 (*linesw[t].l_open)(dev, tp, addr); 278 if (u.u_error==0) 279 tp->t_line = t; 280 (void) spl0(); 281 break; 282 283 /* 284 * Prevent more opens on channel 285 */ 286 case TIOCEXCL: 287 tp->t_state |= XCLUDE; 288 break; 289 290 case TIOCNXCL: 291 tp->t_state &= ~XCLUDE; 292 break; 293 294 /* 295 * Set new parameters 296 */ 297 case TIOCSETP: 298 case TIOCSETN: 299 if (copyin(addr, (caddr_t)&iocb, sizeof(iocb))) { 300 u.u_error = EFAULT; 301 return(1); 302 } 303 (void) spl5(); 304 if (tp->t_line == 0) { 305 if (com == TIOCSETP) 306 wflushtty(tp); 307 while (canon(tp)>=0) 308 ; 309 #ifdef notdef 310 wakeup((caddr_t)&tp->t_rawq); 311 #endif 312 } else if (tp->t_line == NTTYDISC) { 313 if (tp->t_flags&RAW || iocb.sg_flags&RAW || 314 com == TIOCSETP) 315 wflushtty(tp); 316 else if ((tp->t_flags&CBREAK) != (iocb.sg_flags&CBREAK)) { 317 if (iocb.sg_flags & CBREAK) { 318 catq(&tp->t_rawq, &tp->t_canq); 319 tq = tp->t_rawq; 320 tp->t_rawq = tp->t_canq; 321 tp->t_canq = tq; 322 } else { 323 tp->t_local |= LPENDIN; 324 if (tp->t_canq.c_cc) 325 panic("ioccom canq"); 326 #ifdef notdef 327 if (tp->t_chan) 328 (void) sdata(tp->t_chan); 329 else 330 #endif 331 wakeup((caddr_t)&tp->t_rawq); 332 } 333 } 334 } 335 if ((tp->t_state&SPEEDS)==0) { 336 tp->t_ispeed = iocb.sg_ispeed; 337 tp->t_ospeed = iocb.sg_ospeed; 338 } 339 tp->t_erase = iocb.sg_erase; 340 tp->t_kill = iocb.sg_kill; 341 tp->t_flags = iocb.sg_flags; 342 (void) spl0(); 343 break; 344 345 /* 346 * Send current parameters to user 347 */ 348 case TIOCGETP: 349 iocb.sg_ispeed = tp->t_ispeed; 350 iocb.sg_ospeed = tp->t_ospeed; 351 iocb.sg_erase = tp->t_erase; 352 iocb.sg_kill = tp->t_kill; 353 iocb.sg_flags = tp->t_flags; 354 if (copyout((caddr_t)&iocb, addr, sizeof(iocb))) 355 u.u_error = EFAULT; 356 break; 357 358 /* 359 * Hang up line on last close 360 */ 361 case TIOCHPCL: 362 tp->t_state |= HUPCLS; 363 break; 364 365 case TIOCFLUSH: 366 flushtty(tp, FREAD|FWRITE); 367 break; 368 369 /* 370 * Set and fetch special characters 371 */ 372 case TIOCSETC: 373 if (copyin(addr, (caddr_t)&tun, sizeof(struct tchars))) 374 u.u_error = EFAULT; 375 break; 376 377 case TIOCGETC: 378 if (copyout((caddr_t)&tun, addr, sizeof(struct tchars))) 379 u.u_error = EFAULT; 380 break; 381 382 /* local ioctls */ 383 /* 384 * Set/get local special characters. 385 */ 386 case TIOCSLTC: 387 if (copyin(addr, (caddr_t)&tlun, sizeof (struct ltchars))) 388 u.u_error = EFAULT; 389 break; 390 391 case TIOCGLTC: 392 if (copyout((caddr_t)&tlun, addr, sizeof (struct ltchars))) 393 u.u_error = EFAULT; 394 break; 395 396 /* 397 * Return number of characters immediately available. 398 */ 399 case FIONREAD: { 400 off_t nread; 401 402 switch (tp->t_line) { 403 404 case NETLDISC: 405 nread = tp->t_rec ? tp->t_inbuf : 0; 406 break; 407 408 case 0: 409 (void) spl5(); 410 while (canon(tp)>=0) 411 ; 412 (void) spl0(); 413 /* fall into ... */ 414 415 case NTTYDISC: 416 nread = tp->t_canq.c_cc; 417 if (tp->t_flags & (RAW|CBREAK)) 418 nread += tp->t_rawq.c_cc; 419 break; 420 421 } 422 if (copyout((caddr_t)&nread, addr, sizeof (off_t))) 423 u.u_error = EFAULT; 424 break; 425 } 426 427 /* 428 * Should allow SPGRP and GPGRP only if tty open for reading. 429 */ 430 case TIOCSPGRP: 431 if (copyin(addr, (caddr_t)&tp->t_pgrp, sizeof (tp->t_pgrp))) 432 u.u_error = EFAULT; 433 break; 434 435 case TIOCGPGRP: 436 if (copyout((caddr_t)&tp->t_pgrp, addr, sizeof(tp->t_pgrp))) 437 u.u_error = EFAULT; 438 break; 439 440 /* 441 * Modify local mode word. 442 */ 443 case TIOCLBIS: 444 if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local))) 445 u.u_error = EFAULT; 446 else 447 tp->t_local |= temp; 448 break; 449 450 case TIOCLBIC: 451 if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local))) 452 u.u_error = EFAULT; 453 else 454 tp->t_local &= ~temp; 455 break; 456 457 case TIOCLSET: 458 if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local))) 459 u.u_error = EFAULT; 460 else 461 tp->t_local = temp; 462 break; 463 464 case TIOCLGET: 465 if (copyout((caddr_t)&tp->t_local, addr, sizeof(tp->t_local))) 466 u.u_error = EFAULT; 467 break; 468 469 /* 470 * Return number of characters in 471 * the output. 472 */ 473 case TIOCOUTQ: 474 if (copyout((caddr_t)&tp->t_outq.c_cc, addr, sizeof(tp->t_outq.c_cc))) 475 u.u_error = EFAULT; 476 break; 477 478 /* 479 * Simulate typing of a character at the terminal. 480 */ 481 case TIOCSTI: 482 c = fubyte(addr); 483 if (u.u_uid && u.u_ttyp != tp || c < 0) 484 u.u_error = EFAULT; 485 else 486 (*linesw[tp->t_line].l_rint)(c, tp); 487 break; 488 /* end of locals */ 489 490 default: 491 return(0); 492 } 493 return(1); 494 } 495