|
|
1.1 ! root 1: /* tty.c 4.12 81/07/22 */ ! 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: if (tp == 0) { ! 165: printf("ttrstrt: arg was 0!\n"); ! 166: return; ! 167: } ! 168: tp->t_state &= ~TIMEOUT; ! 169: ttstart(tp); ! 170: } ! 171: ! 172: /* ! 173: * Start output on the typewriter. It is used from the top half ! 174: * after some characters have been put on the output queue, ! 175: * from the interrupt routine to transmit the next ! 176: * character, and after a timeout has finished. ! 177: */ ! 178: ttstart(tp) ! 179: register struct tty *tp; ! 180: { ! 181: register s; ! 182: ! 183: s = spl5(); ! 184: if((tp->t_state&(TIMEOUT|TTSTOP|BUSY)) == 0) ! 185: (*tp->t_oproc)(tp); ! 186: splx(s); ! 187: } ! 188: ! 189: /* ! 190: * Common code for tty ioctls. ! 191: */ ! 192: /*ARGSUSED*/ ! 193: ttioctl(tp, com, addr, flag) ! 194: register struct tty *tp; ! 195: caddr_t addr; ! 196: { ! 197: int dev; ! 198: unsigned t; ! 199: struct sgttyb iocb; ! 200: struct clist tq; ! 201: extern int nldisp; ! 202: register c; ! 203: int temp; ! 204: ! 205: /* ! 206: * This is especially so that isatty() will ! 207: * fail when carrier is gone. ! 208: */ ! 209: if ((tp->t_state&CARR_ON) == 0) { ! 210: u.u_error = EBADF; ! 211: return (1); ! 212: } ! 213: ! 214: dev = tp->t_dev; ! 215: /* ! 216: * If the ioctl involves modification, ! 217: * insist on being able to write the device, ! 218: * and hang if in the background. ! 219: */ ! 220: switch(com) { ! 221: ! 222: case TIOCSETD: ! 223: case TIOCSETP: ! 224: case TIOCSETN: ! 225: case TIOCFLUSH: ! 226: case TIOCSETC: ! 227: case TIOCSLTC: ! 228: case TIOCSPGRP: ! 229: case TIOCLBIS: ! 230: case TIOCLBIC: ! 231: case TIOCLSET: ! 232: case TIOCSTI: ! 233: /* this is reasonable, but impractical... ! 234: if ((flag & FWRITE) == 0) { ! 235: u.u_error = EBADF; ! 236: return (1); ! 237: } ! 238: */ ! 239: while (tp->t_line == NTTYDISC && ! 240: u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp && ! 241: (u.u_procp->p_flag&SVFORK) == 0 && ! 242: u.u_signal[SIGTTOU] != SIG_IGN && ! 243: u.u_signal[SIGTTOU] != SIG_HOLD && ! 244: (u.u_procp->p_flag&SDETACH)==0) { ! 245: gsignal(u.u_procp->p_pgrp, SIGTTOU); ! 246: sleep((caddr_t)&lbolt, TTOPRI); ! 247: } ! 248: break; ! 249: } ! 250: ! 251: /* ! 252: * Process the ioctl. ! 253: */ ! 254: switch(com) { ! 255: ! 256: /* ! 257: * Get discipline number ! 258: */ ! 259: case TIOCGETD: ! 260: t = tp->t_line; ! 261: if (copyout((caddr_t)&t, addr, sizeof(t))) ! 262: u.u_error = EFAULT; ! 263: break; ! 264: ! 265: /* ! 266: * Set line discipline ! 267: */ ! 268: case TIOCSETD: ! 269: if (copyin(addr, (caddr_t)&t, sizeof(t))) { ! 270: u.u_error = EFAULT; ! 271: break; ! 272: } ! 273: if (t >= nldisp) { ! 274: u.u_error = ENXIO; ! 275: break; ! 276: } ! 277: (void) spl5(); ! 278: if (tp->t_line) ! 279: (*linesw[tp->t_line].l_close)(tp); ! 280: if (t) ! 281: (*linesw[t].l_open)(dev, tp, addr); ! 282: if (u.u_error==0) ! 283: tp->t_line = t; ! 284: (void) spl0(); ! 285: break; ! 286: ! 287: /* ! 288: * Prevent more opens on channel ! 289: */ ! 290: case TIOCEXCL: ! 291: tp->t_state |= XCLUDE; ! 292: break; ! 293: ! 294: case TIOCNXCL: ! 295: tp->t_state &= ~XCLUDE; ! 296: break; ! 297: ! 298: /* ! 299: * Set new parameters ! 300: */ ! 301: case TIOCSETP: ! 302: case TIOCSETN: ! 303: if (copyin(addr, (caddr_t)&iocb, sizeof(iocb))) { ! 304: u.u_error = EFAULT; ! 305: return(1); ! 306: } ! 307: (void) spl5(); ! 308: if (tp->t_line == 0) { ! 309: if (com == TIOCSETP) ! 310: wflushtty(tp); ! 311: while (canon(tp)>=0) ! 312: ; ! 313: #ifdef notdef ! 314: wakeup((caddr_t)&tp->t_rawq); ! 315: #endif ! 316: } else if (tp->t_line == NTTYDISC) { ! 317: if (tp->t_flags&RAW || iocb.sg_flags&RAW || ! 318: com == TIOCSETP) ! 319: wflushtty(tp); ! 320: else if ((tp->t_flags&CBREAK) != (iocb.sg_flags&CBREAK)) { ! 321: if (iocb.sg_flags & CBREAK) { ! 322: catq(&tp->t_rawq, &tp->t_canq); ! 323: tq = tp->t_rawq; ! 324: tp->t_rawq = tp->t_canq; ! 325: tp->t_canq = tq; ! 326: } else { ! 327: tp->t_local |= LPENDIN; ! 328: if (tp->t_canq.c_cc) ! 329: panic("ioccom canq"); ! 330: #ifdef notdef ! 331: if (tp->t_chan) ! 332: (void) sdata(tp->t_chan); ! 333: else ! 334: #endif ! 335: wakeup((caddr_t)&tp->t_rawq); ! 336: } ! 337: } ! 338: } ! 339: if ((tp->t_state&SPEEDS)==0) { ! 340: tp->t_ispeed = iocb.sg_ispeed; ! 341: tp->t_ospeed = iocb.sg_ospeed; ! 342: } ! 343: tp->t_erase = iocb.sg_erase; ! 344: tp->t_kill = iocb.sg_kill; ! 345: tp->t_flags = iocb.sg_flags; ! 346: if (tp->t_flags & RAW) { ! 347: tp->t_state &= ~TTSTOP; ! 348: ttstart(tp); ! 349: } ! 350: (void) spl0(); ! 351: break; ! 352: ! 353: /* ! 354: * Send current parameters to user ! 355: */ ! 356: case TIOCGETP: ! 357: iocb.sg_ispeed = tp->t_ispeed; ! 358: iocb.sg_ospeed = tp->t_ospeed; ! 359: iocb.sg_erase = tp->t_erase; ! 360: iocb.sg_kill = tp->t_kill; ! 361: iocb.sg_flags = tp->t_flags; ! 362: if (copyout((caddr_t)&iocb, addr, sizeof(iocb))) ! 363: u.u_error = EFAULT; ! 364: break; ! 365: ! 366: /* ! 367: * Hang up line on last close ! 368: */ ! 369: case TIOCHPCL: ! 370: tp->t_state |= HUPCLS; ! 371: break; ! 372: ! 373: case TIOCFLUSH: { ! 374: int flags; ! 375: if (addr == 0) ! 376: flags = FREAD|FWRITE; ! 377: else if (copyin(addr, (caddr_t)&flags, sizeof (flags))) { ! 378: u.u_error = EFAULT; ! 379: return(1); ! 380: } ! 381: flushtty(tp, flags); ! 382: break; ! 383: } ! 384: ! 385: /* ! 386: * Set and fetch special characters ! 387: */ ! 388: case TIOCSETC: ! 389: if (copyin(addr, (caddr_t)&tun, sizeof(struct tchars))) ! 390: u.u_error = EFAULT; ! 391: break; ! 392: ! 393: case TIOCGETC: ! 394: if (copyout((caddr_t)&tun, addr, sizeof(struct tchars))) ! 395: u.u_error = EFAULT; ! 396: break; ! 397: ! 398: /* local ioctls */ ! 399: /* ! 400: * Set/get local special characters. ! 401: */ ! 402: case TIOCSLTC: ! 403: if (copyin(addr, (caddr_t)&tlun, sizeof (struct ltchars))) ! 404: u.u_error = EFAULT; ! 405: break; ! 406: ! 407: case TIOCGLTC: ! 408: if (copyout((caddr_t)&tlun, addr, sizeof (struct ltchars))) ! 409: u.u_error = EFAULT; ! 410: break; ! 411: ! 412: /* ! 413: * Return number of characters immediately available. ! 414: */ ! 415: case FIONREAD: { ! 416: off_t nread; ! 417: ! 418: switch (tp->t_line) { ! 419: ! 420: case NETLDISC: ! 421: nread = tp->t_rec ? tp->t_inbuf : 0; ! 422: break; ! 423: ! 424: case 0: ! 425: (void) spl5(); ! 426: while (canon(tp)>=0) ! 427: ; ! 428: (void) spl0(); ! 429: /* fall into ... */ ! 430: ! 431: case NTTYDISC: ! 432: if (tp->t_local & LPENDIN) ! 433: ntypend(tp); ! 434: nread = tp->t_canq.c_cc; ! 435: if (tp->t_flags & (RAW|CBREAK)) ! 436: nread += tp->t_rawq.c_cc; ! 437: break; ! 438: ! 439: } ! 440: if (copyout((caddr_t)&nread, addr, sizeof (off_t))) ! 441: u.u_error = EFAULT; ! 442: break; ! 443: } ! 444: ! 445: /* ! 446: * Should allow SPGRP and GPGRP only if tty open for reading. ! 447: */ ! 448: case TIOCSPGRP: ! 449: if (copyin(addr, (caddr_t)&tp->t_pgrp, sizeof (tp->t_pgrp))) ! 450: u.u_error = EFAULT; ! 451: break; ! 452: ! 453: case TIOCGPGRP: ! 454: if (copyout((caddr_t)&tp->t_pgrp, addr, sizeof(tp->t_pgrp))) ! 455: u.u_error = EFAULT; ! 456: break; ! 457: ! 458: /* ! 459: * Modify local mode word. ! 460: */ ! 461: case TIOCLBIS: ! 462: if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local))) ! 463: u.u_error = EFAULT; ! 464: else ! 465: tp->t_local |= temp; ! 466: break; ! 467: ! 468: case TIOCLBIC: ! 469: if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local))) ! 470: u.u_error = EFAULT; ! 471: else ! 472: tp->t_local &= ~temp; ! 473: break; ! 474: ! 475: case TIOCLSET: ! 476: if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local))) ! 477: u.u_error = EFAULT; ! 478: else ! 479: tp->t_local = temp; ! 480: break; ! 481: ! 482: case TIOCLGET: ! 483: if (copyout((caddr_t)&tp->t_local, addr, sizeof(tp->t_local))) ! 484: u.u_error = EFAULT; ! 485: break; ! 486: ! 487: /* ! 488: * Return number of characters in ! 489: * the output. ! 490: */ ! 491: case TIOCOUTQ: ! 492: if (copyout((caddr_t)&tp->t_outq.c_cc, addr, sizeof(tp->t_outq.c_cc))) ! 493: u.u_error = EFAULT; ! 494: break; ! 495: ! 496: /* ! 497: * Simulate typing of a character at the terminal. ! 498: */ ! 499: case TIOCSTI: ! 500: c = fubyte(addr); ! 501: if (u.u_uid && u.u_ttyp != tp || c < 0) ! 502: u.u_error = EFAULT; ! 503: else ! 504: (*linesw[tp->t_line].l_rint)(c, tp); ! 505: break; ! 506: /* end of locals */ ! 507: ! 508: default: ! 509: return(0); ! 510: } ! 511: return(1); ! 512: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.