# 2.11BSD#431 - /usr/src/sys/sys/tty.c

##### Functions

    nullmodem         X
    ttbreakc          X
    ttioctl           X
    ttnread           X
    ttread            X
    ttrstrt           X
    ttselect          X
    ttstart           X
    ttwakeup          X
    ttwrite           X
    ttyblock          X
    ttychars          X
    ttycheckoutq      X
    ttyclose          X
    ttyecho           X
    ttyflush          X
    ttyinput          X
    ttylclose         X
    ttymodem          X
    ttyopen           X
    ttyout            X
    ttyoutput         X
    ttyowake          X
    ttypend           X
    ttyretype         X
    ttyrub            X
    ttyrubo           X
    ttyselect         X
    ttyunblock        X
    ttywait           X
    ttywflush         X

##### Variables

    TTYBLOCK          X
    TTYHOG            X
    TTYUNBLOCK        X
    partab            X
    tthiwat           X
    ttlowat           X
    ttydefaults       X

##### Macros

    CLR               X
    ISSET             X
    SET               X

       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

- in /usr/src/sys/sys/tty_conf.c line 22, 45, 54

ttbreakc defined in line 1662; used 2 times

- in line 1005, 1262

ttioctl defined in line 304; used 7 times

- in /usr/src/sys/pdp/cons.c line 133
- in /usr/src/sys/pdpuba/dh.c line 321
- in /usr/src/sys/pdpuba/dhu.c line 358
- in /usr/src/sys/pdpuba/dhv.c line 377
- in /usr/src/sys/pdpuba/dz.c line 279
- in /usr/src/sys/sys/tty_pty.c line 524-526(2)

ttnread defined in line 576; used 2 times

- in line 402, 616

ttread defined in line 1136; used 3 times

- in /usr/src/sys/sys/tty_conf.c line 21, 41, 50

ttrstrt defined in line 276; used 2 times

- in /usr/src/sys/pdpuba/dz.c line 38, 439

ttselect defined in line 597; used 4 times

- in /usr/src/sys/pdp/conf.c line 357-362(2), 370, 406

ttstart defined in line 292; used 24 times

- in line 239, 262, 281, 423, 469, 720, 1037, 1298, 1407, 1436, 1443, 1464
- in /usr/src/sys/pdp/net_mac.h line 185-187(2)
- in /usr/src/sys/pdpuba/dh.c line 737
- in /usr/src/sys/pdpuba/dhu.c line 287
- in /usr/src/sys/pdpuba/dhv.c line 296
- in /usr/src/sys/sys/subr_prf.c line 328
- in /usr/src/sys/sys/tty_conf.c line 21, 42-45(2), 51-54(2)
- in /usr/src/sys/sys/tty_tb.c line 315

ttwakeup defined in line 1683; used 6 times

- in line 193, 463, 823, 929, 1008
- in /usr/src/sys/sys/tty_pty.c line 417

ttwrite defined in line 1315; used 4 times

- in /usr/src/sys/sys/tty_conf.c line 21, 41-44(2), 50

ttyblock defined in line 215; used 1 times

- in line 812

ttychars defined in line 111; used 6 times

- in /usr/src/sys/pdp/cons.c line 63
- in /usr/src/sys/pdpuba/dh.c line 161
- in /usr/src/sys/pdpuba/dhu.c line 149
- in /usr/src/sys/pdpuba/dhv.c line 163
- in /usr/src/sys/pdpuba/dz.c line 131
- in /usr/src/sys/sys/tty_pty.c line 72

ttycheckoutq defined in line 1287; used 2 times

- in /usr/src/sys/sys/subr_prf.c line 79, 101

ttyclose defined in line 695; used 6 times

- in /usr/src/sys/pdp/cons.c line 81
- in /usr/src/sys/pdpuba/dh.c line 205
- in /usr/src/sys/pdpuba/dhu.c line 205
- in /usr/src/sys/pdpuba/dhv.c line 210
- in /usr/src/sys/pdpuba/dz.c line 183
- in /usr/src/sys/sys/tty_pty.c line 96

