1: # 2: /* 3: * general TTY subroutines 4: */ 5: #include "../h/param.h" 6: #include "../h/systm.h" 7: #include "../h/dir.h" 8: #include "../h/user.h" 9: #include "../h/tty.h" 10: #include "../h/proc.h" 11: #include "../h/mx.h" 12: #include "../h/inode.h" 13: #include "../h/file.h" 14: #include "../h/reg.h" 15: #include "../h/conf.h" 16: 17: char partab[]; 18: 19: 20: /* 21: * Input mapping table-- if an entry is non-zero, when the 22: * corresponding character is typed preceded by "\" the escape 23: * sequence is replaced by the table value. Mostly used for 24: * upper-case only terminals. 25: */ 26: 27: char maptab[] ={ 28: 000,000,000,000,000,000,000,000, 29: 000,000,000,000,000,000,000,000, 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,'`', 33: '{','}',000,000,000,000,000,000, 34: 000,000,000,000,000,000,000,000, 35: 000,000,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, 40: 000,'A','B','C','D','E','F','G', 41: 'H','I','J','K','L','M','N','O', 42: 'P','Q','R','S','T','U','V','W', 43: 'X','Y','Z',000,000,000,000,000, 44: }; 45: 46: 47: /* 48: * shorthand 49: */ 50: #define q1 tp->t_rawq 51: #define q2 tp->t_canq 52: #define q3 tp->t_outq 53: #define q4 tp->t_un.t_ctlq 54: 55: 56: /* 57: * routine called on first teletype open. 58: * establishes a process group for distribution 59: * of quits and interrupts from the tty. 60: */ 61: ttyopen(dev, tp) 62: dev_t dev; 63: register struct tty *tp; 64: { 65: register struct proc *pp; 66: 67: pp = u.u_procp; 68: tp->t_dev = dev; 69: if(pp->p_pgrp == 0) { 70: u.u_ttyp = tp; 71: u.u_ttyd = dev; 72: if (tp->t_pgrp==0) 73: tp->t_pgrp = pp->p_pid; 74: pp->p_pgrp = tp->t_pgrp; 75: } 76: tp->t_state &= ~WOPEN; 77: tp->t_state |= ISOPEN; 78: } 79: 80: 81: /* 82: * set default control characters. 83: */ 84: ttychars(tp) 85: register struct tty *tp; 86: { 87: tun.t_intrc = CINTR; 88: tun.t_quitc = CQUIT; 89: tun.t_startc = CSTART; 90: tun.t_stopc = CSTOP; 91: tun.t_eofc = CEOT; 92: tun.t_brkc = CBRK; 93: tp->t_erase = CERASE; 94: tp->t_kill = CKILL; 95: } 96: 97: /* 98: * clean tp on last close 99: */ 100: ttyclose(tp) 101: register struct tty *tp; 102: { 103: 104: tp->t_pgrp = 0; 105: wflushtty(tp); 106: tp->t_state = 0; 107: } 108: 109: /* 110: * stty/gtty writearound 111: */ 112: stty() 113: { 114: u.u_arg[2] = u.u_arg[1]; 115: u.u_arg[1] = TIOCSETP; 116: ioctl(); 117: } 118: 119: gtty() 120: { 121: u.u_arg[2] = u.u_arg[1]; 122: u.u_arg[1] = TIOCGETP; 123: ioctl(); 124: } 125: 126: /* 127: * ioctl system call 128: * Check legality, execute common code, and switch out to individual 129: * device routine. 130: */ 131: ioctl() 132: { 133: register struct file *fp; 134: register struct inode *ip; 135: register struct a { 136: int fdes; 137: int cmd; 138: caddr_t cmarg; 139: } *uap; 140: register dev_t dev; 141: register fmt; 142: 143: uap = (struct a *)u.u_ap; 144: if ((fp = getf(uap->fdes)) == NULL) 145: return; 146: if (uap->cmd==FIOCLEX) { 147: u.u_pofile[uap->fdes] |= EXCLOSE; 148: return; 149: } 150: if (uap->cmd==FIONCLEX) { 151: u.u_pofile[uap->fdes] &= ~EXCLOSE; 152: return; 153: } 154: ip = fp->f_inode; 155: fmt = ip->i_mode & IFMT; 156: if (fmt != IFCHR && fmt != IFMPC) { 157: u.u_error = ENOTTY; 158: return; 159: } 160: dev = (dev_t)ip->i_un.i_rdev; 161: (*cdevsw[major(dev)].d_ioctl)(dev, uap->cmd, uap->cmarg, fp->f_flag); 162: } 163: 164: /* 165: * Common code for several tty ioctl commands 166: */ 167: ttioccomm(com, tp, addr, dev) 168: register struct tty *tp; 169: caddr_t addr; 170: { 171: unsigned t; 172: struct ttiocb iocb; 173: extern int nldisp; 174: 175: switch(com) { 176: 177: /* 178: * get discipline number 179: */ 180: case TIOCGETD: 181: t = tp->t_line; 182: if (copyout((caddr_t)&t, addr, sizeof(t))) 183: u.u_error = EFAULT; 184: break; 185: 186: /* 187: * set line discipline 188: */ 189: case TIOCSETD: 190: if (copyin(addr, (caddr_t)&t, sizeof(t))) { 191: u.u_error = EFAULT; 192: break; 193: } 194: if (t >= nldisp) { 195: u.u_error = ENXIO; 196: break; 197: } 198: if (tp->t_line) 199: (*linesw[tp->t_line].l_close)(tp); 200: if (t) 201: (*linesw[t].l_open)(dev, tp, addr); 202: if (u.u_error==0) 203: tp->t_line = t; 204: break; 205: 206: /* 207: * prevent more opens on channel 208: */ 209: case TIOCEXCL: 210: tp->t_state |= XCLUDE; 211: break; 212: case TIOCNXCL: 213: tp->t_state &= ~XCLUDE; 214: break; 215: 216: /* 217: * Set new parameters 218: */ 219: case TIOCSETP: 220: wflushtty(tp); 221: case TIOCSETN: 222: if (copyin(addr, (caddr_t)&iocb, sizeof(iocb))) { 223: u.u_error = EFAULT; 224: return(1); 225: } 226: tp->t_ispeed = iocb.ioc_ispeed; 227: tp->t_ospeed = iocb.ioc_ospeed; 228: tp->t_erase = iocb.ioc_erase; 229: tp->t_kill = iocb.ioc_kill; 230: tp->t_flags = iocb.ioc_flags; 231: break; 232: 233: /* 234: * send current parameters to user 235: */ 236: case TIOCGETP: 237: iocb.ioc_ispeed = tp->t_ispeed; 238: iocb.ioc_ospeed = tp->t_ospeed; 239: iocb.ioc_erase = tp->t_erase; 240: iocb.ioc_kill = tp->t_kill; 241: iocb.ioc_flags = tp->t_flags; 242: if (copyout((caddr_t)&iocb, addr, sizeof(iocb))) 243: u.u_error = EFAULT; 244: break; 245: 246: /* 247: * Hang up line on last close 248: */ 249: 250: case TIOCHPCL: 251: tp->t_state |= HUPCLS; 252: break; 253: 254: case TIOCFLUSH: 255: flushtty(tp); 256: break; 257: 258: /* 259: * ioctl entries to line discipline 260: */ 261: case DIOCSETP: 262: case DIOCGETP: 263: (*linesw[tp->t_line].l_ioctl)(com, tp, addr); 264: break; 265: 266: /* 267: * set and fetch special characters 268: */ 269: case TIOCSETC: 270: if (copyin(addr, (caddr_t)&tun, sizeof(struct tc))) 271: u.u_error = EFAULT; 272: break; 273: 274: case TIOCGETC: 275: if (copyout((caddr_t)&tun, addr, sizeof(struct tc))) 276: u.u_error = EFAULT; 277: break; 278: 279: default: 280: return(0); 281: } 282: return(1); 283: } 284: 285: /* 286: * Wait for output to drain, then flush input waiting. 287: */ 288: wflushtty(tp) 289: register struct tty *tp; 290: { 291: 292: spl5(); 293: while (tp->t_outq.c_cc && tp->t_state&CARR_ON) { 294: (*tp->t_oproc)(tp); 295: tp->t_state |= ASLEEP; 296: sleep((caddr_t)&tp->t_outq, TTOPRI); 297: } 298: flushtty(tp); 299: spl0(); 300: } 301: 302: /* 303: * flush all TTY queues 304: */ 305: flushtty(tp) 306: register struct tty *tp; 307: { 308: register s; 309: 310: while (getc(&tp->t_canq) >= 0) 311: ; 312: wakeup((caddr_t)&tp->t_rawq); 313: wakeup((caddr_t)&tp->t_outq); 314: s = spl6(); 315: tp->t_state &= ~TTSTOP; 316: (*cdevsw[major(tp->t_dev)].d_stop)(tp); 317: while (getc(&tp->t_outq) >= 0) 318: ; 319: while (getc(&tp->t_rawq) >= 0) 320: ; 321: tp->t_delct = 0; 322: splx(s); 323: } 324: 325: 326: 327: /* 328: * transfer raw input list to canonical list, 329: * doing erase-kill processing and handling escapes. 330: * It waits until a full line has been typed in cooked mode, 331: * or until any character has been typed in raw mode. 332: */ 333: canon(tp) 334: register struct tty *tp; 335: { 336: register char *bp; 337: char *bp1; 338: register int c; 339: int mc; 340: 341: spl5(); 342: while ((tp->t_flags&(RAW|CBREAK))==0 && tp->t_delct==0 343: || (tp->t_flags&(RAW|CBREAK))!=0 && tp->t_rawq.c_cc==0) { 344: if ((tp->t_state&CARR_ON)==0 || tp->t_chan!=NULL) { 345: return(0); 346: } 347: sleep((caddr_t)&tp->t_rawq, TTIPRI); 348: } 349: spl0(); 350: loop: 351: bp = &canonb[2]; 352: while ((c=getc(&tp->t_rawq)) >= 0) { 353: if ((tp->t_flags&(RAW|CBREAK))==0) { 354: if (c==0377) { 355: tp->t_delct--; 356: break; 357: } 358: if (bp[-1]!='\\') { 359: if (c==tp->t_erase) { 360: if (bp > &canonb[2]) 361: bp--; 362: continue; 363: } 364: if (c==tp->t_kill) 365: goto loop; 366: if (c==tun.t_eofc) 367: continue; 368: } else { 369: mc = maptab[c]; 370: if (c==tp->t_erase || c==tp->t_kill) 371: mc = c; 372: if (mc && (mc==c || (tp->t_flags&LCASE))) { 373: if (bp[-2] != '\\') 374: c = mc; 375: bp--; 376: } 377: } 378: } 379: *bp++ = c; 380: if (bp>=canonb+CANBSIZ) 381: break; 382: } 383: bp1 = &canonb[2]; 384: b_to_q(bp1, bp-bp1, &tp->t_canq); 385: 386: if (tp->t_state&TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) { 387: if (putc(tun.t_startc, &tp->t_outq)==0) { 388: tp->t_state &= ~TBLOCK; 389: ttstart(tp); 390: } 391: tp->t_char = 0; 392: } 393: 394: return(bp-bp1); 395: } 396: 397: 398: /* 399: * block transfer input handler. 400: */ 401: ttyrend(tp, pb, pe) 402: register struct tty *tp; 403: register char *pb, *pe; 404: { 405: int tandem; 406: 407: tandem = tp->t_flags&TANDEM; 408: if (tp->t_flags&RAW) { 409: b_to_q(pb, pe-pb, &tp->t_rawq); 410: if (tp->t_chan) 411: sdata(tp->t_chan); else 412: wakeup((caddr_t)&tp->t_rawq); 413: } else { 414: tp->t_flags &= ~TANDEM; 415: while (pb < pe) 416: ttyinput(*pb++, tp); 417: tp->t_flags |= tandem; 418: } 419: if (tandem) 420: ttyblock(tp); 421: } 422: 423: /* 424: * Place a character on raw TTY input queue, putting in delimiters 425: * and waking up top half as needed. 426: * Also echo if required. 427: * The arguments are the character and the appropriate 428: * tty structure. 429: */ 430: ttyinput(c, tp) 431: register c; 432: register struct tty *tp; 433: { 434: register int t_flags; 435: register struct chan *cp; 436: 437: tk_nin += 1; 438: c &= 0377; 439: t_flags = tp->t_flags; 440: if (t_flags&TANDEM) 441: ttyblock(tp); 442: if ((t_flags&RAW)==0) { 443: c &= 0177; 444: if (tp->t_state&TTSTOP) { 445: if (c==tun.t_startc) { 446: tp->t_state &= ~TTSTOP; 447: ttstart(tp); 448: return; 449: } 450: if (c==tun.t_stopc) 451: return; 452: tp->t_state &= ~TTSTOP; 453: ttstart(tp); 454: } else { 455: if (c==tun.t_stopc) { 456: tp->t_state |= TTSTOP; 457: (*cdevsw[major(tp->t_dev)].d_stop)(tp); 458: return; 459: } 460: if (c==tun.t_startc) 461: return; 462: } 463: if (c==tun.t_quitc || c==tun.t_intrc) { 464: flushtty(tp); 465: c = (c==tun.t_intrc) ? SIGINT:SIGQUIT; 466: if (tp->t_chan) 467: scontrol(tp->t_chan, M_SIG, c); 468: else 469: signal(tp->t_pgrp, c); 470: return; 471: } 472: if (c=='\r' && t_flags&CRMOD) 473: c = '\n'; 474: } 475: if (tp->t_rawq.c_cc>TTYHOG) { 476: flushtty(tp); 477: return; 478: } 479: if (t_flags&LCASE && c>='A' && c<='Z') 480: c += 'a'-'A'; 481: putc(c, &tp->t_rawq); 482: if (t_flags&(RAW|CBREAK)||(c=='\n'||c==tun.t_eofc||c==tun.t_brkc)) { 483: if ((t_flags&(RAW|CBREAK))==0 && putc(0377, &tp->t_rawq)==0) 484: tp->t_delct++; 485: if ((cp=tp->t_chan)!=NULL) 486: sdata(cp); else 487: wakeup((caddr_t)&tp->t_rawq); 488: } 489: if (t_flags&ECHO) { 490: ttyoutput(c, tp); 491: if (c==tp->t_kill && (t_flags&(RAW|CBREAK))==0) 492: ttyoutput('\n', tp); 493: ttstart(tp); 494: } 495: } 496: 497: 498: /* 499: * Send stop character on input overflow. 500: */ 501: ttyblock(tp) 502: register struct tty *tp; 503: { 504: register x; 505: x = q1.c_cc + q2.c_cc; 506: if (q1.c_cc > TTYHOG) { 507: flushtty(tp); 508: tp->t_state &= ~TBLOCK; 509: } 510: if (x >= TTYHOG/2) { 511: if (putc(tun.t_stopc, &tp->t_outq)==0) { 512: tp->t_state |= TBLOCK; 513: tp->t_char++; 514: ttstart(tp); 515: } 516: } 517: } 518: 519: /* 520: * put character on TTY output queue, adding delays, 521: * expanding tabs, and handling the CR/NL bit. 522: * It is called both from the top half for output, and from 523: * interrupt level for echoing. 524: * The arguments are the character and the tty structure. 525: */ 526: ttyoutput(c, tp) 527: register c; 528: register struct tty *tp; 529: { 530: register char *colp; 531: register ctype; 532: 533: tk_nout += 1; 534: /* 535: * Ignore EOT in normal mode to avoid hanging up 536: * certain terminals. 537: * In raw mode dump the char unchanged. 538: */ 539: 540: if ((tp->t_flags&RAW)==0) { 541: c &= 0177; 542: if (c==CEOT) 543: return; 544: } else { 545: putc(c, &tp->t_outq); 546: return; 547: } 548: 549: /* 550: * Turn tabs to spaces as required 551: */ 552: if (c=='\t' && (tp->t_flags&TBDELAY)==XTABS) { 553: c = 8; 554: do 555: ttyoutput(' ', tp); 556: while (--c >= 0 && tp->t_col&07); 557: return; 558: } 559: /* 560: * for upper-case-only terminals, 561: * generate escapes. 562: */ 563: if (tp->t_flags&LCASE) { 564: colp = "({)}!|^~'`"; 565: while(*colp++) 566: if(c == *colp++) { 567: ttyoutput('\\', tp); 568: c = colp[-2]; 569: break; 570: } 571: if ('a'<=c && c<='z') 572: c += 'A' - 'a'; 573: } 574: /* 575: * turn <nl> to <cr><lf> if desired. 576: */ 577: if (c=='\n' && tp->t_flags&CRMOD) 578: ttyoutput('\r', tp); 579: putc(c, &tp->t_outq); 580: /* 581: * Calculate delays. 582: * The numbers here represent clock ticks 583: * and are not necessarily optimal for all terminals. 584: * The delays are indicated by characters above 0200. 585: * In raw mode there are no delays and the 586: * transmission path is 8 bits wide. 587: */ 588: colp = &tp->t_col; 589: ctype = partab[c]; 590: c = 0; 591: switch (ctype&077) { 592: 593: /* ordinary */ 594: case 0: 595: (*colp)++; 596: 597: /* non-printing */ 598: case 1: 599: break; 600: 601: /* backspace */ 602: case 2: 603: if (*colp) 604: (*colp)--; 605: break; 606: 607: /* newline */ 608: case 3: 609: ctype = (tp->t_flags >> 8) & 03; 610: if(ctype == 1) { /* tty 37 */ 611: if (*colp) 612: c = max(((unsigned)*colp>>4) + 3, (unsigned)6); 613: } else 614: if(ctype == 2) { /* vt05 */ 615: c = 6; 616: } 617: *colp = 0; 618: break; 619: 620: /* tab */ 621: case 4: 622: ctype = (tp->t_flags >> 10) & 03; 623: if(ctype == 1) { /* tty 37 */ 624: c = 1 - (*colp | ~07); 625: if(c < 5) 626: c = 0; 627: } 628: *colp |= 07; 629: (*colp)++; 630: break; 631: 632: /* vertical motion */ 633: case 5: 634: if(tp->t_flags & VTDELAY) /* tty 37 */ 635: c = 0177; 636: break; 637: 638: /* carriage return */ 639: case 6: 640: ctype = (tp->t_flags >> 12) & 03; 641: if(ctype == 1) { /* tn 300 */ 642: c = 5; 643: } else if(ctype == 2) { /* ti 700 */ 644: c = 10; 645: } 646: *colp = 0; 647: } 648: if(c) 649: putc(c|0200, &tp->t_outq); 650: } 651: 652: /* 653: * Restart typewriter output following a delay 654: * timeout. 655: * The name of the routine is passed to the timeout 656: * subroutine and it is called during a clock interrupt. 657: */ 658: ttrstrt(tp) 659: register struct tty *tp; 660: { 661: 662: tp->t_state &= ~TIMEOUT; 663: ttstart(tp); 664: } 665: 666: /* 667: * Start output on the typewriter. It is used from the top half 668: * after some characters have been put on the output queue, 669: * from the interrupt routine to transmit the next 670: * character, and after a timeout has finished. 671: */ 672: ttstart(tp) 673: register struct tty *tp; 674: { 675: register s; 676: 677: s = spl5(); 678: if((tp->t_state&(TIMEOUT|TTSTOP|BUSY)) == 0) 679: (*tp->t_oproc)(tp); 680: splx(s); 681: } 682: 683: /* 684: * Called from device's read routine after it has 685: * calculated the tty-structure given as argument. 686: */ 687: ttread(tp) 688: register struct tty *tp; 689: { 690: 691: if ((tp->t_state&CARR_ON)==0) 692: return(0); 693: if (tp->t_canq.c_cc || canon(tp)) 694: while (tp->t_canq.c_cc && passc(getc(&tp->t_canq))>=0) 695: ; 696: return(tp->t_rawq.c_cc + tp->t_canq.c_cc); 697: } 698: 699: /* 700: * Called from the device's write routine after it has 701: * calculated the tty-structure given as argument. 702: */ 703: caddr_t 704: ttwrite(tp) 705: register struct tty *tp; 706: { 707: register c; 708: 709: if ((tp->t_state&CARR_ON)==0) 710: return(NULL); 711: while (u.u_count) { 712: spl5(); 713: while (tp->t_outq.c_cc > TTHIWAT) { 714: ttstart(tp); 715: tp->t_state |= ASLEEP; 716: if (tp->t_chan) 717: return((caddr_t)&tp->t_outq); 718: sleep((caddr_t)&tp->t_outq, TTOPRI); 719: } 720: spl0(); 721: if ((c = cpass()) < 0) 722: break; 723: ttyoutput(c, tp); 724: } 725: ttstart(tp); 726: return(NULL); 727: }