1: /*
   2:  *	SCCS id	@(#)ttynew.c	2.1 (Berkeley)	8/5/83
   3:  */
   4: 
   5: /*
   6:  * New version of tty driver, supported
   7:  * as NTTYDISC.  Adapted from a tty.c written
   8:  * by J.E.Kulp of IIASA, Austria (jekulp@mc)
   9:  */
  10: #include "param.h"
  11: #ifdef UCB_NTTY
  12: #include <sys/systm.h>
  13: #include <sys/dir.h>
  14: #include <sys/user.h>
  15: #include <sys/tty.h>
  16: #include <sys/proc.h>
  17: #ifdef  MPX_FILS
  18: #include <sys/mx.h>
  19: #endif
  20: #include <sys/inode.h>
  21: #include <sys/file.h>
  22: #include <sys/reg.h>
  23: #include <sys/conf.h>
  24: #include <sys/buf.h>
  25: 
  26: #ifndef UCB_NET
  27: #define ttsignal(tp, c) gsignal((tp)->t_pgrp, c)
  28: #define ttwakeup(tp)    wakeup((caddr_t) &(tp)->t_rawq)
  29: #endif
  30: 
  31: extern  char    partab[];
  32: 
  33: /*
  34:  * Input mapping table-- if an entry is non-zero, when the
  35:  * corresponding character is typed preceded by "\" the escape
  36:  * sequence is replaced by the table value.  Mostly used for
  37:  * upper-case only terminals.
  38:  */
  39: 
  40: char    maptab[];       /* see tty.c */
  41: 
  42: /*
  43:  * shorthand
  44:  */
  45: #define q1  tp->t_rawq
  46: #define q2  tp->t_canq
  47: #define q3  tp->t_outq
  48: #define q4  tp->t_un.t_ctlq
  49: 
  50: #define OBUFSIZ 100
  51: 
  52: /*
  53:  * routine called on switching to NTTYDISC
  54:  */
  55: ntyopen(tp)
  56: register struct tty *tp;
  57: {
  58:     if (tp->t_line != NTTYDISC)
  59:         wflushtty(tp);
  60: }
  61: 
  62: /*
  63:  * clean tp on exiting NTTYDISC
  64:  */
  65: ntyclose(tp)
  66: struct tty *tp;
  67: {
  68:     wflushtty(tp);
  69: }
  70: 
  71: /*
  72:  * reinput pending characters after state switch
  73:  * call at spl5().
  74:  */
  75: ttypend(tp)
  76: register struct tty *tp;
  77: {
  78:     struct clist tq;
  79:     register c;
  80: 
  81:     tp->t_local &= ~LPENDIN;
  82:     tp->t_lstate |= LSTYPEN;
  83:     tq = tp->t_rawq;
  84:     tp->t_rawq.c_cc = 0;
  85:     tp->t_rawq.c_cf = tp->t_rawq.c_cl = NULL;
  86:     while ((c = getc(&tq)) >= 0)
  87:         ntyinput(c, tp);
  88:     tp->t_lstate &= ~LSTYPEN;
  89: }
  90: 
  91: /*
  92:  * Place a character on raw TTY input queue, putting in delimiters
  93:  * and waking up top half as needed.
  94:  * Also echo if required.
  95:  * The arguments are the character and the appropriate
  96:  * tty structure.
  97:  */
  98: ntyinput(c, tp)
  99: register c;
 100: register struct tty *tp;
 101: {
 102:     register int t_flags;
 103:     int i;
 104: 
 105:     if (tp->t_local&LPENDIN)
 106:         ttypend(tp);
 107:     tk_nin++;
 108:     c &= 0377;
 109:     t_flags = tp->t_flags;
 110:     if (t_flags&TANDEM)
 111:         ttyblock(tp);
 112:     if ((t_flags&RAW)==0) {
 113:         if ((tp->t_lstate&LSTYPEN) == 0)
 114:             c &= 0177;
 115:     /* check for literal nexting before any other processing */
 116:         if (tp->t_lstate&LSLNCH) {
 117:             c |= 0200;
 118:             tp->t_lstate &= ~LSLNCH;
 119:         }
 120:         if (c==tlun.t_lnextc) {
 121:             if (tp->t_flags&ECHO)
 122:                 ntyout("^\b", tp);
 123:             tp->t_lstate |= LSLNCH;
 124:     /* check for output control functions */
 125:         } else if (c==tun.t_stopc) {
 126:             if ((tp->t_state&TTSTOP)==0) {
 127:                 tp->t_state |= TTSTOP;
 128:                 (*cdevsw[major(tp->t_dev)].d_stop)(tp,0);
 129:                 return;
 130:             }
 131:             if (c!=tun.t_startc)
 132:                 return;
 133:         } else if (c==tun.t_startc) {
 134:             tp->t_state &= ~TTSTOP;
 135:             tp->t_local &= ~LFLUSHO;
 136:             ttstart(tp);
 137:             return;
 138:     /* check for input interrupts (and flushed output) */
 139:         } else if (c==tlun.t_flushc) {
 140:             if (tp->t_local & LFLUSHO)
 141:                 tp->t_local &= ~LFLUSHO;
 142:             else {
 143:                 flushtty(tp, FWRITE);
 144:                 ntyecho(c, tp);
 145:                 if (tp->t_rawq.c_cc+tp->t_canq.c_cc)
 146:                     ntyretype(tp);
 147:                 tp->t_local |= LFLUSHO;
 148:             }
 149:             ttstart(tp);
 150:             return;
 151: #ifdef  MENLO_JCL
 152:         } else if (c==tlun.t_suspc || c==tun.t_intrc ||
 153:                c==tun.t_quitc) {
 154:                 if ((tp->t_local & LNOFLSH) == 0)
 155:                     flushtty(tp, c==tlun.t_suspc ? FREAD : FREAD|FWRITE);
 156:             ntyecho(c, tp);
 157:             c = c==tun.t_intrc ? SIGINT :
 158:                 ((c==tun.t_quitc) ? SIGQUIT : SIGTSTP);
 159: #else
 160:         } else if (c==tun.t_intrc || c==tun.t_quitc) {
 161:                 if ((tp->t_local & LNOFLSH) == 0)
 162:                     flushtty(tp, FREAD|FWRITE);
 163:             ntyecho(c, tp);
 164:             c = c==tun.t_intrc ? SIGINT : SIGQUIT;
 165: #endif
 166: #ifdef  MPX_FILS
 167:             if (tp->t_chan)
 168:                 scontrol(tp->t_chan, M_SIG, c);
 169:             else
 170: #endif
 171:                 ttsignal(tp, c);
 172:     /* check for buffer editing functions - cooked mode */
 173:         } else if ((t_flags&CBREAK) == 0) {
 174:             if ((tp->t_lstate&LSQUOT) &&
 175:                 (c==tp->t_erase||c==tp->t_kill)) {
 176:                 ntyrub(unputc(&tp->t_rawq), tp);
 177:                 c |= 0200;
 178:             }
 179:             if (c==tp->t_erase) {
 180:                 if (tp->t_rawq.c_cc)
 181:                     ntyrub(unputc(&tp->t_rawq), tp);
 182:             } else if (c==tp->t_kill) {
 183:                 if (tp->t_local&LCRTKIL &&
 184:                     tp->t_rawq.c_cc == tp->t_rocount) {
 185:                     while (tp->t_rawq.c_cc)
 186:                         ntyrub(unputc(&tp->t_rawq), tp);
 187:                 } else {
 188:                     ntyecho(c, tp);
 189:                     ntyecho('\n', tp);
 190:                     while (getc(&tp->t_rawq) > 0)
 191:                         ;
 192:                     tp->t_rocount = 0;
 193:                 }
 194:                 tp->t_lstate = 0;
 195:             } else if (c==tlun.t_werasc) {
 196:                 if (tp->t_rawq.c_cc == 0)
 197:                     goto out;
 198:                 do {
 199:                     c = unputc(&tp->t_rawq);
 200:                     if (c != ' ' && c != '\t')
 201:                         goto erasenb;
 202:                     ntyrub(c, tp);
 203:                 } while (tp->t_rawq.c_cc);
 204:                 goto out;
 205:                 erasenb:
 206:                 do {
 207:                     ntyrub(c, tp);
 208:                     if (tp->t_rawq.c_cc == 0)
 209:                         goto out;
 210:                     c = unputc(&tp->t_rawq);
 211:                 } while (c != ' ' && c != '\t');
 212:                 (void) putc(c, &tp->t_rawq);
 213:             } else if (c==tlun.t_rprntc) {
 214:                 ntyretype(tp);
 215:     /* check for cooked mode input buffer overflow */
 216:             } else if (tp->t_rawq.c_cc + tp->t_canq.c_cc > TTYHOG) {
 217:                 /* we should start a timeout that flushes the
 218: 				   buffer if it stays full - same in CBREAK */
 219:                 if (tp->t_outq.c_cc < TTHIWAT(tp))
 220:                     (void) ntyoutput(CTRL(g), tp);
 221:     /* put data char in q for user and wakeup if a break char */
 222:             } else if (putc(c, &tp->t_rawq) >= 0) {
 223:                 if (!ntbreakc(c, tp)) {
 224:                     if (tp->t_rocount++ == 0)
 225:                         tp->t_rocol = tp->t_col;
 226:                 } else {
 227:                     tp->t_rocount = 0;
 228:                     catq(&tp->t_rawq, &tp->t_canq);
 229: #ifdef  MPX_FILS
 230:                     if (tp->t_chan)
 231:                         (void) sdata(tp->t_chan);
 232:                     else
 233: #endif
 234:                         ttwakeup(tp);
 235: #ifdef  MENLO_JCL
 236:                     if (tp->t_local&LINTRUP)
 237:                         ttsignal(tp, SIGTINT);
 238: #endif
 239:                 }
 240:                 tp->t_lstate &= ~LSQUOT;
 241:                 if (c == '\\')
 242:                     tp->t_lstate |= LSQUOT;
 243:                 if (tp->t_lstate&LSERASE) {
 244:                     tp->t_lstate &= ~LSERASE;
 245:                     (void) ntyoutput('/', tp);
 246:                 }
 247:                 i = tp->t_col;
 248:                 ntyecho(c, tp);
 249:                 if (c==tun.t_eofc && tp->t_flags&ECHO) {
 250:                     i = MIN(2, tp->t_col - i);
 251:                     while (i > 0) {
 252:                         (void) ntyoutput('\b', tp);
 253:                         i--;
 254:                     }
 255:                 }
 256:             }
 257:     /* CBREAK mode */
 258:         } else if (tp->t_rawq.c_cc > TTYHOG) {
 259:             if (tp->t_outq.c_cc < TTHIWAT(tp))
 260:                 (void) ntyoutput(CTRL(g), tp);
 261:         } else if (putc(c, &tp->t_rawq) >= 0) {
 262: #ifdef  MENLO_JCL
 263:             if (tp->t_local&LINTRUP)
 264:                 ttsignal(tp, SIGTINT);
 265: #endif
 266: #ifdef  MPX_FILS
 267:             if (tp->t_chan)
 268:                 (void) sdata(tp->t_chan);
 269:             else
 270: #endif
 271:                 ttwakeup(tp);
 272:             ntyecho(c, tp);
 273:         }
 274:     /* RAW mode */
 275:     } else if (tp->t_rawq.c_cc > TTYHOG)
 276:         flushtty(tp, FREAD|FWRITE);
 277:     else {
 278:         if (putc(c, &tp->t_rawq) >= 0) {
 279: #ifdef  MENLO_JCL
 280:             if (tp->t_local&LINTRUP)
 281:                 ttsignal(tp, SIGTINT);
 282: #endif
 283: #ifdef  MPX_FILS
 284:             if (tp->t_chan)
 285:                 (void) sdata(tp->t_chan);
 286:             else
 287: #endif
 288:                 ttwakeup(tp);
 289:         }
 290:         ntyecho(c, tp);
 291:     }
 292: out:
 293:     if (tp->t_local & LDECCTQ && tp->t_state & TTSTOP)
 294:         return;
 295:     tp->t_state &= ~TTSTOP;
 296:     tp->t_local &= ~LFLUSHO;
 297:     ttstart(tp);
 298: }
 299: 
 300: /*
 301:  * put character on TTY output queue, adding delays,
 302:  * expanding tabs, and handling the CR/NL bit.
 303:  * It is called both from the top half for output, and from
 304:  * interrupt level for echoing.
 305:  * The arguments are the character and the tty structure.
 306:  * Returns < 0 if putc succeeds, otherwise returns char to resend
 307:  * Must be recursive.
 308:  */
 309: ntyoutput(c, tp)
 310: register c;
 311: register struct tty *tp;
 312: {
 313:     register char *colp;
 314:     register ctype;
 315: 
 316:     if (tp->t_flags&RAW || tp->t_local&LLITOUT) {
 317:         if (tp->t_local&LFLUSHO)
 318:             return (-1);
 319:         if (putc(c, &tp->t_outq))
 320:             return(c);
 321:         tk_nout++;
 322:         return (-1);
 323:     }
 324:     /*
 325: 	 * Ignore EOT in normal mode to avoid hanging up
 326: 	 * certain terminals.
 327: 	 */
 328:     c &= 0177;
 329:     if (c==CEOT && (tp->t_flags&CBREAK)==0)
 330:         return (-1);
 331:     /*
 332: 	 * Turn tabs to spaces as required
 333: 	 */
 334:     if (c=='\t' && (tp->t_flags&TBDELAY)==XTABS) {
 335:         register int s;
 336: 
 337:         c = 8 - (tp->t_col&7);
 338:         if ((tp->t_local&LFLUSHO) == 0) {
 339:             s = spl5();     /* don't interrupt tabs */
 340:             c -= b_to_q("        ", c, &tp->t_outq);
 341:             tk_nout += c;
 342:             splx(s);
 343:         }
 344:         tp->t_col += c;
 345:         return (c ? -1 : '\t');
 346:     }
 347:     tk_nout++;
 348:     /*
 349: 	 * for upper-case-only terminals,
 350: 	 * generate escapes.
 351: 	 */
 352:     if (tp->t_flags&LCASE) {
 353:         colp = "({)}!|^~'`";
 354:         while(*colp++)
 355:             if(c == *colp++) {
 356:                 if (ntyoutput('\\', tp) >= 0)
 357:                     return (c);
 358:                 c = colp[-2];
 359:                 break;
 360:             }
 361:         if ('a'<=c && c<='z')
 362:             c += 'A' - 'a';
 363:     }
 364:     /*
 365: 	 * turn <nl> to <cr><lf> if desired.
 366: 	 */
 367:     if (c=='\n' && tp->t_flags&CRMOD)
 368:         if (ntyoutput('\r', tp) >= 0)
 369:             return (c);
 370:     if (c=='~' && tp->t_local&LTILDE)
 371:         c = '`';
 372:     if ((tp->t_local&LFLUSHO) == 0 && putc(c, &tp->t_outq))
 373:         return (c);
 374:     /*
 375: 	 * Calculate delays.
 376: 	 * The numbers here represent clock ticks
 377: 	 * and are not necessarily optimal for all terminals.
 378: 	 * The delays are indicated by characters above 0200.
 379: 	 * In raw mode there are no delays and the
 380: 	 * transmission path is 8 bits wide.
 381: 	 */
 382:     colp = &tp->t_col;
 383:     ctype = partab[c];
 384:     c = 0;
 385:     switch (ctype&077) {
 386: 
 387:     case ORDINARY:
 388:         (*colp)++;
 389: 
 390:     case CONTROL:
 391:         break;
 392: 
 393:     case BACKSPACE:
 394:         if (*colp)
 395:             (*colp)--;
 396:         break;
 397: 
 398:     case NEWLINE:
 399:         ctype = (tp->t_flags >> 8) & 03;
 400:         if(ctype == 1) { /* tty 37 */
 401:             if (*colp)
 402:                 c = MAX(((unsigned)*colp>>4) + 3, (unsigned)6);
 403:         } else
 404:         if(ctype == 2) { /* vt05 */
 405:             c = 6;
 406:         }
 407:         *colp = 0;
 408:         break;
 409: 
 410:     case TAB:
 411:         ctype = (tp->t_flags >> 10) & 03;
 412:         if(ctype == 1) { /* tty 37 */
 413:             c = 1 - (*colp | ~07);
 414:             if(c < 5)
 415:                 c = 0;
 416:         }
 417:         *colp |= 07;
 418:         (*colp)++;
 419:         break;
 420: 
 421:     case VTAB:
 422:         if(tp->t_flags & VTDELAY) /* tty 37 */
 423:             c = 0177;
 424:         break;
 425: 
 426:     case RETURN:
 427:         ctype = (tp->t_flags >> 12) & 03;
 428:         if(ctype == 1) { /* tn 300 */
 429:             c = 5;
 430:         } else if(ctype == 2) { /* ti 700 */
 431:             c = 10;
 432:         } else if(ctype == 3) { /* concept 100 */
 433:             int i;
 434:             if ((i = *colp) >= 0)
 435:                 for (; i<9; i++)
 436:                     (void) putc(0177, &tp->t_outq);
 437:         }
 438:         *colp = 0;
 439:     }
 440:     if(c && (tp->t_local&LFLUSHO) == 0)
 441:         (void) putc(c|0200, &tp->t_outq);
 442:     return (-1);
 443: }
 444: 
 445: /*
 446:  * Called from device's read routine after it has
 447:  * calculated the tty-structure given as argument.
 448:  */
 449: ntread(tp)
 450: register struct tty *tp;
 451: {
 452:     register struct clist *qp;
 453:     register c, first;
 454: 
 455:     if ((tp->t_state&CARR_ON)==0)
 456:         return(0);
 457: loop:
 458:     (void) _spl5();
 459:     if (tp->t_local&LPENDIN)
 460:         ttypend(tp);
 461:     (void) _spl0();
 462: #ifdef  MENLO_JCL
 463:     while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) {
 464:         if (u.u_signal[SIGTTIN] == SIG_IGN ||
 465:             u.u_signal[SIGTTIN] == SIG_HOLD ||
 466:             (u.u_procp->p_flag&SDETACH))
 467:             return (0);
 468:         gsignal(u.u_procp->p_pgrp, SIGTTIN);
 469:         sleep((caddr_t)&lbolt, TTIPRI);
 470:     }
 471: #endif
 472:     if (tp->t_flags&RAW) {
 473:         (void) _spl5();
 474:         if (tp->t_rawq.c_cc <= 0) {
 475: #ifdef  MPX_FILS
 476:             if ((tp->t_state&CARR_ON)==0 || tp->t_chan!=NULL
 477: #else
 478:             if ((tp->t_state&CARR_ON)==0
 479: #endif
 480: #ifdef  UCB_NET
 481:                 || (tp->t_state&TS_NBIO)
 482: #endif
 483:                )
 484:             {
 485:                 (void) _spl0();
 486:                 return (0);
 487:             }
 488: #ifdef  MENLO_JCL
 489:             if (tp->t_local&LINTRUP &&
 490:                 u.u_signal[SIGTINT] != SIG_DFL) {
 491:                 u.u_error = EWOULDBLOCK;
 492:                 (void) _spl0();
 493:                 return (0);
 494:             }
 495: #endif
 496:             sleep((caddr_t)&tp->t_rawq, TTIPRI);
 497:             (void) _spl0();
 498:             goto loop;
 499:         }
 500:         (void) _spl0();
 501:         while (tp->t_rawq.c_cc && passc(getc(&tp->t_rawq))>=0)
 502:             ;
 503:     } else {
 504:         qp = tp->t_flags & CBREAK ? &tp->t_rawq : &tp->t_canq;
 505:         (void) _spl5();
 506:         if (qp->c_cc <= 0) {
 507: #ifdef  MPX_FILS
 508:             if ((tp->t_state&CARR_ON)==0 || tp->t_chan!=NULL
 509: #else
 510:             if ((tp->t_state&CARR_ON)==0
 511: #endif
 512: #ifdef  UCB_NET
 513:                || (tp->t_state&TS_NBIO)
 514: #endif
 515:                )
 516:             {
 517:                 (void) _spl0();
 518:                 return (0);
 519:             }
 520: #ifdef  MENLO_JCL
 521:             if (tp->t_local&LINTRUP &&
 522:                 u.u_signal[SIGTINT] != SIG_DFL) {
 523:                 u.u_error = EWOULDBLOCK;
 524:                 (void) _spl0();
 525:                 return (0);
 526:             }
 527: #endif
 528:             sleep((caddr_t)&tp->t_rawq, TTIPRI);
 529:             (void) _spl0();
 530:             goto loop;
 531:         }
 532:         (void) _spl0();
 533:         first = 1;
 534:         while ((c = getc(qp)) >= 0) {
 535:             if (tp->t_flags&CRMOD && c == '\r')
 536:                 c = '\n';
 537:             if (tp->t_flags&LCASE && c <= 0177)
 538:                 if (tp->t_lstate&LSBKSL) {
 539:                     if (maptab[c])
 540:                         c = maptab[c];
 541:                     tp->t_lstate &= ~LSBKSL;
 542:                 } else if (c >= 'A' && c <= 'Z')
 543:                     c += 'a' - 'A';
 544:                 else if (c == '\\') {
 545:                     tp->t_lstate |= LSBKSL;
 546:                     continue;
 547:                 }
 548: #ifdef  MENLO_JCL
 549:             if (c == tlun.t_dsuspc) {
 550:                 ttsignal(tp, SIGTSTP);
 551:                 if (first) {
 552:                     sleep((caddr_t)&lbolt, TTIPRI);
 553:                     goto loop;
 554:                 }
 555:                 break;
 556:             }
 557: #endif
 558:             if (c == tun.t_eofc && (tp->t_flags&CBREAK)==0)
 559:                 break;
 560:             if (passc(c & 0177) < 0)
 561:                 break;
 562:             if ((tp->t_flags&CBREAK)==0 && ntbreakc(c, tp))
 563:                 break;
 564:             first = 0;
 565:         }
 566:         tp->t_lstate &= ~LSBKSL;
 567:     }
 568: 
 569:     /*
 570:  	 * Resume output iff:
 571:  	 * is blocked
 572:  	 * AND (input < threshold OR (cooked mode AND delim_count == 0))
 573:  	 * This makes tandem mode usable for line-mode input.
 574:  	 */
 575:     if (tp->t_state&TBLOCK && ((tp->t_rawq.c_cc < TTYHOG/5) ||
 576:        (tp->t_delct==0 && ((tp->t_flags&(CBREAK|RAW)) == 0)))) {
 577:         if (putc(tun.t_startc, &tp->t_outq)==0) {
 578:             tp->t_state &= ~TBLOCK;
 579:             ttstart(tp);
 580:         }
 581:     }
 582: 
 583:     return (tp->t_rawq.c_cc + tp->t_canq.c_cc);
 584: }
 585: 
 586: /*
 587:  * Called from the device's write routine after it has
 588:  * calculated the tty-structure given as argument.
 589:  */
 590: caddr_t
 591: ntwrite(tp)
 592: register struct tty *tp;
 593: {
 594:     register char *cp;
 595:     register int cc, ce;
 596:     register i;
 597:     char obuf[OBUFSIZ];
 598:     register c;
 599:     int hiwat = TTHIWAT(tp);
 600: #ifdef  UCB_NET
 601:     int cnt = u.u_count;
 602: #endif
 603: 
 604:     if ((tp->t_state&CARR_ON)==0)
 605:         return (NULL);
 606: loop:
 607: #ifdef  MENLO_JCL
 608:     while (u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
 609:         (tp->t_local&LTOSTOP) &&
 610:         u.u_signal[SIGTTOU] != SIG_IGN &&
 611:         u.u_signal[SIGTTOU] != SIG_HOLD &&
 612:         (u.u_procp->p_flag&SDETACH)==0) {
 613:         gsignal(u.u_procp->p_pgrp, SIGTTOU);
 614:         sleep((caddr_t)&lbolt, TTIPRI);
 615:     }
 616: #endif
 617:     while (u.u_count) {
 618:         cc = MIN(u.u_count, OBUFSIZ);
 619:         cp = obuf;
 620:         iomove(cp, (unsigned)cc, B_WRITE);
 621:         if (u.u_error)
 622:             break;
 623:         if (tp->t_outq.c_cc > hiwat)
 624:             goto ovhiwat;
 625:         if (tp->t_local&LFLUSHO)
 626:             continue;
 627:         if (tp->t_flags&LCASE || tp->t_local&LTILDE) {
 628:             while (cc--) {
 629:                 c = *cp++;
 630:                 tp->t_rocount = 0;
 631:                 while((c = ntyoutput(c, tp)) >= 0) {
 632:                     /* out of clists, wait a bit */
 633:                     ttstart(tp);
 634:                     sleep((caddr_t)&lbolt, TTOPRI);
 635:                     tp->t_rocount = 0;
 636:                 }
 637:                 if (tp->t_outq.c_cc > hiwat)
 638:                     goto ovhiwat;
 639:             }
 640:             continue;
 641:         }
 642:         while (cc) {
 643:             if (tp->t_flags&RAW || tp->t_local&LLITOUT)
 644:                 ce = cc;
 645:             else {
 646:                 ce=0;
 647:                 while(((partab[(*(cp+ce))&0177]&077)==0)&&(ce<cc))
 648:                     ce++;
 649:                 if (ce==0) {
 650:                     tp->t_rocount = 0;
 651:                     if (ntyoutput(*cp, tp) >= 0) {
 652:                         ttstart(tp);
 653:                         sleep((caddr_t)&lbolt, TTOPRI);
 654:                         continue;
 655:                     }
 656:                     cp++;
 657:                     cc--;
 658:                     if (tp->t_outq.c_cc > hiwat)
 659:                         goto ovhiwat;
 660:                 }
 661:             }
 662:             tp->t_rocount = 0;
 663:             i=b_to_q(cp,ce,&tp->t_outq);
 664:             ce-=i;
 665:             tk_nout+=ce;
 666:             tp->t_col+=ce;
 667:             cp+=ce;
 668:             cc-=ce;
 669:             if (i) {
 670:                 ttstart(tp);
 671:                 sleep((caddr_t)&lbolt, TTOPRI);
 672:             }
 673:             if (ce || tp->t_outq.c_cc > hiwat)
 674:                 goto ovhiwat;
 675:         }
 676:     }
 677:     ttstart(tp);
 678:     return(NULL);
 679: 
 680: ovhiwat:
 681:     (void) _spl5();
 682:     u.u_base -= cc;
 683:     u.u_offset -= cc;
 684:     u.u_count += cc;
 685:     if (tp->t_outq.c_cc <= hiwat) {
 686:         (void) _spl0();
 687:         goto loop;
 688:     }
 689:     ttstart(tp);
 690: #ifdef  UCB_NET
 691:     if (tp->t_state & TS_NBIO) {
 692:         if (u.u_count == cnt)
 693:             u.u_error = EWOULDBLOCK;
 694:         return(NULL);
 695:     }
 696: #endif
 697:     tp->t_state |= ASLEEP;
 698: #ifdef  MPX_FILS
 699:     if (tp->t_chan) {
 700:         (void) _spl0();
 701:         return ((caddr_t)&tp->t_outq);
 702:     }
 703: #endif
 704:     sleep((caddr_t)&tp->t_outq, TTOPRI);
 705:     (void) _spl0();
 706:     goto loop;
 707: }
 708: 
 709: /*
 710:  * Rubout one character from the rawq of tp
 711:  * as cleanly as possible.
 712:  */
 713: ntyrub(c, tp)
 714: register c;
 715: register struct tty *tp;
 716: {
 717:     register char *cp;
 718:     register int savecol;
 719:     int s;
 720:     char *nextc();
 721: 
 722:     if ((tp->t_flags&ECHO)==0)
 723:         return;
 724:     tp->t_local &= ~LFLUSHO;
 725:     c &= 0377;
 726:     if (tp->t_local&LCRTBS) {
 727:         if (tp->t_rocount == 0) {
 728:             /*
 729: 			 * Screwed by ttwrite; retype
 730: 			 */
 731:             ntyretype(tp);
 732:             return;
 733:         }
 734:         if (c==('\t'|0200) || c==('\n'|0200))
 735:             ntyrubo(tp, 2);
 736:         else switch(partab[c&=0177] & 0177) {
 737: 
 738:         case ORDINARY:
 739:             ntyrubo(tp, 1);
 740:             break;
 741: 
 742:         case VTAB:
 743:         case BACKSPACE:
 744:         case CONTROL:
 745:         case RETURN:
 746:             if (tp->t_local & LCTLECH)
 747:                 ntyrubo(tp, 2);
 748:             break;
 749: 
 750:         case TAB:
 751:             if (tp->t_rocount < tp->t_rawq.c_cc) {
 752:                 ntyretype(tp);
 753:                 return;
 754:             }
 755:             s = spl5();
 756:             savecol = tp->t_col;
 757:             tp->t_lstate |= LSCNTTB;
 758:             tp->t_local |= LFLUSHO;
 759:             tp->t_col = tp->t_rocol;
 760:             for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp))
 761:                 ntyecho(lookc(cp), tp);
 762:             tp->t_local &= ~LFLUSHO;
 763:             tp->t_lstate &= ~LSCNTTB;
 764:             splx(s);
 765:             /*
 766: 			 * savecol will now be length of the tab
 767: 			 */
 768:             savecol -= tp->t_col;
 769:             tp->t_col += savecol;
 770:             if (savecol > 8)
 771:                 savecol = 8;        /* overflow screw */
 772:             while (--savecol >= 0)
 773:                 (void) ntyoutput('\b', tp);
 774:             break;
 775: 
 776:         default:
 777:             panic("ttyrub");
 778:         }
 779:     } else if (tp->t_local&LPRTERA) {
 780:         if ((tp->t_lstate&LSERASE) == 0) {
 781:             (void) ntyoutput('\\', tp);
 782:             tp->t_lstate |= LSERASE;
 783:         }
 784:         ntyecho(c, tp);
 785:     } else
 786:         ntyecho(tp->t_erase, tp);
 787:     tp->t_rocount--;
 788: }
 789: 
 790: /*
 791:  * Crt back over cnt chars perhaps
 792:  * erasing them.
 793:  */
 794: ntyrubo(tp, cnt)
 795: register struct tty *tp;
 796: register cnt;
 797: {
 798: 
 799:     while (--cnt >= 0)
 800:         ntyout(tp->t_local&LCRTERA ? "\b \b" : "\b", tp);
 801: }
 802: 
 803: /*
 804:  * Reprint the rawq line.
 805:  * We assume c_cc has already been checked.
 806:  */
 807: ntyretype(tp)
 808: register struct tty *tp;
 809: {
 810:     register char *cp;
 811:     char *nextc();
 812:     register s;
 813: 
 814:     if (tlun.t_rprntc != 0377)
 815:         ntyecho(tlun.t_rprntc, tp);
 816:     (void) ntyoutput('\n', tp);
 817:     s = spl5();
 818:     for (cp = tp->t_canq.c_cf; cp; cp = nextc(&tp->t_canq, cp))
 819:         ntyecho(lookc(cp), tp);
 820:     for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp))
 821:         ntyecho(lookc(cp), tp);
 822:     tp->t_lstate &= ~LSERASE;
 823:     splx(s);
 824:     tp->t_rocount = tp->t_rawq.c_cc;
 825:     tp->t_rocol = 0;
 826: }
 827: 
 828: /*
 829:  * Echo a typed character to the terminal
 830:  */
 831: ntyecho(c, tp)
 832: register c;
 833: register struct tty *tp;
 834: {
 835: 
 836:     if ((tp->t_lstate & LSCNTTB) == 0)
 837:         tp->t_local &= ~LFLUSHO;
 838:     if ((tp->t_flags&ECHO) == 0)
 839:         return;
 840:     c &= 0377;
 841:     if (tp->t_flags&RAW) {
 842:         (void) ntyoutput(c, tp);
 843:         return;
 844:     }
 845:     if (c == '\r' && tp->t_flags&CRMOD)
 846:         c = '\n';
 847:     if (tp->t_local&LCTLECH) {
 848:         if ((c&0177) <= 037 && c!='\t' && c!='\n' || (c&0177)==0177) {
 849:             (void) ntyoutput('^', tp);
 850:             c &= 0177;
 851:             if (c == 0177)
 852:                 c = '?';
 853:             else if (tp->t_flags&LCASE)
 854:                 c += 'a' - 1;
 855:             else
 856:                 c += 'A' - 1;
 857:         }
 858:     }
 859:     (void) ntyoutput(c & 0177, tp);
 860: }
 861: 
 862: /*
 863:  * Is c a break char for tp?
 864:  */
 865: ntbreakc(c, tp)
 866: register c;
 867: register struct tty *tp;
 868: {
 869:     return (c == '\n' || c == tun.t_eofc || c == tun.t_brkc ||
 870:         c == '\r' && (tp->t_flags&CRMOD));
 871: }
 872: 
 873: /*
 874:  * send string cp to tp
 875:  */
 876: ntyout(cp, tp)
 877: register char *cp;
 878: register struct tty *tp;
 879: {
 880:     register char c;
 881: 
 882:     while (c = *cp++)
 883:         (void) ntyoutput(c, tp);
 884: }
 885: 
 886: #ifdef  UCB_NET
 887: ttwakeup(tp)
 888:     struct tty *tp;
 889: {
 890:     if (tp->t_rsel) {
 891:         selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL);
 892:         tp->t_state &= ~TS_RCOLL;
 893:         tp->t_rsel = 0;
 894:     }
 895:     wakeup((caddr_t)&tp->t_rawq);
 896: }
 897: 
 898: ttsignal(tp, signo)
 899:     struct tty *tp;
 900:     int signo;
 901: {
 902: 
 903:     gsignal(tp->t_pgrp, signo);
 904: }
 905: #endif	UCB_NET
 906: #endif	UCB_NTTY

Defined functions

ntbreakc defined in line 865; used 2 times
ntread defined in line 449; never used
ntwrite defined in line 590; never used
ntyclose defined in line 65; never used
ntyecho defined in line 831; used 14 times
ntyinput defined in line 98; used 1 times
  • in line 87
ntyopen defined in line 55; never used
ntyout defined in line 876; used 2 times
ntyoutput defined in line 309; used 15 times
ntyretype defined in line 807; used 4 times
ntyrub defined in line 713; used 5 times
ntyrubo defined in line 794; used 3 times
ttsignal defined in line 898; never used
ttwakeup defined in line 887; never used
ttypend defined in line 75; used 3 times

Defined variables

maptab defined in line 40; used 3 times

Defined macros

OBUFSIZ defined in line 50; used 2 times
q1 defined in line 45; never used
q2 defined in line 46; never used
q3 defined in line 47; never used
q4 defined in line 48; never used
ttsignal defined in line 27; used 5 times
ttwakeup defined in line 28; used 3 times
Last modified: 1983-08-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2202
Valid CSS Valid XHTML 1.0 Strict