ttyecho defined in line 1628; used 17 times

- in line 824, 876, 886, 914, 930, 950-951(2), 1016, 1538-1542(2), 1566-1568(2), 1597, 1607-1617(4)

ttyflush defined in line 179; used 15 times

- in line 151, 396, 451, 686, 699, 734, 820, 875, 885, 913
- in /usr/src/sys/net/if_sl.c line 140
- in /usr/src/sys/pdp/net_mac.h line 189-191(2)
- in /usr/src/sys/sys/tty_conf.c line 101
- in /usr/src/sys/sys/tty_pty.c line 506

ttyinput defined in line 791; used 6 times

- in line 780
- in /usr/src/sys/sys/tty_conf.c line 22, 42, 51
- in /usr/src/sys/sys/tty_pty.c line 474, 533

ttylclose defined in line 674; used 3 times

- in /usr/src/sys/sys/tty_conf.c line 21, 41, 50

ttymodem defined in line 709; used 3 times

- in /usr/src/sys/sys/tty_conf.c line 22, 42, 51

ttyopen defined in line 646; used 3 times

- in /usr/src/sys/sys/tty_conf.c line 21, 41, 50

ttyout defined in line 1673; used 6 times

- in line 867, 1583
- in /usr/src/sys/sys/tty_tb.c line 307-314(4)

ttyoutput defined in line 1048; used 14 times

- in line 927, 996, 1013, 1020, 1405, 1555, 1563, 1598, 1641, 1649, 1656, 1680
- in /usr/src/sys/sys/subr_prf.c line 326-327(2)

ttyowake defined in line 123; used 4 times

- in /usr/src/sys/pdp/cons.c line 157
- in /usr/src/sys/pdpuba/dh.c line 524
- in /usr/src/sys/pdpuba/dhu.c line 551
- in /usr/src/sys/pdpuba/dhv.c line 594

ttypend defined in line 768; used 3 times

- in line 582, 802, 1151

ttyretype defined in line 1590; used 4 times

- in line 878, 986, 1497, 1522

ttyrub defined in line 1480; used 4 times

- in line 941, 948, 972-977(2)

ttyrubo defined in line 1576; used 3 times

- in line 1505-1509(2), 1517

ttyselect defined in line 606; used 4 times

- in line 603
- in /usr/src/sys/pdpuba/dh.c line 218
- in /usr/src/sys/pdpuba/dhu.c line 219
- in /usr/src/sys/pdpuba/dhv.c line 225

ttyunblock defined in line 252; used 2 times

- in line 206, 1274

ttywait defined in line 154; used 2 times

- in line 150, 450

ttywflush defined in line 146; used 7 times

- in line 666, 688
- in /usr/src/sys/net/if_sl.c line 160
- in /usr/src/sys/pdp/net_mac.h line 193-195(2)
- in /usr/src/sys/sys/tty_conf.c line 111
- in /usr/src/sys/sys/tty_tb.c line 84

#### Defined variables

TTYBLOCK defined in line 40; used 1 times

- in line 225

TTYHOG defined in line 39; used 7 times

- in line 819, 924, 994
- in /usr/src/sys/sys/tty_pty.c line 364, 400-403(2), 433

TTYUNBLOCK defined in line 41; used 1 times

- in line 1273

partab defined in line 50; used 3 times

- in line 1110, 1398, 1506

rts defined in line 210; used 2 times

- in line 245, 265

tthiwat defined in line 93; never used
ttlowat defined in line 95; never used
ttydefaults defined in line 98; used 2 times

- in line 115
- in /usr/src/sys/sys/tty.c line 115

#### Defined macros

CLR defined in line 104; used 5 times

- in line 131, 138, 202, 261, 267

ISSET defined in line 105; used 12 times

- in line 129, 166, 205, 234, 244, 257, 264, 1176-1177(2), 1209-1210(2), 1273

SET defined in line 103; used 2 times

- in line 238, 247

Last modified: 1997-05-05 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 3746 |