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