|
|
1.1 ! root 1: /* ttyold.c 4.9 81/07/22 */ ! 2: ! 3: /* ! 4: * general TTY subroutines ! 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: char maptab[]; ! 29: ! 30: #define OBUFSIZ 100 ! 31: ! 32: /* ! 33: * routine called on first teletype open. ! 34: * establishes a process group for distribution ! 35: * of quits and interrupts from the tty. ! 36: */ ! 37: ttyopen(dev, tp) ! 38: dev_t dev; ! 39: register struct tty *tp; ! 40: { ! 41: register struct proc *pp; ! 42: ! 43: pp = u.u_procp; ! 44: tp->t_dev = dev; ! 45: if(pp->p_pgrp == 0) { ! 46: u.u_ttyp = tp; ! 47: u.u_ttyd = dev; ! 48: if (tp->t_pgrp == 0) ! 49: tp->t_pgrp = pp->p_pid; ! 50: pp->p_pgrp = tp->t_pgrp; ! 51: } ! 52: tp->t_state &= ~WOPEN; ! 53: tp->t_state |= ISOPEN; ! 54: tp->t_line = 0; /* conservative */ ! 55: } ! 56: ! 57: /* ! 58: * clean tp on last close ! 59: */ ! 60: ttyclose(tp) ! 61: register struct tty *tp; ! 62: { ! 63: ! 64: tp->t_pgrp = 0; ! 65: wflushtty(tp); ! 66: tp->t_state = 0; ! 67: tp->t_line = 0; ! 68: } ! 69: ! 70: /* ! 71: * transfer raw input list to canonical list, ! 72: * doing erase-kill processing and handling escapes. ! 73: * It waits until a full line has been typed in cooked mode, ! 74: * or until any character has been typed in raw mode. ! 75: */ ! 76: canon(tp) ! 77: register struct tty *tp; ! 78: { ! 79: register char *bp; ! 80: char *bp1; ! 81: register int c; ! 82: int mc; ! 83: int s; ! 84: ! 85: if ((tp->t_flags&(RAW|CBREAK))==0 && tp->t_delct==0 ! 86: || (tp->t_flags&(RAW|CBREAK))!=0 && tp->t_rawq.c_cc==0) { ! 87: return(-1); ! 88: } ! 89: s = spl0(); ! 90: loop: ! 91: bp = &canonb[2]; ! 92: while ((c=getc(&tp->t_rawq)) >= 0) { ! 93: if ((tp->t_flags&(RAW|CBREAK))==0) { ! 94: if (c==0377) { ! 95: tp->t_delct--; ! 96: break; ! 97: } ! 98: if (bp[-1]!='\\') { ! 99: if (c==tp->t_erase) { ! 100: if (bp > &canonb[2]) ! 101: bp--; ! 102: continue; ! 103: } ! 104: if (c==tp->t_kill) ! 105: goto loop; ! 106: if (c==tun.t_eofc) ! 107: continue; ! 108: } else { ! 109: mc = maptab[c]; ! 110: if (c==tp->t_erase || c==tp->t_kill) ! 111: mc = c; ! 112: if (mc && (mc==c || (tp->t_flags&LCASE))) { ! 113: if (bp[-2] != '\\') ! 114: c = mc; ! 115: bp--; ! 116: } ! 117: } ! 118: } ! 119: *bp++ = c; ! 120: if (bp>=canonb+CANBSIZ) ! 121: break; ! 122: } ! 123: bp1 = &canonb[2]; ! 124: (void) b_to_q(bp1, bp-bp1, &tp->t_canq); ! 125: ! 126: if (tp->t_state&TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) { ! 127: if (putc(tun.t_startc, &tp->t_outq)==0) { ! 128: tp->t_state &= ~TBLOCK; ! 129: ttstart(tp); ! 130: } ! 131: tp->t_char = 0; ! 132: } ! 133: ! 134: splx(s); ! 135: return(0); ! 136: } ! 137: ! 138: ! 139: /* ! 140: * block transfer input handler. ! 141: */ ! 142: ttyrend(tp, pb, pe) ! 143: register struct tty *tp; ! 144: register char *pb, *pe; ! 145: { ! 146: int tandem; ! 147: ! 148: tandem = tp->t_flags&TANDEM; ! 149: if (tp->t_flags&RAW) { ! 150: (void) b_to_q(pb, pe-pb, &tp->t_rawq); ! 151: if (tp->t_chan) ! 152: (void) sdata(tp->t_chan); ! 153: wakeup((caddr_t)&tp->t_rawq); ! 154: } else { ! 155: tp->t_flags &= ~TANDEM; ! 156: while (pb < pe) ! 157: ttyinput(*pb++, tp); ! 158: tp->t_flags |= tandem; ! 159: } ! 160: if (tandem) ! 161: ttyblock(tp); ! 162: } ! 163: ! 164: /* ! 165: * Place a character on raw TTY input queue, putting in delimiters ! 166: * and waking up top half as needed. ! 167: * Also echo if required. ! 168: * The arguments are the character and the appropriate ! 169: * tty structure. ! 170: */ ! 171: ttyinput(c, tp) ! 172: register c; ! 173: register struct tty *tp; ! 174: { ! 175: register int t_flags; ! 176: register struct chan *cp; ! 177: ! 178: tk_nin += 1; ! 179: c &= 0377; ! 180: t_flags = tp->t_flags; ! 181: if (t_flags&TANDEM) ! 182: ttyblock(tp); ! 183: if ((t_flags&RAW)==0) { ! 184: c &= 0177; ! 185: if (tp->t_state&TTSTOP) { ! 186: if (c==tun.t_startc) { ! 187: tp->t_state &= ~TTSTOP; ! 188: ttstart(tp); ! 189: return; ! 190: } ! 191: if (c==tun.t_stopc) ! 192: return; ! 193: if ((tp->t_local & LDECCTQ) == 0) { ! 194: tp->t_state &= ~TTSTOP; ! 195: ttstart(tp); ! 196: } ! 197: } else { ! 198: if (c==tun.t_stopc) { ! 199: tp->t_state |= TTSTOP; ! 200: (*cdevsw[major(tp->t_dev)].d_stop)(tp); ! 201: return; ! 202: } ! 203: if (c==tun.t_startc) ! 204: return; ! 205: } ! 206: if (c==tun.t_quitc || c==tun.t_intrc) { ! 207: if ((tp->t_local & LNOFLSH) == 0) ! 208: flushtty(tp, FREAD|FWRITE); ! 209: c = (c==tun.t_intrc) ? SIGINT:SIGQUIT; ! 210: if (tp->t_chan) ! 211: scontrol(tp->t_chan, M_SIG, c); ! 212: gsignal(tp->t_pgrp, c); ! 213: return; ! 214: } ! 215: if (c=='\r' && t_flags&CRMOD) ! 216: c = '\n'; ! 217: } ! 218: if (tp->t_rawq.c_cc>TTYHOG) { ! 219: flushtty(tp, FREAD|FWRITE); ! 220: return; ! 221: } ! 222: if (t_flags&LCASE && c>='A' && c<='Z') ! 223: c += 'a'-'A'; ! 224: (void) putc(c, &tp->t_rawq); ! 225: if (t_flags&(RAW|CBREAK)||(c=='\n'||c==tun.t_eofc||c==tun.t_brkc)) { ! 226: if ((t_flags&(RAW|CBREAK))==0 && putc(0377, &tp->t_rawq)==0) ! 227: tp->t_delct++; ! 228: if ((cp=tp->t_chan)!=NULL) ! 229: (void) sdata(cp); ! 230: wakeup((caddr_t)&tp->t_rawq); ! 231: } ! 232: if (t_flags&ECHO) { ! 233: ttyoutput(c, tp); ! 234: if (c==tp->t_kill && (t_flags&(RAW|CBREAK))==0) ! 235: ttyoutput('\n', tp); ! 236: ttstart(tp); ! 237: } ! 238: } ! 239: ! 240: /* ! 241: * put character on TTY output queue, adding delays, ! 242: * expanding tabs, and handling the CR/NL bit. ! 243: * It is called both from the top half for output, and from ! 244: * interrupt level for echoing. ! 245: * The arguments are the character and the tty structure. ! 246: */ ! 247: ttyoutput(c, tp) ! 248: register c; ! 249: register struct tty *tp; ! 250: { ! 251: register char *colp; ! 252: register ctype; ! 253: ! 254: /* ! 255: * Ignore EOT in normal mode to avoid hanging up ! 256: * certain terminals. ! 257: * In raw mode dump the char unchanged. ! 258: */ ! 259: if ((tp->t_flags&RAW)==0) { ! 260: c &= 0177; ! 261: if ((tp->t_flags&CBREAK)==0 && c==CEOT) ! 262: return; ! 263: } else { ! 264: tk_nout++; ! 265: (void) putc(c, &tp->t_outq); ! 266: return; ! 267: } ! 268: ! 269: /* ! 270: * Turn tabs to spaces as required ! 271: */ ! 272: if (c=='\t' && (tp->t_flags&TBDELAY)==XTABS) { ! 273: c = 8 - (tp->t_col & 7); ! 274: (void) b_to_q(" ", c, &tp->t_outq); ! 275: tp->t_col += c; ! 276: tk_nout += c; ! 277: return; ! 278: } ! 279: tk_nout++; ! 280: /* ! 281: * for upper-case-only terminals, ! 282: * generate escapes. ! 283: */ ! 284: if (tp->t_flags&LCASE) { ! 285: colp = "({)}!|^~'`"; ! 286: while(*colp++) ! 287: if(c == *colp++) { ! 288: ttyoutput('\\', tp); ! 289: c = colp[-2]; ! 290: break; ! 291: } ! 292: if ('a'<=c && c<='z') ! 293: c += 'A' - 'a'; ! 294: } ! 295: /* ! 296: * turn <nl> to <cr><lf> if desired. ! 297: */ ! 298: if (c=='\n' && tp->t_flags&CRMOD) ! 299: ttyoutput('\r', tp); ! 300: (void) putc(c, &tp->t_outq); ! 301: /* ! 302: * Calculate delays. ! 303: * The numbers here represent clock ticks ! 304: * and are not necessarily optimal for all terminals. ! 305: * The delays are indicated by characters above 0200. ! 306: * In raw mode there are no delays and the ! 307: * transmission path is 8 bits wide. ! 308: */ ! 309: colp = &tp->t_col; ! 310: ctype = partab[c]; ! 311: c = 0; ! 312: switch (ctype&077) { ! 313: ! 314: /* ordinary */ ! 315: case 0: ! 316: (*colp)++; ! 317: ! 318: /* non-printing */ ! 319: case 1: ! 320: break; ! 321: ! 322: /* backspace */ ! 323: case 2: ! 324: if (*colp) ! 325: (*colp)--; ! 326: break; ! 327: ! 328: /* newline */ ! 329: case 3: ! 330: ctype = (tp->t_flags >> 8) & 03; ! 331: if(ctype == 1) { /* tty 37 */ ! 332: if (*colp) ! 333: c = max(((unsigned)*colp>>4) + 3, (unsigned)6); ! 334: } else ! 335: if(ctype == 2) { /* vt05 */ ! 336: c = 6; ! 337: } ! 338: *colp = 0; ! 339: break; ! 340: ! 341: /* tab */ ! 342: case 4: ! 343: ctype = (tp->t_flags >> 10) & 03; ! 344: if(ctype == 1) { /* tty 37 */ ! 345: c = 1 - (*colp | ~07); ! 346: if(c < 5) ! 347: c = 0; ! 348: } ! 349: *colp |= 07; ! 350: (*colp)++; ! 351: break; ! 352: ! 353: /* vertical motion */ ! 354: case 5: ! 355: if(tp->t_flags & VTDELAY) /* tty 37 */ ! 356: c = 0177; ! 357: break; ! 358: ! 359: /* carriage return */ ! 360: case 6: ! 361: ctype = (tp->t_flags >> 12) & 03; ! 362: if(ctype == 1) { /* tn 300 */ ! 363: c = 5; ! 364: } else if(ctype == 2) { /* ti 700 */ ! 365: c = 10; ! 366: } else if(ctype == 3) { /* concept 100 */ ! 367: int i; ! 368: if ((i = *colp) >= 0) ! 369: for (; i<9; i++) ! 370: (void) putc(0177, &tp->t_outq); ! 371: } ! 372: *colp = 0; ! 373: } ! 374: if(c) ! 375: (void) putc(c|0200, &tp->t_outq); ! 376: } ! 377: ! 378: /* ! 379: * Called from device's read routine after it has ! 380: * calculated the tty-structure given as argument. ! 381: */ ! 382: ttread(tp) ! 383: register struct tty *tp; ! 384: { ! 385: register s; ! 386: ! 387: if ((tp->t_state&CARR_ON)==0) ! 388: return(-1); ! 389: s = spl5(); ! 390: if (tp->t_canq.c_cc==0) ! 391: while (canon(tp)<0) ! 392: if (tp->t_chan==NULL || ! 393: (getf(u.u_ap[0])->f_flag&FMP)==0) { ! 394: sleep((caddr_t)&tp->t_rawq, TTIPRI); ! 395: } else { ! 396: splx(s); ! 397: return(0); ! 398: } ! 399: splx(s); ! 400: while (tp->t_canq.c_cc && passc(getc(&tp->t_canq))>=0) ! 401: ; ! 402: return(tp->t_rawq.c_cc+tp->t_canq.c_cc); ! 403: } ! 404: ! 405: /* ! 406: * Called from the device's write routine after it has ! 407: * calculated the tty-structure given as argument. ! 408: */ ! 409: caddr_t ! 410: ttwrite(tp) ! 411: register struct tty *tp; ! 412: { ! 413: /* ! 414: * THE POSITIONING OF CP, CC, AND CE ARE CRITICAL ! 415: * AND MUST NOT BE CHANGED WITHOUT PATCHING ! 416: * THE 'ASM' INLINES BELOW. WATCH OUT. ! 417: */ ! 418: register char *cp; ! 419: register int cc, ce; ! 420: register i; ! 421: char obuf[OBUFSIZ]; ! 422: int hiwat = TTHIWAT(tp); ! 423: ! 424: if ((tp->t_state&CARR_ON)==0) ! 425: return(NULL); ! 426: while (u.u_count) { ! 427: cc = MIN(u.u_count, OBUFSIZ); ! 428: cp = obuf; ! 429: iomove(cp, (unsigned)cc, B_WRITE); ! 430: if (u.u_error) ! 431: break; ! 432: (void) spl5(); ! 433: while (tp->t_outq.c_cc > hiwat) { ! 434: ttstart(tp); ! 435: tp->t_state |= ASLEEP; ! 436: if (tp->t_chan && u.u_segflg == 0 && ! 437: (getf(u.u_ap[0])->f_flag&FMP)) { ! 438: u.u_base -= cc; ! 439: u.u_offset -= cc; ! 440: u.u_count += cc; ! 441: (void) spl0(); ! 442: return((caddr_t)&tp->t_outq); ! 443: } ! 444: sleep((caddr_t)&tp->t_outq, TTOPRI); ! 445: } ! 446: (void) spl0(); ! 447: if (tp->t_flags&LCASE) { ! 448: while (cc--) ! 449: ttyoutput(*cp++,tp); ! 450: continue; ! 451: } ! 452: while (cc) { ! 453: if (tp->t_flags&RAW) ! 454: ce=cc; ! 455: else { ! 456: #ifdef vax ! 457: asm(" scanc r9,(r10),_partab,$077"); ! 458: asm(" subl3 r0,r9,r8"); ! 459: #else ! 460: ce=0; ! 461: while(((partab[*(unsigned char *)(cp+ce)]&077)==0)&&(ce<cc)) ! 462: ce++; ! 463: #endif ! 464: if (ce==0) { ! 465: ttyoutput(*cp++,tp); ! 466: cc--; ! 467: goto check; ! 468: } ! 469: } ! 470: i=b_to_q(cp,ce,&tp->t_outq); ! 471: ce-=i; ! 472: tk_nout+=ce; ! 473: tp->t_col+=ce; ! 474: cp+=ce; ! 475: cc-=ce; ! 476: check: ! 477: if (tp->t_outq.c_cc > hiwat) { ! 478: (void) spl5(); ! 479: while (tp->t_outq.c_cc > hiwat) { ! 480: ttstart(tp); ! 481: tp->t_state |= ASLEEP; ! 482: sleep((caddr_t)&tp->t_outq, TTOPRI); ! 483: } ! 484: (void) spl0(); ! 485: } ! 486: } ! 487: } ! 488: ttstart(tp); ! 489: return(NULL); ! 490: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.