1: /* 2: * Copyright (c) 1986 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: * 6: * @(#)tty.c 1.5 (2.11BSD GTE) 1997/5/4 7: */ 8: 9: #include "param.h" 10: #include "user.h" 11: #include "ioctl.h" 12: #include "tty.h" 13: #include "proc.h" 14: #include "file.h" 15: #include "conf.h" 16: #include "dk.h" 17: #include "uio.h" 18: #include "kernel.h" 19: #include "systm.h" 20: #include "inode.h" 21: #include "syslog.h" 22: 23: /* 24: * These were moved here from tty.h so that they could be easily modified 25: * and/or patched instead of recompiling the kernel. There is only 1 other 26: * place which references these - see tty_pty.c 27: * 28: * The block and unblock numbers may look low but certain devices (the DHV-11 29: * for example) have poor silo handling and at high data rates (19200) the 30: * raw queue overflows even though we've stopped the sending device. At 192 31: * characters for the 'block' point c-kermit would regularily see dropped data 32: * during interactive mode at 19200. 33: * 34: * It would be nice to have a larger than 8kb clist area and raise these limits 35: * but that would require 2 mapping registers and/or a rewrite of the entire 36: * clist handling. 37: */ 38: 39: int TTYHOG = 255; 40: int TTYBLOCK=128; 41: int TTYUNBLOCK=64; 42: 43: /* 44: * Table giving parity for characters and indicating 45: * character classes to tty driver. In particular, 46: * if the low 6 bits are 0, then the character needs 47: * no special processing on output. 48: */ 49: 50: char partab[] = { 51: 0001,0201,0201,0001,0201,0001,0001,0201, 52: 0202,0004,0003,0201,0005,0206,0201,0001, 53: 0201,0001,0001,0201,0001,0201,0201,0001, 54: 0001,0201,0201,0001,0201,0001,0001,0201, 55: 0200,0000,0000,0200,0000,0200,0200,0000, 56: 0000,0200,0200,0000,0200,0000,0000,0200, 57: 0000,0200,0200,0000,0200,0000,0000,0200, 58: 0200,0000,0000,0200,0000,0200,0200,0000, 59: 0200,0000,0000,0200,0000,0200,0200,0000, 60: 0000,0200,0200,0000,0200,0000,0000,0200, 61: 0000,0200,0200,0000,0200,0000,0000,0200, 62: 0200,0000,0000,0200,0000,0200,0200,0000, 63: 0000,0200,0200,0000,0200,0000,0000,0200, 64: 0200,0000,0000,0200,0000,0200,0200,0000, 65: 0200,0000,0000,0200,0000,0200,0200,0000, 66: 0000,0200,0200,0000,0200,0000,0000,0201, 67: 68: /* 69: * 7 bit ascii ends with the last character above, 70: * but we contine through all 256 codes for the sake 71: * of the tty output routines which use special vax 72: * instructions which need a 256 character trt table. 73: */ 74: 75: 0007,0007,0007,0007,0007,0007,0007,0007, 76: 0007,0007,0007,0007,0007,0007,0007,0007, 77: 0007,0007,0007,0007,0007,0007,0007,0007, 78: 0007,0007,0007,0007,0007,0007,0007,0007, 79: 0007,0007,0007,0007,0007,0007,0007,0007, 80: 0007,0007,0007,0007,0007,0007,0007,0007, 81: 0007,0007,0007,0007,0007,0007,0007,0007, 82: 0007,0007,0007,0007,0007,0007,0007,0007, 83: 0007,0007,0007,0007,0007,0007,0007,0007, 84: 0007,0007,0007,0007,0007,0007,0007,0007, 85: 0007,0007,0007,0007,0007,0007,0007,0007, 86: 0007,0007,0007,0007,0007,0007,0007,0007, 87: 0007,0007,0007,0007,0007,0007,0007,0007, 88: 0007,0007,0007,0007,0007,0007,0007,0007, 89: 0007,0007,0007,0007,0007,0007,0007,0007, 90: 0007,0007,0007,0007,0007,0007,0007,0007 91: }; 92: 93: short tthiwat[16] = 94: { 100,100,100,100,100,100,100,200,200,400,400,400,650,650,1300,2000 }; 95: short ttlowat[16] = 96: { 30, 30, 30, 30, 30, 30, 30, 50, 50,120,120,120,125,125,125,125 }; 97: 98: struct ttychars ttydefaults = { 99: CERASE, CKILL, CINTR, CQUIT, CSTART, CSTOP, CEOF, 100: CBRK, CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE,CLNEXT 101: }; 102: 103: #define SET(t,f) (t) |= (f) 104: #define CLR(t,f) (t) &= ~(f) 105: #define ISSET(t,f) ((t) & (f)) 106: 107: extern char *nextc(); 108: extern int nldisp; 109: extern int wakeup(); 110: 111: ttychars(tp) 112: struct tty *tp; 113: { 114: 115: tp->t_chars = ttydefaults; 116: } 117: 118: /* 119: * Wakeup processes waiting on output flow control (TS_ASLEEP). Normally 120: * called from driver start routine (dhvstart, etc) after a transmit done 121: * interrupt. If t_outq.c_cc <= t_lowat then do the wakeup. 122: */ 123: ttyowake(tp) 124: register struct tty *tp; 125: { 126: 127: if (tp->t_outq.c_cc <= TTLOWAT(tp)) 128: { 129: if (ISSET(tp->t_state,TS_ASLEEP)) 130: { 131: CLR(tp->t_state,TS_ASLEEP); 132: wakeup((caddr_t)&tp->t_outq); 133: } 134: if (tp->t_wsel) 135: { 136: selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 137: tp->t_wsel = 0; 138: CLR(tp->t_state,TS_WCOLL); 139: } 140: } 141: } 142: 143: /* 144: * Wait for output to drain, then flush input waiting. 145: */ 146: ttywflush(tp) 147: register struct tty *tp; 148: { 149: 150: ttywait(tp); 151: ttyflush(tp, FREAD); 152: } 153: 154: ttywait(tp) 155: register struct tty *tp; 156: { 157: register int s = spltty(); 158: 159: while ((tp->t_outq.c_cc || tp->t_state&TS_BUSY) && 160: tp->t_state&TS_CARR_ON && tp->t_oproc) { 161: (*tp->t_oproc)(tp); 162: /* 163: * If the output routine drains the queue and the device is no longer busy 164: * then don't wait for something that's already happened. 165: */ 166: if (tp->t_outq.c_cc == 0 && !ISSET(tp->t_state,TS_BUSY)) 167: break; 168: tp->t_state |= TS_ASLEEP; 169: sleep((caddr_t)&tp->t_outq, TTOPRI); 170: splx(s); /* drop priority, give interrupts a chance */ 171: s = spltty(); 172: } 173: splx(s); 174: } 175: 176: /* 177: * Flush all TTY queues 178: */ 179: ttyflush(tp, rw) 180: register struct tty *tp; 181: { 182: register int s; 183: 184: s = spltty(); 185: if (rw & FREAD) { 186: while (getc(&tp->t_canq) >= 0) 187: ; 188: while (getc(&tp->t_rawq) >= 0) 189: ; 190: tp->t_rocount = 0; 191: tp->t_rocol = 0; 192: tp->t_state &= ~TS_LOCAL; 193: ttwakeup(tp); 194: } 195: if (rw & FWRITE) { 196: tp->t_state &= ~TS_TTSTOP; 197: (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw); 198: wakeup((caddr_t)&tp->t_outq); 199: while (getc(&tp->t_outq) >= 0) 200: ; 201: selwakeup(&tp->t_wsel, tp->t_state & TS_WCOLL); 202: CLR(tp->t_state, TS_WCOLL); 203: tp->t_wsel = 0; 204: } 205: if (rw & FREAD && ISSET(tp->t_state,TS_TBLOCK)) 206: ttyunblock(tp); 207: splx(s); 208: } 209: 210: static int rts = TIOCM_RTS; 211: 212: /* 213: * Send stop character on input overflow. 214: */ 215: ttyblock(tp) 216: register struct tty *tp; 217: { 218: register int total; 219: 220: total = tp->t_rawq.c_cc + tp->t_canq.c_cc; 221: /* 222: * Block further input iff: 223: * Current input > threshold AND input is available to user program 224: */ 225: if (total >= TTYBLOCK && 226: ((tp->t_flags & (RAW|CBREAK)) || (tp->t_canq.c_cc > 0)) && 227: (tp->t_state&TS_TBLOCK) == 0) 228: { 229: /* 230: * TANDEM is the same as IXOFF for all intents and purposes. Since we could 231: * get called for either software or hardware flow control we need to check 232: * the IXOFF bit. 233: */ 234: if (ISSET(tp->t_flags,TANDEM) && 235: tp->t_stopc != _POSIX_VDISABLE && 236: putc(tp->t_stopc, &tp->t_outq) == 0) 237: { 238: SET(tp->t_state, TS_TBLOCK); 239: ttstart(tp); 240: } 241: /* 242: * If queue is full, drop RTS to tell modem to stop sending us stuff 243: */ 244: if (ISSET(tp->t_flags, RTSCTS) && 245: (*cdevsw[major(tp->t_dev)].d_ioctl)(tp->t_dev,TIOCMBIC, &rts, 0) == 0) 246: { 247: SET(tp->t_state, TS_TBLOCK); 248: } 249: } 250: } 251: 252: ttyunblock(tp) 253: register struct tty *tp; 254: { 255: register int s = spltty(); 256: 257: if (ISSET(tp->t_flags,TANDEM) && 258: tp->t_startc != _POSIX_VDISABLE && 259: putc(tp->t_startc, &tp->t_outq) == 0) 260: { 261: CLR(tp->t_state,TS_TBLOCK); 262: ttstart(tp); 263: } 264: if (ISSET(tp->t_flags, RTSCTS) && 265: (*cdevsw[major(tp->t_dev)].d_ioctl)(tp->t_dev,TIOCMBIS,&rts,0) == 0) 266: { 267: CLR(tp->t_state, TS_TBLOCK); 268: } 269: } 270: 271: /* 272: * Restart typewriter output following a delay timeout. 273: * The name of the routine is passed to the timeout 274: * subroutine and it is called during a clock interrupt. 275: */ 276: ttrstrt(tp) 277: register struct tty *tp; 278: { 279: 280: tp->t_state &= ~TS_TIMEOUT; 281: ttstart(tp); 282: } 283: 284: /* 285: * Start output on the typewriter. It is used from the top half 286: * after some characters have been put on the output queue, 287: * from the interrupt routine to transmit the next 288: * character, and after a timeout has finished. 289: * 290: * The spl calls were removed because the priority should already be spltty. 291: */ 292: ttstart(tp) 293: register struct tty *tp; 294: { 295: 296: if (tp->t_oproc) /* kludge for pty */ 297: (*tp->t_oproc)(tp); 298: } 299: 300: /* 301: * Common code for tty ioctls. 302: */ 303: /*ARGSUSED*/ 304: ttioctl(tp, com, data, flag) 305: register struct tty *tp; 306: u_int com; 307: caddr_t data; 308: int flag; 309: { 310: int dev = tp->t_dev; 311: int s; 312: long newflags; 313: 314: /* 315: * If the ioctl involves modification, 316: * hang if in the background. 317: */ 318: switch (com) { 319: 320: case TIOCSETD: 321: case TIOCSETP: 322: case TIOCSETN: 323: case TIOCFLUSH: 324: case TIOCSETC: 325: case TIOCSLTC: 326: case TIOCSPGRP: 327: case TIOCLBIS: 328: case TIOCLBIC: 329: case TIOCLSET: 330: case TIOCSTI: 331: case TIOCSWINSZ: 332: while (tp->t_line == NTTYDISC && 333: u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp && 334: (u.u_procp->p_flag&SVFORK) == 0 && 335: !(u.u_procp->p_sigignore & sigmask(SIGTTOU)) && 336: !(u.u_procp->p_sigmask & sigmask(SIGTTOU))) { 337: gsignal(u.u_procp->p_pgrp, SIGTTOU); 338: sleep((caddr_t)&lbolt, TTOPRI); 339: } 340: break; 341: } 342: 343: /* 344: * Process the ioctl. 345: */ 346: switch (com) { 347: 348: /* get discipline number */ 349: case TIOCGETD: 350: *(int *)data = tp->t_line; 351: break; 352: 353: /* set line discipline */ 354: case TIOCSETD: { 355: register int t = *(int *)data; 356: int error = 0; 357: 358: if ((unsigned) t >= nldisp) 359: return (ENXIO); 360: if (t != tp->t_line) { 361: s = spltty(); 362: (*linesw[tp->t_line].l_close)(tp, flag); 363: error = (*linesw[t].l_open)(dev, tp); 364: if (error) { 365: (void) (*linesw[tp->t_line].l_open)(dev, tp); 366: splx(s); 367: return (error); 368: } 369: tp->t_line = t; 370: splx(s); 371: } 372: break; 373: } 374: 375: /* prevent more opens on channel */ 376: case TIOCEXCL: 377: tp->t_state |= TS_XCLUDE; 378: break; 379: 380: case TIOCNXCL: 381: tp->t_state &= ~TS_XCLUDE; 382: break; 383: 384: /* hang up line on last close */ 385: case TIOCHPCL: 386: tp->t_state |= TS_HUPCLS; 387: break; 388: 389: case TIOCFLUSH: { 390: register int flags = *(int *)data; 391: 392: if (flags == 0) 393: flags = FREAD|FWRITE; 394: else 395: flags &= FREAD|FWRITE; 396: ttyflush(tp, flags); 397: break; 398: } 399: 400: /* return number of characters immediately available */ 401: case FIONREAD: 402: *(off_t *)data = ttnread(tp); 403: break; 404: 405: case TIOCOUTQ: 406: *(int *)data = tp->t_outq.c_cc; 407: break; 408: 409: case TIOCSTOP: 410: s = spltty(); 411: if ((tp->t_state&TS_TTSTOP) == 0) { 412: tp->t_state |= TS_TTSTOP; 413: (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 414: } 415: splx(s); 416: break; 417: 418: case TIOCSTART: 419: s = spltty(); 420: if ((tp->t_state&TS_TTSTOP) || (tp->t_flags&FLUSHO)) { 421: tp->t_state &= ~TS_TTSTOP; 422: tp->t_flags &= ~FLUSHO; 423: ttstart(tp); 424: } 425: splx(s); 426: break; 427: 428: /* 429: * Simulate typing of a character at the terminal. 430: */ 431: case TIOCSTI: 432: if (u.u_uid && (flag & FREAD) == 0) 433: return (EPERM); 434: if (u.u_uid && u.u_ttyp != tp) 435: return (EACCES); 436: (*linesw[tp->t_line].l_rint)(*(char *)data, tp); 437: break; 438: 439: case TIOCSETP: 440: case TIOCSETN: { 441: register struct sgttyb *sg = (struct sgttyb *)data; 442: 443: tp->t_erase = sg->sg_erase; 444: tp->t_kill = sg->sg_kill; 445: tp->t_ispeed = sg->sg_ispeed; 446: tp->t_ospeed = sg->sg_ospeed; 447: newflags = (tp->t_flags&0xffff0000) | (sg->sg_flags&0xffffL); 448: s = spltty(); 449: if (tp->t_flags&RAW || newflags&RAW || com == TIOCSETP) { 450: ttywait(tp); 451: ttyflush(tp, FREAD); 452: } else if ((tp->t_flags&CBREAK) != (newflags&CBREAK)) { 453: if (newflags&CBREAK) { 454: struct clist tq; 455: 456: catq(&tp->t_rawq, &tp->t_canq); 457: tq = tp->t_rawq; 458: tp->t_rawq = tp->t_canq; 459: tp->t_canq = tq; 460: } else { 461: tp->t_flags |= PENDIN; 462: newflags |= PENDIN; 463: ttwakeup(tp); 464: } 465: } 466: tp->t_flags = newflags; 467: if (tp->t_flags&RAW) { 468: tp->t_state &= ~TS_TTSTOP; 469: ttstart(tp); 470: } 471: splx(s); 472: break; 473: } 474: 475: /* send current parameters to user */ 476: case TIOCGETP: { 477: register struct sgttyb *sg = (struct sgttyb *)data; 478: 479: sg->sg_ispeed = tp->t_ispeed; 480: sg->sg_ospeed = tp->t_ospeed; 481: sg->sg_erase = tp->t_erase; 482: sg->sg_kill = tp->t_kill; 483: sg->sg_flags = tp->t_flags; 484: break; 485: } 486: 487: case FIONBIO: 488: break; /* XXX remove */ 489: 490: case FIOASYNC: 491: if (*(int *)data) 492: tp->t_state |= TS_ASYNC; 493: else 494: tp->t_state &= ~TS_ASYNC; 495: break; 496: 497: case TIOCGETC: 498: bcopy((caddr_t)&tp->t_intrc, data, sizeof (struct tchars)); 499: break; 500: 501: case TIOCSETC: 502: bcopy(data, (caddr_t)&tp->t_intrc, sizeof (struct tchars)); 503: break; 504: 505: /* set/get local special characters */ 506: case TIOCSLTC: 507: bcopy(data, (caddr_t)&tp->t_suspc, sizeof (struct ltchars)); 508: break; 509: 510: case TIOCGLTC: 511: bcopy((caddr_t)&tp->t_suspc, data, sizeof (struct ltchars)); 512: break; 513: 514: /* 515: * Modify local mode word. 516: */ 517: case TIOCLBIS: 518: tp->t_flags |= (long)*(u_int *)data << 16; 519: break; 520: 521: case TIOCLBIC: 522: tp->t_flags &= ~((long)*(u_int *)data << 16); 523: break; 524: 525: case TIOCLSET: 526: tp->t_flags &= 0xffffL; 527: tp->t_flags |= (long)*(u_int *)data << 16; 528: break; 529: 530: case TIOCLGET: 531: *(int *)data = tp->t_flags >> 16; 532: break; 533: 534: /* 535: * Allow SPGRP only if tty is open for reading. 536: * Quick check: if we can find a process in the new pgrp, 537: * this user must own that process. 538: * SHOULD VERIFY THAT PGRP IS IN USE AND IS THIS USER'S. 539: */ 540: case TIOCSPGRP: { 541: struct proc *p; 542: short pgrp = *(int *)data; 543: 544: if (u.u_uid && (flag & FREAD) == 0) 545: return (EPERM); 546: p = pfind(pgrp); 547: if (p && p->p_pgrp == pgrp && 548: p->p_uid != u.u_uid && u.u_uid && !inferior(p)) 549: return (EPERM); 550: tp->t_pgrp = pgrp; 551: break; 552: } 553: 554: case TIOCGPGRP: 555: *(int *)data = tp->t_pgrp; 556: break; 557: 558: case TIOCSWINSZ: 559: if (bcmp((caddr_t)&tp->t_winsize, data, 560: sizeof (struct winsize))) { 561: tp->t_winsize = *(struct winsize *)data; 562: gsignal(tp->t_pgrp, SIGWINCH); 563: } 564: break; 565: 566: case TIOCGWINSZ: 567: *(struct winsize *)data = tp->t_winsize; 568: break; 569: 570: default: 571: return (-1); 572: } 573: return (0); 574: } 575: 576: ttnread(tp) 577: register struct tty *tp; 578: { 579: register int nread = 0; 580: 581: if (tp->t_flags & PENDIN) 582: ttypend(tp); 583: nread = tp->t_canq.c_cc; 584: if (tp->t_flags & (RAW|CBREAK)) 585: nread += tp->t_rawq.c_cc; 586: return (nread); 587: } 588: 589: /* 590: * XXX - this cleans up the minor device number by stripping off the 591: * softcarrier bit. Drives which use more bits of the minor device 592: * MUST call their own select routine. See dhv.c for an example. 593: * 594: * This routine will go away when all the drivers have been updated/converted 595: */ 596: 597: ttselect(dev, rw) 598: register dev_t dev; 599: int rw; 600: { 601: struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)&0177]; 602: 603: return(ttyselect(tp,rw)); 604: } 605: 606: ttyselect(tp,rw) 607: register struct tty *tp; 608: int rw; 609: { 610: int nread; 611: register int s = spltty(); 612: 613: switch (rw) { 614: 615: case FREAD: 616: nread = ttnread(tp); 617: if ((nread > 0) || ((tp->t_state & TS_CARR_ON) == 0)) 618: goto win; 619: if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait) 620: tp->t_state |= TS_RCOLL; 621: else 622: tp->t_rsel = u.u_procp; 623: break; 624: 625: case FWRITE: 626: if (tp->t_outq.c_cc <= TTLOWAT(tp)) 627: goto win; 628: if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait) 629: tp->t_state |= TS_WCOLL; 630: else 631: tp->t_wsel = u.u_procp; 632: break; 633: } 634: splx(s); 635: return (0); 636: win: 637: splx(s); 638: return (1); 639: } 640: 641: /* 642: * Initial open of tty, or (re)entry to line discipline. 643: * Establish a process group for distribution of 644: * quits and interrupts from the tty. 645: */ 646: ttyopen(dev, tp) 647: dev_t dev; 648: register struct tty *tp; 649: { 650: register struct proc *pp; 651: 652: pp = u.u_procp; 653: tp->t_dev = dev; 654: if (pp->p_pgrp == 0) { 655: u.u_ttyp = tp; 656: u.u_ttyd = dev; 657: if (tp->t_pgrp == 0) 658: tp->t_pgrp = pp->p_pid; 659: pp->p_pgrp = tp->t_pgrp; 660: } 661: tp->t_state &= ~TS_WOPEN; 662: if ((tp->t_state & TS_ISOPEN) == 0) { 663: tp->t_state |= TS_ISOPEN; 664: bzero((caddr_t)&tp->t_winsize, sizeof(tp->t_winsize)); 665: if (tp->t_line != NTTYDISC) 666: ttywflush(tp); 667: } 668: return (0); 669: } 670: 671: /* 672: * "close" a line discipline 673: */ 674: ttylclose(tp, flag) 675: register struct tty *tp; 676: int flag; 677: { 678: 679: /* 680: * 4.4 has IO_NDELAY but I think that is a mistake because the upper level 681: * 'close' routines all pass 'fp->f_flags' down. This was verified with a 682: * printf here - the F* flags are received rather than the IO_* flags! 683: */ 684: 685: if (flag & FNDELAY) 686: ttyflush(tp, FREAD|FWRITE); 687: else 688: ttywflush(tp); 689: tp->t_line = 0; 690: } 691: 692: /* 693: * clean tp on last close 694: */ 695: ttyclose(tp) 696: register struct tty *tp; 697: { 698: 699: ttyflush(tp, FREAD|FWRITE); 700: tp->t_pgrp = 0; 701: tp->t_state = 0; 702: } 703: 704: /* 705: * Handle modem control transition on a tty. 706: * Flag indicates new state of carrier. 707: * Returns 0 if the line should be turned off, otherwise 1. 708: */ 709: ttymodem(tp, flag) 710: register struct tty *tp; 711: int flag; 712: { 713: 714: if ((tp->t_state&TS_WOPEN) == 0 && (tp->t_flags & MDMBUF)) { 715: /* 716: * MDMBUF: do flow control according to carrier flag 717: */ 718: if (flag) { 719: tp->t_state &= ~TS_TTSTOP; 720: ttstart(tp); 721: } else if ((tp->t_state&TS_TTSTOP) == 0) { 722: tp->t_state |= TS_TTSTOP; 723: (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 724: } 725: } else if (flag == 0) { 726: /* 727: * Lost carrier. 728: */ 729: tp->t_state &= ~TS_CARR_ON; 730: if (tp->t_state & TS_ISOPEN) { 731: if ((tp->t_flags & NOHANG) == 0) { 732: gsignal(tp->t_pgrp, SIGHUP); 733: gsignal(tp->t_pgrp, SIGCONT); 734: ttyflush(tp, FREAD|FWRITE); 735: return (0); 736: } 737: } 738: } else { 739: /* 740: * Carrier now on. 741: */ 742: tp->t_state |= TS_CARR_ON; 743: wakeup((caddr_t)&tp->t_rawq); 744: } 745: return (1); 746: } 747: 748: /* 749: * Default modem control routine (for other line disciplines). 750: * Return argument flag, to turn off device on carrier drop. 751: */ 752: nullmodem(tp, flag) 753: register struct tty *tp; 754: int flag; 755: { 756: 757: if (flag) 758: tp->t_state |= TS_CARR_ON; 759: else 760: tp->t_state &= ~TS_CARR_ON; 761: return (flag); 762: } 763: 764: /* 765: * reinput pending characters after state switch 766: * call at spltty(). 767: */ 768: ttypend(tp) 769: register struct tty *tp; 770: { 771: struct clist tq; 772: register int c; 773: 774: tp->t_flags &= ~PENDIN; 775: tp->t_state |= TS_TYPEN; 776: tq = tp->t_rawq; 777: tp->t_rawq.c_cc = 0; 778: tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0; 779: while ((c = getc(&tq)) >= 0) 780: ttyinput(c, tp); 781: tp->t_state &= ~TS_TYPEN; 782: } 783: 784: /* 785: * Place a character on raw TTY input queue, 786: * putting in delimiters and waking up top 787: * half as needed. Also echo if required. 788: * The arguments are the character and the 789: * appropriate tty structure. 790: */ 791: ttyinput(c, tp) 792: register int c; 793: register struct tty *tp; 794: { 795: long t_flags = tp->t_flags; 796: int i; 797: 798: /* 799: * If input is pending take it first. 800: */ 801: if (t_flags&PENDIN) 802: ttypend(tp); 803: #ifdef UCB_METER 804: tk_nin++; 805: #endif 806: c &= 0377; 807: 808: /* 809: * In tandem mode, check high water mark. 810: */ 811: if (t_flags & (TANDEM|RTSCTS)) 812: ttyblock(tp); 813: 814: if (t_flags&RAW) { 815: /* 816: * Raw mode, just put character 817: * in input q w/o interpretation. 818: */ 819: if (tp->t_rawq.c_cc > TTYHOG) 820: ttyflush(tp, FREAD|FWRITE); 821: else { 822: if (putc(c, &tp->t_rawq) == 0) 823: ttwakeup(tp); 824: ttyecho(c, tp); 825: } 826: goto endcase; 827: } 828: 829: /* 830: * Ignore any high bit added during 831: * previous ttyinput processing. 832: */ 833: if ((tp->t_state&TS_TYPEN) == 0 && (t_flags&PASS8) == 0) 834: c &= 0177; 835: 836: /* 837: * Check for literal nexting very first. This is the _ONLY_ place 838: * left which ORs in 0200. Handling literal nexting this way is 839: * what keeps the tty subsystem from being 8 bit clean. The fix is 840: * horrendous though and is put off for now. And to think that ALL 841: * of this is made necessary by ttyrubout() - it's the only place that 842: * actually _checks_ the 0200 bit and only for newline and tab chars 843: * at that! 844: * 845: * If we had 9 bit bytes life would be a lot simpler ;) 846: * 847: * The basic idea is to flag the character as "special" and also 848: * modify it so that the character does not match any of the special 849: * editing or control characters. We could just as simply jump directly 850: * to the test for 'cbreak' below. 851: */ 852: if (tp->t_state&TS_LNCH) { 853: c |= 0200; 854: tp->t_state &= ~TS_LNCH; 855: } 856: 857: /* 858: * Scan for special characters. This code 859: * is really just a big case statement with 860: * non-constant cases. The bottom of the 861: * case statement is labeled ``endcase'', so goto 862: * it after a case match, or similar. 863: */ 864: if (tp->t_line == NTTYDISC) { 865: if (CCEQ(tp->t_lnextc,c)) { 866: if (t_flags&ECHO) 867: ttyout("^\b", tp); 868: tp->t_state |= TS_LNCH; 869: goto endcase; 870: } 871: if (CCEQ(tp->t_flushc,c)) { 872: if (t_flags&FLUSHO) 873: tp->t_flags &= ~FLUSHO; 874: else { 875: ttyflush(tp, FWRITE); 876: ttyecho(c, tp); 877: if (tp->t_rawq.c_cc + tp->t_canq.c_cc) 878: ttyretype(tp); 879: tp->t_flags |= FLUSHO; 880: } 881: goto startoutput; 882: } 883: if (CCEQ(tp->t_suspc,c)) { 884: if ((t_flags&NOFLSH) == 0) 885: ttyflush(tp, FREAD); 886: ttyecho(c, tp); 887: gsignal(tp->t_pgrp, SIGTSTP); 888: goto endcase; 889: } 890: } 891: 892: /* 893: * Handle start/stop characters. 894: */ 895: if (CCEQ(tp->t_stopc,c)) { 896: if ((tp->t_state&TS_TTSTOP) == 0) { 897: tp->t_state |= TS_TTSTOP; 898: (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 899: return; 900: } 901: if (CCEQ(tp->t_startc,c)) 902: return; 903: goto endcase; 904: } 905: if (CCEQ(tp->t_startc,c)) 906: goto restartoutput; 907: 908: /* 909: * Look for interrupt/quit chars. 910: */ 911: if (CCEQ(tp->t_intrc,c) || CCEQ(tp->t_quitc,c)) { 912: if ((t_flags&NOFLSH) == 0) 913: ttyflush(tp, FREAD|FWRITE); 914: ttyecho(c, tp); 915: gsignal(tp->t_pgrp, CCEQ(tp->t_intrc,c) ? SIGINT : SIGQUIT); 916: goto endcase; 917: } 918: 919: /* 920: * Cbreak mode, don't process line editing 921: * characters; check high water mark for wakeup. 922: */ 923: if (t_flags&CBREAK) { 924: if (tp->t_rawq.c_cc > TTYHOG) { 925: if (tp->t_outq.c_cc < TTHIWAT(tp) && 926: tp->t_line == NTTYDISC) 927: (void) ttyoutput(CTRL(g), tp); 928: } else if (putc(c, &tp->t_rawq) == 0) { 929: ttwakeup(tp); 930: ttyecho(c, tp); 931: } 932: goto endcase; 933: } 934: 935: /* 936: * From here on down cooked mode character 937: * processing takes place. 938: */ 939: if (CCEQ(tp->t_erase,c)) { 940: if (tp->t_rawq.c_cc) 941: ttyrub(unputc(&tp->t_rawq), tp); 942: goto endcase; 943: } 944: if (CCEQ(tp->t_kill,c)) { 945: if (t_flags&CRTKIL && 946: tp->t_rawq.c_cc == tp->t_rocount) { 947: while (tp->t_rawq.c_cc) 948: ttyrub(unputc(&tp->t_rawq), tp); 949: } else { 950: ttyecho(c, tp); 951: ttyecho('\n', tp); 952: while (getc(&tp->t_rawq) > 0) 953: ; 954: tp->t_rocount = 0; 955: } 956: tp->t_state &= ~TS_LOCAL; 957: goto endcase; 958: } 959: 960: /* 961: * New line discipline, 962: * check word erase/reprint line. 963: */ 964: if (tp->t_line == NTTYDISC) { 965: if (CCEQ(tp->t_werasc,c)) { 966: if (tp->t_rawq.c_cc == 0) 967: goto endcase; 968: do { 969: c = unputc(&tp->t_rawq); 970: if (c != ' ' && c != '\t') 971: goto erasenb; 972: ttyrub(c, tp); 973: } while (tp->t_rawq.c_cc); 974: goto endcase; 975: erasenb: 976: do { 977: ttyrub(c, tp); 978: if (tp->t_rawq.c_cc == 0) 979: goto endcase; 980: c = unputc(&tp->t_rawq); 981: } while (c != ' ' && c != '\t'); 982: (void) putc(c, &tp->t_rawq); 983: goto endcase; 984: } 985: if (CCEQ(tp->t_rprntc,c)) { 986: ttyretype(tp); 987: goto endcase; 988: } 989: } 990: 991: /* 992: * Check for input buffer overflow 993: */ 994: if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG) { 995: if (tp->t_line == NTTYDISC) 996: (void) ttyoutput(CTRL(g), tp); 997: goto endcase; 998: } 999: 1000: /* 1001: * Put data char in q for user and 1002: * wakeup on seeing a line delimiter. 1003: */ 1004: if (putc(c, &tp->t_rawq) == 0) { 1005: if (ttbreakc(c, tp)) { 1006: tp->t_rocount = 0; 1007: catq(&tp->t_rawq, &tp->t_canq); 1008: ttwakeup(tp); 1009: } else if (tp->t_rocount++ == 0) 1010: tp->t_rocol = tp->t_col; 1011: if (tp->t_state&TS_ERASE) { 1012: tp->t_state &= ~TS_ERASE; 1013: (void) ttyoutput('/', tp); 1014: } 1015: i = tp->t_col; 1016: ttyecho(c, tp); 1017: if (CCEQ(tp->t_eofc,c) && t_flags&ECHO) { 1018: i = MIN(2, tp->t_col - i); 1019: while (i > 0) { 1020: (void) ttyoutput('\b', tp); 1021: i--; 1022: } 1023: } 1024: } 1025: endcase: 1026: /* 1027: * If DEC-style start/stop is enabled don't restart 1028: * output until seeing the start character. 1029: */ 1030: if (t_flags&DECCTQ && tp->t_state&TS_TTSTOP && 1031: tp->t_startc != tp->t_stopc) 1032: return; 1033: restartoutput: 1034: tp->t_state &= ~TS_TTSTOP; 1035: tp->t_flags &= ~FLUSHO; 1036: startoutput: 1037: ttstart(tp); 1038: } 1039: 1040: /* 1041: * Put character on TTY output queue, adding delays, 1042: * expanding tabs, and handling the CR/NL bit. 1043: * This is called both from the top half for output, 1044: * and from interrupt level for echoing. 1045: * The arguments are the character and the tty structure. 1046: * Returns < 0 if putc succeeds, otherwise returns char to resend 1047: */ 1048: ttyoutput(c, tp) 1049: register int c; 1050: register struct tty *tp; 1051: { 1052: register int col; 1053: 1054: if (tp->t_flags & (RAW|LITOUT)) { 1055: if (tp->t_flags&FLUSHO) 1056: return (-1); 1057: if (putc(c, &tp->t_outq)) 1058: return(c); 1059: #ifdef UCB_METER 1060: tk_nout++; 1061: #endif 1062: return(-1); 1063: } 1064: 1065: c &= 0177; 1066: #ifdef whybother 1067: /* 1068: * Ignore EOT in normal mode to avoid 1069: * hanging up certain terminals. 1070: */ 1071: if (c == CEOT && (tp->t_flags&CBREAK) == 0) 1072: return(-1); 1073: #endif 1074: /* 1075: * Turn tabs to spaces as required 1076: */ 1077: if (c == '\t' && (tp->t_flags&XTABS)) { 1078: register int s; 1079: 1080: c = 8 - (tp->t_col&7); 1081: if ((tp->t_flags&FLUSHO) == 0) { 1082: s = spltty(); /* don't interrupt tabs */ 1083: c -= b_to_q(" ", c, &tp->t_outq); 1084: #ifdef UCB_METER 1085: tk_nout += c; 1086: #endif 1087: splx(s); 1088: } 1089: tp->t_col += c; 1090: return (c ? -1 : '\t'); 1091: } 1092: #ifdef UCB_METER 1093: tk_nout++; 1094: #endif 1095: /* 1096: * turn <nl> to <cr><lf> if desired. 1097: */ 1098: if (c == '\n' && tp->t_flags&CRMOD) 1099: { 1100: if (putc('\r', &tp->t_outq)) 1101: return(c); 1102: #ifdef UCB_METER 1103: tk_nout++; 1104: #endif 1105: } 1106: if ((tp->t_flags&FLUSHO) == 0 && putc(c, &tp->t_outq)) 1107: return (c); 1108: 1109: col = tp->t_col; 1110: switch (partab[c]&077) { 1111: 1112: case ORDINARY: 1113: col++; 1114: case CONTROL: 1115: break; 1116: case BACKSPACE: 1117: if (col) 1118: col--; 1119: break; 1120: case NEWLINE: 1121: case RETURN: 1122: col = 0; 1123: break; 1124: case TAB: 1125: col = (col | 07) + 1; 1126: break; 1127: } 1128: tp->t_col = col; 1129: return(-1); 1130: } 1131: 1132: /* 1133: * Called from device's read routine after it has 1134: * calculated the tty-structure given as argument. 1135: */ 1136: ttread(tp, uio, flag) 1137: register struct tty *tp; 1138: struct uio *uio; 1139: { 1140: register struct clist *qp; 1141: register int c; 1142: long t_flags; 1143: int s, first, error = 0, carrier; 1144: 1145: loop: 1146: /* 1147: * Take any pending input first. 1148: */ 1149: s = spltty(); 1150: if (tp->t_flags&PENDIN) 1151: ttypend(tp); 1152: splx(s); 1153: 1154: /* 1155: * Hang process if it's in the background. 1156: */ 1157: if (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) { 1158: if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) || 1159: (u.u_procp->p_sigmask & sigmask(SIGTTIN)) || 1160: u.u_procp->p_flag&SVFORK) 1161: return (EIO); 1162: gsignal(u.u_procp->p_pgrp, SIGTTIN); 1163: sleep((caddr_t)&lbolt, TTIPRI); 1164: goto loop; 1165: } 1166: t_flags = tp->t_flags; 1167: 1168: /* 1169: * In raw mode take characters directly from the 1170: * raw queue w/o processing. Interlock against 1171: * device interrupts when interrogating rawq. 1172: */ 1173: if (t_flags&RAW) { 1174: s = spltty(); 1175: if (tp->t_rawq.c_cc <= 0) { 1176: carrier = ISSET(tp->t_state, TS_CARR_ON); 1177: if (!carrier && ISSET(tp->t_state, TS_ISOPEN)) 1178: { 1179: splx(s); 1180: return(0); /* EOF */ 1181: } 1182: if (flag & IO_NDELAY) 1183: { 1184: splx(s); 1185: return(EWOULDBLOCK); 1186: } 1187: sleep((caddr_t)&tp->t_rawq, TTIPRI); 1188: splx(s); 1189: goto loop; 1190: } 1191: splx(s); 1192: while (!error && tp->t_rawq.c_cc && uio->uio_resid) 1193: error = ureadc(getc(&tp->t_rawq), uio); 1194: goto checktandem; 1195: } 1196: 1197: /* 1198: * In cbreak mode use the rawq, otherwise 1199: * take characters from the canonicalized q. 1200: */ 1201: qp = t_flags&CBREAK ? &tp->t_rawq : &tp->t_canq; 1202: 1203: /* 1204: * No input, sleep on rawq awaiting hardware 1205: * receipt and notification. 1206: */ 1207: s = spltty(); 1208: if (qp->c_cc <= 0) { 1209: carrier = ISSET(tp->t_state, TS_CARR_ON); 1210: if (!carrier && ISSET(tp->t_state,TS_ISOPEN)) 1211: { 1212: splx(s); 1213: return(0); /* EOF */ 1214: } 1215: if (flag & IO_NDELAY) 1216: { 1217: splx(s); 1218: return(EWOULDBLOCK); 1219: } 1220: sleep((caddr_t)&tp->t_rawq, TTIPRI); 1221: splx(s); 1222: goto loop; 1223: } 1224: splx(s); 1225: 1226: /* 1227: * Input present, perform input mapping 1228: * and processing (we're not in raw mode). 1229: */ 1230: first = 1; 1231: while ((c = getc(qp)) >= 0) { 1232: if (t_flags&CRMOD && c == '\r') 1233: c = '\n'; 1234: /* 1235: * Check for delayed suspend character. 1236: */ 1237: if (tp->t_line == NTTYDISC && CCEQ(tp->t_dsuspc,c)) { 1238: gsignal(tp->t_pgrp, SIGTSTP); 1239: if (first) { 1240: sleep((caddr_t)&lbolt, TTIPRI); 1241: goto loop; 1242: } 1243: break; 1244: } 1245: /* 1246: * Interpret EOF only in cooked mode. 1247: */ 1248: if (CCEQ(tp->t_eofc,c) && (t_flags&CBREAK) == 0) 1249: break; 1250: /* 1251: * Give user character. 1252: */ 1253: error = ureadc(t_flags&PASS8 ? c : c & 0177, uio); 1254: if (error) 1255: break; 1256: if (uio->uio_resid == 0) 1257: break; 1258: /* 1259: * In cooked mode check for a "break character" 1260: * marking the end of a "line of input". 1261: */ 1262: if ((t_flags&CBREAK) == 0 && ttbreakc(c, tp)) 1263: break; 1264: first = 0; 1265: } 1266: 1267: checktandem: 1268: /* 1269: * Look to unblock output now that (presumably) 1270: * the input queue has gone down. 1271: */ 1272: s = spltty(); 1273: if (ISSET(tp->t_state,TS_TBLOCK) && tp->t_rawq.c_cc < TTYUNBLOCK) 1274: ttyunblock(tp); 1275: splx(s); 1276: return(error); 1277: } 1278: 1279: /* 1280: * Check the output queue on tp for space for a kernel message 1281: * (from uprintf/tprintf). Allow some space over the normal 1282: * hiwater mark so we don't lose messages due to normal flow 1283: * control, but don't let the tty run amok. 1284: * Sleeps here are not interruptible, but we return prematurely 1285: * if new signals come in. 1286: */ 1287: ttycheckoutq(tp, wait) 1288: register struct tty *tp; 1289: int wait; 1290: { 1291: int hiwat, s, oldsig; 1292: 1293: hiwat = TTHIWAT(tp); 1294: s = spltty(); 1295: oldsig = u.u_procp->p_sig; 1296: if (tp->t_outq.c_cc > hiwat + 200) 1297: while (tp->t_outq.c_cc > hiwat) { 1298: ttstart(tp); 1299: if (wait == 0 || u.u_procp->p_sig != oldsig) { 1300: splx(s); 1301: return(0); 1302: } 1303: timeout(wakeup, (caddr_t)&tp->t_outq, hz); 1304: tp->t_state |= TS_ASLEEP; 1305: sleep((caddr_t)&tp->t_outq, PZERO - 1); 1306: } 1307: splx(s); 1308: return(1); 1309: } 1310: 1311: /* 1312: * Called from the device's write routine after it has 1313: * calculated the tty-structure given as argument. 1314: */ 1315: ttwrite(tp, uio, flag) 1316: register struct tty *tp; 1317: register struct uio *uio; 1318: { 1319: char *cp; 1320: register int cc, ce, c; 1321: int i, hiwat, cnt, error, s; 1322: char obuf[OBUFSIZ]; 1323: 1324: hiwat = TTHIWAT(tp); 1325: cnt = uio->uio_resid; 1326: error = 0; 1327: cc = 0; 1328: loop: 1329: s = spltty(); 1330: if (!(tp->t_state&TS_CARR_ON)) { 1331: if (tp->t_state & TS_ISOPEN) { 1332: splx(s); 1333: return(EIO); 1334: } else if (flag & IO_NDELAY) { 1335: splx(s); 1336: error = EWOULDBLOCK; 1337: goto out; 1338: } else { 1339: /* Sleep awaiting carrier. */ 1340: sleep((caddr_t)&tp->t_rawq, TTIPRI); 1341: goto loop; 1342: } 1343: } 1344: splx(s); 1345: /* 1346: * Hang the process if it's in the background. 1347: */ 1348: if (u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp && 1349: (tp->t_flags&TOSTOP) && (u.u_procp->p_flag&SVFORK)==0 && 1350: !(u.u_procp->p_sigignore & sigmask(SIGTTOU)) && 1351: !(u.u_procp->p_sigmask & sigmask(SIGTTOU))) { 1352: gsignal(u.u_procp->p_pgrp, SIGTTOU); 1353: sleep((caddr_t)&lbolt, TTIPRI); 1354: goto loop; 1355: } 1356: 1357: /* 1358: * Process the user's data in at most OBUFSIZ 1359: * chunks. Perform lower case simulation and 1360: * similar hacks. Keep track of high water 1361: * mark, sleep on overflow awaiting device aid 1362: * in acquiring new space. 1363: */ 1364: while (uio->uio_resid || cc > 0) { 1365: if (tp->t_flags&FLUSHO) { 1366: uio->uio_resid = 0; 1367: return(0); 1368: } 1369: if (tp->t_outq.c_cc > hiwat) 1370: goto ovhiwat; 1371: /* 1372: * Grab a hunk of data from the user, unless we have some 1373: * leftover from last time. 1374: */ 1375: if (cc == 0) { 1376: cc = MIN(uio->uio_resid, OBUFSIZ); 1377: cp = obuf; 1378: error = uiomove(cp, cc, uio); 1379: if (error) { 1380: cc = 0; 1381: break; 1382: } 1383: } 1384: /* 1385: * If nothing fancy need be done, grab those characters we 1386: * can handle without any of ttyoutput's processing and 1387: * just transfer them to the output q. For those chars 1388: * which require special processing (as indicated by the 1389: * bits in partab), call ttyoutput. After processing 1390: * a hunk of data, look for FLUSHO so ^O's will take effect 1391: * immediately. 1392: */ 1393: while (cc > 0) { 1394: if (tp->t_flags & (RAW|LITOUT)) 1395: ce = cc; 1396: else { 1397: ce = cc - scanc((unsigned)cc, (caddr_t)cp, 1398: (caddr_t)partab, 077); 1399: /* 1400: * If ce is zero, then we're processing 1401: * a special character through ttyoutput. 1402: */ 1403: if (ce == 0) { 1404: tp->t_rocount = 0; 1405: if (ttyoutput(*cp, tp) >= 0) { 1406: /* no c-lists, wait a bit */ 1407: ttstart(tp); 1408: sleep((caddr_t)&lbolt, TTOPRI); 1409: goto loop; 1410: } 1411: cp++, cc--; 1412: if (tp->t_flags&FLUSHO || 1413: tp->t_outq.c_cc > hiwat) 1414: goto ovhiwat; 1415: continue; 1416: } 1417: } 1418: /* 1419: * A bunch of normal characters have been found, 1420: * transfer them en masse to the output queue and 1421: * continue processing at the top of the loop. 1422: * If there are any further characters in this 1423: * <= OBUFSIZ chunk, the first should be a character 1424: * requiring special handling by ttyoutput. 1425: */ 1426: tp->t_rocount = 0; 1427: i = b_to_q(cp, ce, &tp->t_outq); 1428: ce -= i; 1429: tp->t_col += ce; 1430: cp += ce, cc -= ce; 1431: #ifdef UCB_METER 1432: tk_nout += ce; 1433: #endif 1434: if (i > 0) { 1435: /* out of c-lists, wait a bit */ 1436: ttstart(tp); 1437: sleep((caddr_t)&lbolt, TTOPRI); 1438: goto loop; 1439: } 1440: if (tp->t_flags&FLUSHO || tp->t_outq.c_cc > hiwat) 1441: break; 1442: } /* while (cc > 0) */ 1443: ttstart(tp); 1444: } /* while (uio->uio_resid || cc > 0) */ 1445: out: 1446: /* 1447: * If cc is nonzero, we leave the uio structure inconsistent, as the 1448: * offset and iov pointers have moved forward, but it doesn't matter 1449: * (the call will either return short or restart with a new uio). 1450: */ 1451: uio->uio_resid += cc; 1452: return (error); 1453: 1454: ovhiwat: 1455: s = spltty(); 1456: /* 1457: * This can only occur if FLUSHO is also set in t_flags, 1458: * or if ttstart/oproc is synchronous (or very fast). 1459: */ 1460: if (tp->t_outq.c_cc <= hiwat) { 1461: splx(s); 1462: goto loop; 1463: } 1464: ttstart(tp); 1465: if (flag & IO_NDELAY) { 1466: splx(s); 1467: uio->uio_resid += cc; 1468: return (uio->uio_resid == cnt ? EWOULDBLOCK : 0); 1469: } 1470: tp->t_state |= TS_ASLEEP; 1471: sleep((caddr_t)&tp->t_outq, TTOPRI); 1472: splx(s); 1473: goto loop; 1474: } 1475: 1476: /* 1477: * Rubout one character from the rawq of tp 1478: * as cleanly as possible. 1479: */ 1480: ttyrub(c, tp) 1481: register int c; 1482: register struct tty *tp; 1483: { 1484: register char *cp; 1485: int savecol; 1486: int s; 1487: 1488: if ((tp->t_flags&ECHO) == 0) 1489: return; 1490: tp->t_flags &= ~FLUSHO; 1491: c &= 0377; 1492: if (tp->t_flags&CRTBS) { 1493: if (tp->t_rocount == 0) { 1494: /* 1495: * Screwed by ttwrite; retype 1496: */ 1497: ttyretype(tp); 1498: return; 1499: } 1500: /* 1501: * Out of the ENTIRE tty subsystem would believe this is the ONLY place 1502: * that the "9th" bit (quoted chars) is tested? 1503: */ 1504: if (c == ('\t'|0200) || c == ('\n'|0200)) 1505: ttyrubo(tp, 2); 1506: else switch (partab[c&=0177]&0177) { 1507: 1508: case ORDINARY: 1509: ttyrubo(tp, 1); 1510: break; 1511: 1512: case VTAB: 1513: case BACKSPACE: 1514: case CONTROL: 1515: case RETURN: 1516: if (tp->t_flags&CTLECH) 1517: ttyrubo(tp, 2); 1518: break; 1519: 1520: case TAB: 1521: if (tp->t_rocount < tp->t_rawq.c_cc) { 1522: ttyretype(tp); 1523: return; 1524: } 1525: s = spltty(); 1526: savecol = tp->t_col; 1527: tp->t_state |= TS_CNTTB; 1528: tp->t_flags |= FLUSHO; 1529: tp->t_col = tp->t_rocol; 1530: cp = tp->t_rawq.c_cf; 1531: #ifdef UCB_CLIST 1532: { 1533: char store; 1534: 1535: if (cp) 1536: store = lookc(cp); 1537: for (; cp; cp = nextc(&tp->t_rawq, cp, &store)) 1538: ttyecho(store, tp); 1539: } 1540: #else 1541: for (; cp; cp = nextc(&tp->t_rawq, cp)) 1542: ttyecho(*cp, tp); 1543: #endif 1544: tp->t_flags &= ~FLUSHO; 1545: tp->t_state &= ~TS_CNTTB; 1546: splx(s); 1547: /* 1548: * savecol will now be length of the tab 1549: */ 1550: savecol -= tp->t_col; 1551: tp->t_col += savecol; 1552: if (savecol > 8) 1553: savecol = 8; /* overflow screw */ 1554: while (--savecol >= 0) 1555: (void) ttyoutput('\b', tp); 1556: break; 1557: 1558: default: 1559: panic("ttyrub"); 1560: } 1561: } else if (tp->t_flags&PRTERA) { 1562: if ((tp->t_state&TS_ERASE) == 0) { 1563: (void) ttyoutput('\\', tp); 1564: tp->t_state |= TS_ERASE; 1565: } 1566: ttyecho(c, tp); 1567: } else 1568: ttyecho(tp->t_erase, tp); 1569: tp->t_rocount--; 1570: } 1571: 1572: /* 1573: * Crt back over cnt chars perhaps 1574: * erasing them. 1575: */ 1576: ttyrubo(tp, cnt) 1577: register struct tty *tp; 1578: register int cnt; 1579: { 1580: register char *rubostring = tp->t_flags&CRTERA ? "\b \b" : "\b"; 1581: 1582: while (--cnt >= 0) 1583: ttyout(rubostring, tp); 1584: } 1585: 1586: /* 1587: * Reprint the rawq line. 1588: * We assume c_cc has already been checked. 1589: */ 1590: ttyretype(tp) 1591: register struct tty *tp; 1592: { 1593: register char *cp; 1594: int s; 1595: 1596: if (tp->t_rprntc != _POSIX_VDISABLE) 1597: ttyecho(tp->t_rprntc, tp); 1598: (void) ttyoutput('\n', tp); 1599: s = spltty(); 1600: #ifdef UCB_CLIST 1601: { 1602: char store; 1603: 1604: if (cp = tp->t_canq.c_cf) 1605: store = lookc(cp); 1606: for (; cp; cp = nextc(&tp->t_canq, cp, &store)) 1607: ttyecho(store, tp); 1608: if (cp = tp->t_rawq.c_cf) 1609: store = lookc(cp); 1610: for (; cp; cp = nextc(&tp->t_rawq, cp, &store)) 1611: ttyecho(store, tp); 1612: } 1613: #else 1614: for (cp = tp->t_canq.c_cf; cp; cp = nextc(&tp->t_canq, cp)) 1615: ttyecho(*cp, tp); 1616: for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp)) 1617: ttyecho(*cp, tp); 1618: #endif 1619: tp->t_state &= ~TS_ERASE; 1620: splx(s); 1621: tp->t_rocount = tp->t_rawq.c_cc; 1622: tp->t_rocol = 0; 1623: } 1624: 1625: /* 1626: * Echo a typed character to the terminal 1627: */ 1628: ttyecho(c, tp) 1629: register int c; 1630: register struct tty *tp; 1631: { 1632: register int c7; 1633: 1634: if ((tp->t_state&TS_CNTTB) == 0) 1635: tp->t_flags &= ~FLUSHO; 1636: if ((tp->t_flags&ECHO) == 0) 1637: return; 1638: c &= 0377; 1639: 1640: if (tp->t_flags&RAW) { 1641: (void) ttyoutput(c, tp); 1642: return; 1643: } 1644: if (c == '\r' && tp->t_flags&CRMOD) 1645: c = '\n'; 1646: c7 = c & 0177; 1647: if (tp->t_flags&CTLECH) { 1648: if (c7 <= 037 && c != '\t' && c != '\n' || c7 == 0177) { 1649: (void) ttyoutput('^', tp); 1650: if (c7 == 0177) 1651: c7 = '?'; 1652: else 1653: c7 += 'A' - 1; 1654: } 1655: } 1656: (void) ttyoutput(c7, tp); 1657: } 1658: 1659: /* 1660: * Is c a break char for tp? 1661: */ 1662: ttbreakc(c, tp) 1663: register int c; 1664: register struct tty *tp; 1665: { 1666: return (c == '\n' || CCEQ(tp->t_eofc,c) || CCEQ(tp->t_brkc,c) || 1667: c == '\r' && (tp->t_flags&CRMOD)); 1668: } 1669: 1670: /* 1671: * send string cp to tp 1672: */ 1673: ttyout(cp, tp) 1674: register char *cp; 1675: register struct tty *tp; 1676: { 1677: register int c; 1678: 1679: while (c = *cp++) 1680: (void) ttyoutput(c, tp); 1681: } 1682: 1683: ttwakeup(tp) 1684: register struct tty *tp; 1685: { 1686: 1687: if (tp->t_rsel) { 1688: selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL); 1689: tp->t_state &= ~TS_RCOLL; 1690: tp->t_rsel = 0; 1691: } 1692: if (tp->t_state & TS_ASYNC) 1693: gsignal(tp->t_pgrp, SIGIO); 1694: wakeup((caddr_t)&tp->t_rawq); 1695: }