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: }

Defined functions

nullmodem defined in line 752; used 3 times
ttbreakc defined in line 1662; used 2 times
ttnread defined in line 576; used 2 times
ttread defined in line 1136; used 3 times
ttrstrt defined in line 276; used 2 times
ttselect defined in line 597; used 4 times
ttwakeup defined in line 1683; used 6 times
ttwrite defined in line 1315; used 4 times
ttyblock defined in line 215; used 1 times
ttycheckoutq defined in line 1287; used 2 times
ttyecho defined in line 1628; used 17 times
ttyinput defined in line 791; used 6 times
ttylclose defined in line 674; used 3 times
ttymodem defined in line 709; used 3 times
ttyopen defined in line 646; used 3 times
ttyout defined in line 1673; used 6 times
ttyoutput defined in line 1048; used 14 times
ttypend defined in line 768; used 3 times
ttyretype defined in line 1590; used 4 times
ttyrub defined in line 1480; used 4 times
ttyrubo defined in line 1576; used 3 times
ttyselect defined in line 606; used 4 times
ttyunblock defined in line 252; used 2 times
ttywait defined in line 154; used 2 times

Defined variables

TTYBLOCK defined in line 40; used 1 times
TTYHOG defined in line 39; used 7 times
TTYUNBLOCK defined in line 41; used 1 times
partab defined in line 50; used 3 times
rts defined in line 210; used 2 times
tthiwat defined in line 93; never used
ttlowat defined in line 95; never used
ttydefaults defined in line 98; used 2 times

Defined macros

CLR defined in line 104; used 5 times
ISSET defined in line 105; used 12 times
SET defined in line 103; used 2 times
Last modified: 1997-05-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 8273
Valid CSS Valid XHTML 1.0 Strict