1*7502Sroot /* tty.c 4.24 82/07/24 */ 239Sbill 339Sbill /* 4903Sbill * TTY subroutines common to more than one line discipline 539Sbill */ 639Sbill #include "../h/param.h" 739Sbill #include "../h/systm.h" 839Sbill #include "../h/dir.h" 939Sbill #include "../h/user.h" 1039Sbill #include "../h/tty.h" 1139Sbill #include "../h/proc.h" 1239Sbill #include "../h/inode.h" 1339Sbill #include "../h/file.h" 1439Sbill #include "../h/reg.h" 1539Sbill #include "../h/conf.h" 1639Sbill #include "../h/buf.h" 17340Sbill #include "../h/dk.h" 1839Sbill 197436Skre /* 207436Skre * Table giving parity for characters and indicating 217436Skre * character classes to tty driver. In particular, 227436Skre * if the low 6 bits are 0, then the character needs 237436Skre * no special processing on output. 247436Skre */ 2539Sbill 267436Skre char partab[] = { 277436Skre 0001,0201,0201,0001,0201,0001,0001,0201, 287436Skre 0202,0004,0003,0201,0005,0206,0201,0001, 297436Skre 0201,0001,0001,0201,0001,0201,0201,0001, 307436Skre 0001,0201,0201,0001,0201,0001,0001,0201, 317436Skre 0200,0000,0000,0200,0000,0200,0200,0000, 327436Skre 0000,0200,0200,0000,0200,0000,0000,0200, 337436Skre 0000,0200,0200,0000,0200,0000,0000,0200, 347436Skre 0200,0000,0000,0200,0000,0200,0200,0000, 357436Skre 0200,0000,0000,0200,0000,0200,0200,0000, 367436Skre 0000,0200,0200,0000,0200,0000,0000,0200, 377436Skre 0000,0200,0200,0000,0200,0000,0000,0200, 387436Skre 0200,0000,0000,0200,0000,0200,0200,0000, 397436Skre 0000,0200,0200,0000,0200,0000,0000,0200, 407436Skre 0200,0000,0000,0200,0000,0200,0200,0000, 417436Skre 0200,0000,0000,0200,0000,0200,0200,0000, 427436Skre 0000,0200,0200,0000,0200,0000,0000,0201, 437436Skre 447436Skre /* 457436Skre * 7 bit ascii ends with the last character above, 467436Skre * but we contine through all 256 codes for the sake 477436Skre * of the tty output routines which use special vax 487436Skre * instructions which need a 256 character trt table. 497436Skre */ 507436Skre 517436Skre 0007,0007,0007,0007,0007,0007,0007,0007, 527436Skre 0007,0007,0007,0007,0007,0007,0007,0007, 537436Skre 0007,0007,0007,0007,0007,0007,0007,0007, 547436Skre 0007,0007,0007,0007,0007,0007,0007,0007, 557436Skre 0007,0007,0007,0007,0007,0007,0007,0007, 567436Skre 0007,0007,0007,0007,0007,0007,0007,0007, 577436Skre 0007,0007,0007,0007,0007,0007,0007,0007, 587436Skre 0007,0007,0007,0007,0007,0007,0007,0007, 597436Skre 0007,0007,0007,0007,0007,0007,0007,0007, 607436Skre 0007,0007,0007,0007,0007,0007,0007,0007, 617436Skre 0007,0007,0007,0007,0007,0007,0007,0007, 627436Skre 0007,0007,0007,0007,0007,0007,0007,0007, 637436Skre 0007,0007,0007,0007,0007,0007,0007,0007, 647436Skre 0007,0007,0007,0007,0007,0007,0007,0007, 657436Skre 0007,0007,0007,0007,0007,0007,0007,0007, 667436Skre 0007,0007,0007,0007,0007,0007,0007,0007 677436Skre }; 687436Skre 69146Sbill /* 7039Sbill * Input mapping table-- if an entry is non-zero, when the 7139Sbill * corresponding character is typed preceded by "\" the escape 7239Sbill * sequence is replaced by the table value. Mostly used for 7339Sbill * upper-case only terminals. 7439Sbill */ 7539Sbill 7639Sbill char maptab[] ={ 7739Sbill 000,000,000,000,000,000,000,000, 7839Sbill 000,000,000,000,000,000,000,000, 7939Sbill 000,000,000,000,000,000,000,000, 8039Sbill 000,000,000,000,000,000,000,000, 8139Sbill 000,'|',000,000,000,000,000,'`', 8239Sbill '{','}',000,000,000,000,000,000, 8339Sbill 000,000,000,000,000,000,000,000, 8439Sbill 000,000,000,000,000,000,000,000, 8539Sbill 000,000,000,000,000,000,000,000, 8639Sbill 000,000,000,000,000,000,000,000, 8739Sbill 000,000,000,000,000,000,000,000, 8839Sbill 000,000,000,000,000,000,'~',000, 8939Sbill 000,'A','B','C','D','E','F','G', 9039Sbill 'H','I','J','K','L','M','N','O', 9139Sbill 'P','Q','R','S','T','U','V','W', 9239Sbill 'X','Y','Z',000,000,000,000,000, 9339Sbill }; 9439Sbill 95925Sbill short tthiwat[16] = 96925Sbill { 100,100,100,100,100,100,100,200,200,400,400,400,650,650,650,650 }; 97925Sbill short ttlowat[16] = 98925Sbill { 30, 30, 30, 30, 30, 30, 30, 50, 50,120,120,120,125,125,125,125 }; 99925Sbill 10039Sbill #define OBUFSIZ 100 10139Sbill 10239Sbill /* 10339Sbill * set default control characters. 10439Sbill */ 10539Sbill ttychars(tp) 10639Sbill register struct tty *tp; 10739Sbill { 108174Sbill 10939Sbill tun.t_intrc = CINTR; 11039Sbill tun.t_quitc = CQUIT; 11139Sbill tun.t_startc = CSTART; 11239Sbill tun.t_stopc = CSTOP; 11339Sbill tun.t_eofc = CEOT; 11439Sbill tun.t_brkc = CBRK; 11539Sbill tp->t_erase = CERASE; 11639Sbill tp->t_kill = CKILL; 117174Sbill /* begin local */ 118208Sbill tlun.t_suspc = CTRL(z); 119208Sbill tlun.t_dsuspc = CTRL(y); 120174Sbill tlun.t_rprntc = CTRL(r); 121174Sbill tlun.t_flushc = CTRL(o); 122174Sbill tlun.t_werasc = CTRL(w); 123174Sbill tlun.t_lnextc = CTRL(v); 124174Sbill tp->t_local = 0; 125174Sbill tp->t_lstate = 0; 126174Sbill /* end local */ 12739Sbill } 12839Sbill 12939Sbill /* 130903Sbill * Wait for output to drain, then flush input waiting. 13139Sbill */ 132903Sbill wflushtty(tp) 1335408Swnj register struct tty *tp; 13439Sbill { 13539Sbill 136903Sbill (void) spl5(); 1375622Swnj while (tp->t_outq.c_cc && tp->t_state&TS_CARR_ON 1385622Swnj && tp->t_oproc) { /* kludge for pty */ 139903Sbill (*tp->t_oproc)(tp); 1405408Swnj tp->t_state |= TS_ASLEEP; 141903Sbill sleep((caddr_t)&tp->t_outq, TTOPRI); 142903Sbill } 1435426Swnj flushtty(tp, FREAD); 144903Sbill (void) spl0(); 14539Sbill } 14639Sbill 14739Sbill /* 148903Sbill * flush all TTY queues 14939Sbill */ 150903Sbill flushtty(tp, rw) 151903Sbill register struct tty *tp; 15239Sbill { 153903Sbill register s; 154903Sbill 155903Sbill s = spl6(); 156903Sbill if (rw & FREAD) { 157903Sbill while (getc(&tp->t_canq) >= 0) 158903Sbill ; 159903Sbill wakeup((caddr_t)&tp->t_rawq); 160903Sbill } 161903Sbill if (rw & FWRITE) { 162903Sbill wakeup((caddr_t)&tp->t_outq); 1635408Swnj tp->t_state &= ~TS_TTSTOP; 1645426Swnj (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw); 165903Sbill while (getc(&tp->t_outq) >= 0) 166903Sbill ; 167903Sbill } 168903Sbill if (rw & FREAD) { 169903Sbill while (getc(&tp->t_rawq) >= 0) 170903Sbill ; 171903Sbill tp->t_delct = 0; 172903Sbill tp->t_rocount = 0; /* local */ 173903Sbill tp->t_rocol = 0; 174903Sbill tp->t_lstate = 0; 175903Sbill } 176903Sbill splx(s); 17739Sbill } 17839Sbill 179903Sbill /* 180903Sbill * Send stop character on input overflow. 181903Sbill */ 182903Sbill ttyblock(tp) 183903Sbill register struct tty *tp; 18439Sbill { 185903Sbill register x; 186903Sbill x = tp->t_rawq.c_cc + tp->t_canq.c_cc; 187903Sbill if (tp->t_rawq.c_cc > TTYHOG) { 188903Sbill flushtty(tp, FREAD|FWRITE); 1895408Swnj tp->t_state &= ~TS_TBLOCK; 190903Sbill } 191903Sbill if (x >= TTYHOG/2) { 192903Sbill if (putc(tun.t_stopc, &tp->t_outq)==0) { 1935408Swnj tp->t_state |= TS_TBLOCK; 194903Sbill tp->t_char++; 195903Sbill ttstart(tp); 196903Sbill } 197903Sbill } 19839Sbill } 19939Sbill 20039Sbill /* 201903Sbill * Restart typewriter output following a delay 202903Sbill * timeout. 203903Sbill * The name of the routine is passed to the timeout 204903Sbill * subroutine and it is called during a clock interrupt. 205121Sbill */ 206903Sbill ttrstrt(tp) 207121Sbill register struct tty *tp; 208121Sbill { 209121Sbill 2103351Swnj if (tp == 0) { 2113351Swnj printf("ttrstrt: arg was 0!\n"); 2123351Swnj return; 2133351Swnj } 2145408Swnj tp->t_state &= ~TS_TIMEOUT; 215903Sbill ttstart(tp); 216121Sbill } 217121Sbill 218121Sbill /* 219903Sbill * Start output on the typewriter. It is used from the top half 220903Sbill * after some characters have been put on the output queue, 221903Sbill * from the interrupt routine to transmit the next 222903Sbill * character, and after a timeout has finished. 22339Sbill */ 224903Sbill ttstart(tp) 225903Sbill register struct tty *tp; 22639Sbill { 227903Sbill register s; 22839Sbill 229903Sbill s = spl5(); 2305622Swnj if((tp->t_state&(TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) == 0 && 2315622Swnj tp->t_oproc) /* kludge for pty */ 232903Sbill (*tp->t_oproc)(tp); 233903Sbill splx(s); 23439Sbill } 23539Sbill 23639Sbill /* 237903Sbill * Common code for tty ioctls. 23839Sbill */ 2391780Sbill /*ARGSUSED*/ 2401904Swnj ttioctl(tp, com, addr, flag) 24139Sbill register struct tty *tp; 24239Sbill caddr_t addr; 24339Sbill { 2441904Swnj int dev; 24539Sbill unsigned t; 246174Sbill struct sgttyb iocb; 247191Sbill struct clist tq; 24839Sbill extern int nldisp; 249887Sbill register c; 250728Sbill int temp; 25139Sbill 252903Sbill /* 253915Sbill * This is especially so that isatty() will 254915Sbill * fail when carrier is gone. 255915Sbill */ 2565408Swnj if ((tp->t_state&TS_CARR_ON) == 0) { 257915Sbill u.u_error = EBADF; 258915Sbill return (1); 259915Sbill } 260915Sbill 2611904Swnj dev = tp->t_dev; 262915Sbill /* 263903Sbill * If the ioctl involves modification, 264903Sbill * insist on being able to write the device, 265903Sbill * and hang if in the background. 266903Sbill */ 26739Sbill switch(com) { 26839Sbill 269915Sbill case TIOCSETD: 270915Sbill case TIOCSETP: 271915Sbill case TIOCSETN: 272903Sbill case TIOCFLUSH: 273903Sbill case TIOCSETC: 274903Sbill case TIOCSLTC: 275903Sbill case TIOCSPGRP: 276903Sbill case TIOCLBIS: 277903Sbill case TIOCLBIC: 278903Sbill case TIOCLSET: 279903Sbill case TIOCSTI: 280915Sbill /* this is reasonable, but impractical... 281903Sbill if ((flag & FWRITE) == 0) { 282903Sbill u.u_error = EBADF; 283903Sbill return (1); 284903Sbill } 285915Sbill */ 286903Sbill while (tp->t_line == NTTYDISC && 287903Sbill u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp && 288903Sbill (u.u_procp->p_flag&SVFORK) == 0 && 289903Sbill u.u_signal[SIGTTOU] != SIG_IGN && 2905626Swnj u.u_signal[SIGTTOU] != SIG_HOLD 2915626Swnj /* 2925626Swnj && 293903Sbill (u.u_procp->p_flag&SDETACH)==0) { 2945626Swnj */ 2955626Swnj ) { 296903Sbill gsignal(u.u_procp->p_pgrp, SIGTTOU); 297903Sbill sleep((caddr_t)&lbolt, TTOPRI); 298903Sbill } 299903Sbill break; 300903Sbill } 301903Sbill 30239Sbill /* 303903Sbill * Process the ioctl. 30439Sbill */ 305903Sbill switch(com) { 306903Sbill 307903Sbill /* 308903Sbill * Get discipline number 309903Sbill */ 31039Sbill case TIOCGETD: 31139Sbill t = tp->t_line; 31239Sbill if (copyout((caddr_t)&t, addr, sizeof(t))) 31339Sbill u.u_error = EFAULT; 31439Sbill break; 31539Sbill 31639Sbill /* 317903Sbill * Set line discipline 31839Sbill */ 31939Sbill case TIOCSETD: 32039Sbill if (copyin(addr, (caddr_t)&t, sizeof(t))) { 32139Sbill u.u_error = EFAULT; 32239Sbill break; 32339Sbill } 32439Sbill if (t >= nldisp) { 32539Sbill u.u_error = ENXIO; 32639Sbill break; 32739Sbill } 328174Sbill (void) spl5(); 32939Sbill if (tp->t_line) 33039Sbill (*linesw[tp->t_line].l_close)(tp); 33139Sbill if (t) 33239Sbill (*linesw[t].l_open)(dev, tp, addr); 33339Sbill if (u.u_error==0) 33439Sbill tp->t_line = t; 335174Sbill (void) spl0(); 33639Sbill break; 33739Sbill 33839Sbill /* 3395614Swnj * Prevent more opens on channel 3405614Swnj */ 3415614Swnj case TIOCEXCL: 3425614Swnj tp->t_state |= TS_XCLUDE; 3435614Swnj break; 3445614Swnj 3455614Swnj case TIOCNXCL: 3465614Swnj tp->t_state &= ~TS_XCLUDE; 3475614Swnj break; 3485614Swnj 3495614Swnj /* 35039Sbill * Set new parameters 35139Sbill */ 35239Sbill case TIOCSETP: 353191Sbill case TIOCSETN: 35439Sbill if (copyin(addr, (caddr_t)&iocb, sizeof(iocb))) { 35539Sbill u.u_error = EFAULT; 35639Sbill return(1); 35739Sbill } 358121Sbill (void) spl5(); 3594484Swnj if (tp->t_flags&RAW || iocb.sg_flags&RAW || 3604484Swnj com == TIOCSETP) 3614484Swnj wflushtty(tp); 3624484Swnj else if ((tp->t_flags&CBREAK) != (iocb.sg_flags&CBREAK)) { 3634484Swnj if (iocb.sg_flags & CBREAK) { 3644484Swnj catq(&tp->t_rawq, &tp->t_canq); 3654484Swnj tq = tp->t_rawq; 3664484Swnj tp->t_rawq = tp->t_canq; 3674484Swnj tp->t_canq = tq; 3684484Swnj } else { 3694484Swnj tp->t_local |= LPENDIN; 3704484Swnj ttwakeup(tp); 371174Sbill } 372174Sbill } 3734484Swnj tp->t_ispeed = iocb.sg_ispeed; 3744484Swnj tp->t_ospeed = iocb.sg_ospeed; 375174Sbill tp->t_erase = iocb.sg_erase; 376174Sbill tp->t_kill = iocb.sg_kill; 377174Sbill tp->t_flags = iocb.sg_flags; 3783941Sbugs if (tp->t_flags & RAW) { 3795408Swnj tp->t_state &= ~TS_TTSTOP; 3803941Sbugs ttstart(tp); 3813941Sbugs } 382121Sbill (void) spl0(); 38339Sbill break; 38439Sbill 38539Sbill /* 386903Sbill * Send current parameters to user 38739Sbill */ 38839Sbill case TIOCGETP: 389174Sbill iocb.sg_ispeed = tp->t_ispeed; 390174Sbill iocb.sg_ospeed = tp->t_ospeed; 391174Sbill iocb.sg_erase = tp->t_erase; 392174Sbill iocb.sg_kill = tp->t_kill; 393174Sbill iocb.sg_flags = tp->t_flags; 39439Sbill if (copyout((caddr_t)&iocb, addr, sizeof(iocb))) 39539Sbill u.u_error = EFAULT; 39639Sbill break; 39739Sbill 39839Sbill /* 39939Sbill * Hang up line on last close 40039Sbill */ 40139Sbill case TIOCHPCL: 4025408Swnj tp->t_state |= TS_HUPCLS; 40339Sbill break; 40439Sbill 4053942Sbugs case TIOCFLUSH: { 4063942Sbugs int flags; 4073942Sbugs if (addr == 0) 4083942Sbugs flags = FREAD|FWRITE; 4093942Sbugs else if (copyin(addr, (caddr_t)&flags, sizeof (flags))) { 4103942Sbugs u.u_error = EFAULT; 4113983Sroot return(1); 4123942Sbugs } 4133942Sbugs flushtty(tp, flags); 41439Sbill break; 4153944Sbugs } 41639Sbill 4175408Swnj case FIONBIO: { 4185408Swnj int nbio; 4195408Swnj if (copyin(addr, (caddr_t)&nbio, sizeof (nbio))) { 4205408Swnj u.u_error = EFAULT; 4215408Swnj return(1); 4225408Swnj } 4235408Swnj if (nbio) 4245408Swnj tp->t_state |= TS_NBIO; 4255408Swnj else 4265408Swnj tp->t_state &= ~TS_NBIO; 4275408Swnj break; 4285408Swnj } 4295408Swnj 4306216Swnj case FIOASYNC: { 4316216Swnj int async; 4326216Swnj if (copyin(addr, (caddr_t)&async, sizeof (async))) { 4336216Swnj u.u_error = EFAULT; 4346216Swnj return(1); 4356216Swnj } 4366216Swnj if (async) 4376216Swnj tp->t_state |= TS_ASYNC; 4386216Swnj else 4396216Swnj tp->t_state &= ~TS_ASYNC; 4406216Swnj break; 4416216Swnj } 4426216Swnj 44339Sbill /* 444903Sbill * Set and fetch special characters 44539Sbill */ 44639Sbill case TIOCSETC: 447174Sbill if (copyin(addr, (caddr_t)&tun, sizeof(struct tchars))) 44839Sbill u.u_error = EFAULT; 44939Sbill break; 45039Sbill 45139Sbill case TIOCGETC: 452174Sbill if (copyout((caddr_t)&tun, addr, sizeof(struct tchars))) 45339Sbill u.u_error = EFAULT; 45439Sbill break; 45539Sbill 456174Sbill /* local ioctls */ 457903Sbill /* 458903Sbill * Set/get local special characters. 459903Sbill */ 460174Sbill case TIOCSLTC: 461174Sbill if (copyin(addr, (caddr_t)&tlun, sizeof (struct ltchars))) 462174Sbill u.u_error = EFAULT; 463174Sbill break; 464174Sbill 465174Sbill case TIOCGLTC: 466174Sbill if (copyout((caddr_t)&tlun, addr, sizeof (struct ltchars))) 467174Sbill u.u_error = EFAULT; 468174Sbill break; 469174Sbill 470903Sbill /* 471903Sbill * Return number of characters immediately available. 472903Sbill */ 473174Sbill case FIONREAD: { 4744484Swnj off_t nread = ttnread(tp); 475174Sbill if (copyout((caddr_t)&nread, addr, sizeof (off_t))) 476174Sbill u.u_error = EFAULT; 477174Sbill break; 478174Sbill } 479174Sbill 480174Sbill /* 481174Sbill * Should allow SPGRP and GPGRP only if tty open for reading. 482174Sbill */ 483174Sbill case TIOCSPGRP: 484728Sbill if (copyin(addr, (caddr_t)&tp->t_pgrp, sizeof (tp->t_pgrp))) 485728Sbill u.u_error = EFAULT; 486174Sbill break; 487174Sbill 488174Sbill case TIOCGPGRP: 489174Sbill if (copyout((caddr_t)&tp->t_pgrp, addr, sizeof(tp->t_pgrp))) 490174Sbill u.u_error = EFAULT; 491174Sbill break; 492174Sbill 493174Sbill /* 494174Sbill * Modify local mode word. 495174Sbill */ 496174Sbill case TIOCLBIS: 497728Sbill if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local))) 498728Sbill u.u_error = EFAULT; 499728Sbill else 500728Sbill tp->t_local |= temp; 501174Sbill break; 502174Sbill 503174Sbill case TIOCLBIC: 504728Sbill if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local))) 505728Sbill u.u_error = EFAULT; 506728Sbill else 507728Sbill tp->t_local &= ~temp; 508174Sbill break; 509174Sbill 510174Sbill case TIOCLSET: 511728Sbill if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local))) 512728Sbill u.u_error = EFAULT; 513728Sbill else 514728Sbill tp->t_local = temp; 515174Sbill break; 516174Sbill 517174Sbill case TIOCLGET: 518174Sbill if (copyout((caddr_t)&tp->t_local, addr, sizeof(tp->t_local))) 519174Sbill u.u_error = EFAULT; 520174Sbill break; 521174Sbill 522903Sbill /* 523903Sbill * Return number of characters in 524903Sbill * the output. 525903Sbill */ 526213Sbill case TIOCOUTQ: 527213Sbill if (copyout((caddr_t)&tp->t_outq.c_cc, addr, sizeof(tp->t_outq.c_cc))) 528213Sbill u.u_error = EFAULT; 529213Sbill break; 530213Sbill 531903Sbill /* 532903Sbill * Simulate typing of a character at the terminal. 533903Sbill */ 534887Sbill case TIOCSTI: 535887Sbill c = fubyte(addr); 536887Sbill if (u.u_uid && u.u_ttyp != tp || c < 0) 537887Sbill u.u_error = EFAULT; 538887Sbill else 539887Sbill (*linesw[tp->t_line].l_rint)(c, tp); 540887Sbill break; 5415573Swnj 5425573Swnj case TIOCSTOP: 5435573Swnj c = spl5(); 5445573Swnj if ((tp->t_state & TS_TTSTOP) == 0) { 5455573Swnj tp->t_state |= TS_TTSTOP; 5465573Swnj (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 5475573Swnj } 5485573Swnj splx(c); 5495573Swnj break; 5505573Swnj 5515573Swnj case TIOCSTART: 5525573Swnj c = spl5(); 5535573Swnj if ((tp->t_state & TS_TTSTOP) || (tp->t_local & LFLUSHO)) { 5545573Swnj tp->t_state &= ~TS_TTSTOP; 5555573Swnj tp->t_local &= ~LFLUSHO; 5565573Swnj ttstart(tp); 5575573Swnj } 5585573Swnj splx(c); 5595573Swnj break; 5605573Swnj 561174Sbill /* end of locals */ 562887Sbill 56339Sbill default: 56439Sbill return(0); 56539Sbill } 56639Sbill return(1); 56739Sbill } 5684484Swnj 5694484Swnj ttnread(tp) 5704484Swnj struct tty *tp; 5714484Swnj { 5724484Swnj int nread = 0; 5734484Swnj 5744484Swnj if (tp->t_local & LPENDIN) 5754484Swnj ttypend(tp); 5764484Swnj nread = tp->t_canq.c_cc; 5774484Swnj if (tp->t_flags & (RAW|CBREAK)) 5784484Swnj nread += tp->t_rawq.c_cc; 5794484Swnj return (nread); 5804484Swnj } 5814484Swnj 5825408Swnj ttselect(dev, rw) 5834484Swnj dev_t dev; 5845408Swnj int rw; 5854484Swnj { 5864484Swnj register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)]; 5874484Swnj int nread; 5885408Swnj int s = spl5(); 5894484Swnj 5905408Swnj switch (rw) { 5914484Swnj 5924484Swnj case FREAD: 5934484Swnj nread = ttnread(tp); 5944484Swnj if (nread > 0) 5955408Swnj goto win; 5964938Swnj if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait) 5975408Swnj tp->t_state |= TS_RCOLL; 5984484Swnj else 5994484Swnj tp->t_rsel = u.u_procp; 6005408Swnj break; 6014484Swnj 6025408Swnj case FWRITE: 6035408Swnj if (tp->t_outq.c_cc <= TTLOWAT(tp)) 6045408Swnj goto win; 6055408Swnj if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait) 6065408Swnj tp->t_state |= TS_WCOLL; 6075408Swnj else 6085408Swnj tp->t_wsel = u.u_procp; 6095408Swnj break; 6104484Swnj } 6115408Swnj splx(s); 6125408Swnj return (0); 6135408Swnj win: 6145408Swnj splx(s); 6155408Swnj return (1); 6164484Swnj } 6177436Skre 618*7502Sroot #define OBUFSIZ 100 619*7502Sroot 620*7502Sroot /* 621*7502Sroot * routine called on opens while tp->t_line == NTTYDISC 622*7502Sroot * establishes a process group for distribution of 623*7502Sroot * quits and interrupts from the tty. 624*7502Sroot * (actually, pp->p_pgrp can't be 0 when this routine 625*7502Sroot * is called since NTTYDISC is not the default discipline) 626*7502Sroot */ 627*7502Sroot ttyopen(dev, tp) 628*7502Sroot dev_t dev; 629*7502Sroot register struct tty *tp; 630*7502Sroot { 631*7502Sroot register struct proc *pp; 632*7502Sroot 633*7502Sroot pp = u.u_procp; 634*7502Sroot tp->t_dev = dev; 635*7502Sroot if(pp->p_pgrp == 0) { 636*7502Sroot u.u_ttyp = tp; 637*7502Sroot u.u_ttyd = dev; 638*7502Sroot if (tp->t_pgrp == 0) 639*7502Sroot tp->t_pgrp = pp->p_pid; 640*7502Sroot pp->p_pgrp = tp->t_pgrp; 641*7502Sroot } 642*7502Sroot tp->t_state &= ~TS_WOPEN; 643*7502Sroot tp->t_state |= TS_ISOPEN; 644*7502Sroot if (tp->t_line != NTTYDISC) 645*7502Sroot wflushtty(tp); 646*7502Sroot } 647*7502Sroot 648*7502Sroot /* 649*7502Sroot * clean tp on last close 650*7502Sroot */ 651*7502Sroot ttyclose(tp) 652*7502Sroot register struct tty *tp; 653*7502Sroot { 654*7502Sroot 655*7502Sroot if (tp->t_line) { 656*7502Sroot wflushtty(tp); 657*7502Sroot tp->t_line = 0; 658*7502Sroot return; 659*7502Sroot } 660*7502Sroot tp->t_pgrp = 0; 661*7502Sroot wflushtty(tp); 662*7502Sroot tp->t_state = 0; 663*7502Sroot } 664*7502Sroot 665*7502Sroot /* 666*7502Sroot * reinput pending characters after state switch 667*7502Sroot * call at spl5(). 668*7502Sroot */ 669*7502Sroot ttypend(tp) 670*7502Sroot register struct tty *tp; 671*7502Sroot { 672*7502Sroot struct clist tq; 673*7502Sroot register c; 674*7502Sroot 675*7502Sroot tp->t_local &= ~LPENDIN; 676*7502Sroot tp->t_lstate |= LSTYPEN; 677*7502Sroot tq = tp->t_rawq; 678*7502Sroot tp->t_rawq.c_cc = 0; 679*7502Sroot tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0; 680*7502Sroot while ((c = getc(&tq)) >= 0) 681*7502Sroot ttyinput(c, tp); 682*7502Sroot tp->t_lstate &= ~LSTYPEN; 683*7502Sroot } 684*7502Sroot 685*7502Sroot /* 686*7502Sroot * Place a character on raw TTY input queue, putting in delimiters 687*7502Sroot * and waking up top half as needed. 688*7502Sroot * Also echo if required. 689*7502Sroot * The arguments are the character and the appropriate 690*7502Sroot * tty structure. 691*7502Sroot */ 692*7502Sroot ttyinput(c, tp) 693*7502Sroot register c; 694*7502Sroot register struct tty *tp; 695*7502Sroot { 696*7502Sroot register int t_flags; 697*7502Sroot int i; 698*7502Sroot 699*7502Sroot if (tp->t_local&LPENDIN) 700*7502Sroot ttypend(tp); 701*7502Sroot tk_nin++; 702*7502Sroot c &= 0377; 703*7502Sroot t_flags = tp->t_flags; 704*7502Sroot if (t_flags&TANDEM) 705*7502Sroot ttyblock(tp); 706*7502Sroot if ((t_flags&RAW)==0) { 707*7502Sroot if ((tp->t_lstate&LSTYPEN) == 0) 708*7502Sroot c &= 0177; 709*7502Sroot /* check for literal nexting very first */ 710*7502Sroot if (tp->t_lstate&LSLNCH) { 711*7502Sroot c |= 0200; 712*7502Sroot tp->t_lstate &= ~LSLNCH; 713*7502Sroot } 714*7502Sroot if (tp->t_line == NTTYDISC && c==tlun.t_lnextc) { 715*7502Sroot if (tp->t_flags&ECHO) 716*7502Sroot ttyout("^\b", tp); 717*7502Sroot tp->t_lstate |= LSLNCH; 718*7502Sroot /* check for output control functions */ 719*7502Sroot } else if (c==tun.t_stopc) { 720*7502Sroot if ((tp->t_state&TS_TTSTOP)==0) { 721*7502Sroot tp->t_state |= TS_TTSTOP; 722*7502Sroot (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 723*7502Sroot return; 724*7502Sroot } 725*7502Sroot if (c!=tun.t_startc) 726*7502Sroot return; 727*7502Sroot } else if (c==tun.t_startc) { 728*7502Sroot tp->t_state &= ~TS_TTSTOP; 729*7502Sroot tp->t_local &= ~LFLUSHO; 730*7502Sroot ttstart(tp); 731*7502Sroot return; 732*7502Sroot } else if (tp->t_line == NTTYDISC && c==tlun.t_flushc) { 733*7502Sroot if (tp->t_local & LFLUSHO) 734*7502Sroot tp->t_local &= ~LFLUSHO; 735*7502Sroot else { 736*7502Sroot flushtty(tp, FWRITE); 737*7502Sroot ttyecho(c, tp); 738*7502Sroot if (tp->t_rawq.c_cc+tp->t_canq.c_cc) 739*7502Sroot ttyretype(tp); 740*7502Sroot tp->t_local |= LFLUSHO; 741*7502Sroot } 742*7502Sroot ttstart(tp); 743*7502Sroot return; 744*7502Sroot } else if (c==tun.t_intrc || c==tun.t_quitc || 745*7502Sroot (tp->t_line == NTTYDISC && c==tlun.t_suspc)) { 746*7502Sroot if ((tp->t_local & LNOFLSH) == 0) 747*7502Sroot flushtty(tp, 748*7502Sroot c==tlun.t_suspc ? FREAD : FREAD|FWRITE); 749*7502Sroot ttyecho(c, tp); 750*7502Sroot c = c==tun.t_intrc ? SIGINT : 751*7502Sroot ((c==tun.t_quitc) ? SIGQUIT : SIGTSTP); 752*7502Sroot ttsignal(tp, c); 753*7502Sroot /* check for buffer editing functions - cooked mode */ 754*7502Sroot } else if ((t_flags&CBREAK) == 0) { 755*7502Sroot if ((tp->t_lstate&LSQUOT) && 756*7502Sroot (c==tp->t_erase||c==tp->t_kill)) { 757*7502Sroot ttyrub(unputc(&tp->t_rawq), tp); 758*7502Sroot c |= 0200; 759*7502Sroot } 760*7502Sroot if (c==tp->t_erase) { 761*7502Sroot if (tp->t_rawq.c_cc) 762*7502Sroot ttyrub(unputc(&tp->t_rawq), tp); 763*7502Sroot } else if (c==tp->t_kill) { 764*7502Sroot if (tp->t_local&LCRTKIL && 765*7502Sroot tp->t_rawq.c_cc == tp->t_rocount) { 766*7502Sroot while (tp->t_rawq.c_cc) 767*7502Sroot ttyrub(unputc(&tp->t_rawq), tp); 768*7502Sroot } else { 769*7502Sroot ttyecho(c, tp); 770*7502Sroot ttyecho('\n', tp); 771*7502Sroot while (getc(&tp->t_rawq) > 0) 772*7502Sroot ; 773*7502Sroot tp->t_rocount = 0; 774*7502Sroot } 775*7502Sroot tp->t_lstate = 0; 776*7502Sroot } else if (tp->t_line == NTTYDISC && c==tlun.t_werasc) { 777*7502Sroot if (tp->t_rawq.c_cc == 0) 778*7502Sroot goto out; 779*7502Sroot do { 780*7502Sroot c = unputc(&tp->t_rawq); 781*7502Sroot if (c != ' ' && c != '\t') 782*7502Sroot goto erasenb; 783*7502Sroot ttyrub(c, tp); 784*7502Sroot } while (tp->t_rawq.c_cc); 785*7502Sroot goto out; 786*7502Sroot erasenb: 787*7502Sroot do { 788*7502Sroot ttyrub(c, tp); 789*7502Sroot if (tp->t_rawq.c_cc == 0) 790*7502Sroot goto out; 791*7502Sroot c = unputc(&tp->t_rawq); 792*7502Sroot } while (c != ' ' && c != '\t'); 793*7502Sroot (void) putc(c, &tp->t_rawq); 794*7502Sroot } else if (tp->t_line == NTTYDISC && c==tlun.t_rprntc) { 795*7502Sroot ttyretype(tp); 796*7502Sroot /* check for cooked mode input buffer overflow */ 797*7502Sroot } else if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG) { 798*7502Sroot ; 799*7502Sroot /* put data char in q for user and wakeup if a break char */ 800*7502Sroot } else if (putc(c, &tp->t_rawq) >= 0) { 801*7502Sroot if (tp->t_rawq.c_cc+tp->t_canq.c_cc==TTYHOG 802*7502Sroot && tp->t_line == NTTYDISC) 803*7502Sroot (void) ttyoutput(CTRL(g), tp); 804*7502Sroot if (!ttbreakc(c, tp)) { 805*7502Sroot if (tp->t_rocount++ == 0) 806*7502Sroot tp->t_rocol = tp->t_col; 807*7502Sroot } else { 808*7502Sroot tp->t_rocount = 0; 809*7502Sroot catq(&tp->t_rawq, &tp->t_canq); 810*7502Sroot /* IF (TP->T_CHAN) (VOID) SDATA(TP->T_CHAN); */ 811*7502Sroot ttwakeup(tp); 812*7502Sroot } 813*7502Sroot tp->t_lstate &= ~LSQUOT; 814*7502Sroot if (c == '\\') 815*7502Sroot tp->t_lstate |= LSQUOT; 816*7502Sroot if (tp->t_lstate&LSERASE) { 817*7502Sroot tp->t_lstate &= ~LSERASE; 818*7502Sroot (void) ttyoutput('/', tp); 819*7502Sroot } 820*7502Sroot i = tp->t_col; 821*7502Sroot ttyecho(c, tp); 822*7502Sroot if (c==tun.t_eofc && tp->t_flags&ECHO) { 823*7502Sroot i = MIN(2, tp->t_col - i); 824*7502Sroot while (i > 0) { 825*7502Sroot (void) ttyoutput('\b', tp); 826*7502Sroot i--; 827*7502Sroot } 828*7502Sroot } 829*7502Sroot } 830*7502Sroot /* CBREAK mode */ 831*7502Sroot } else if (tp->t_rawq.c_cc > TTYHOG) { 832*7502Sroot if (tp->t_outq.c_cc < TTHIWAT(tp) && 833*7502Sroot tp->t_line == NTTYDISC) 834*7502Sroot (void) ttyoutput(CTRL(g), tp); 835*7502Sroot } else if (putc(c, &tp->t_rawq) >= 0) { 836*7502Sroot ttwakeup(tp); 837*7502Sroot ttyecho(c, tp); 838*7502Sroot } 839*7502Sroot /* RAW mode */ 840*7502Sroot } else if (tp->t_rawq.c_cc > TTYHOG) 841*7502Sroot flushtty(tp, FREAD|FWRITE); 842*7502Sroot else { 843*7502Sroot if (putc(c, &tp->t_rawq) >= 0) 844*7502Sroot ttwakeup(tp); 845*7502Sroot ttyecho(c, tp); 846*7502Sroot } 847*7502Sroot out: 848*7502Sroot if (tp->t_local & LDECCTQ && tp->t_state & TS_TTSTOP && 849*7502Sroot tun.t_startc != tun.t_stopc) 850*7502Sroot return; 851*7502Sroot tp->t_state &= ~TS_TTSTOP; 852*7502Sroot tp->t_local &= ~LFLUSHO; 853*7502Sroot ttstart(tp); 854*7502Sroot } 855*7502Sroot 856*7502Sroot /* 857*7502Sroot * put character on TTY output queue, adding delays, 858*7502Sroot * expanding tabs, and handling the CR/NL bit. 859*7502Sroot * It is called both from the top half for output, and from 860*7502Sroot * interrupt level for echoing. 861*7502Sroot * The arguments are the character and the tty structure. 862*7502Sroot * Returns < 0 if putc succeeds, otherwise returns char to resend 863*7502Sroot * Must be recursive. 864*7502Sroot */ 865*7502Sroot ttyoutput(c, tp) 866*7502Sroot register c; 867*7502Sroot register struct tty *tp; 868*7502Sroot { 869*7502Sroot register char *colp; 870*7502Sroot register ctype; 871*7502Sroot 872*7502Sroot if (tp->t_flags&RAW || tp->t_local&LLITOUT) { 873*7502Sroot if (tp->t_local&LFLUSHO) 874*7502Sroot return (-1); 875*7502Sroot if (putc(c, &tp->t_outq)) 876*7502Sroot return(c); 877*7502Sroot tk_nout++; 878*7502Sroot return (-1); 879*7502Sroot } 880*7502Sroot /* 881*7502Sroot * Ignore EOT in normal mode to avoid hanging up 882*7502Sroot * certain terminals. 883*7502Sroot */ 884*7502Sroot c &= 0177; 885*7502Sroot if (c==CEOT && (tp->t_flags&CBREAK)==0) 886*7502Sroot return (-1); 887*7502Sroot /* 888*7502Sroot * Turn tabs to spaces as required 889*7502Sroot */ 890*7502Sroot if (c=='\t' && (tp->t_flags&TBDELAY)==XTABS) { 891*7502Sroot register int s; 892*7502Sroot 893*7502Sroot c = 8 - (tp->t_col&7); 894*7502Sroot if ((tp->t_local&LFLUSHO) == 0) { 895*7502Sroot s = spl5(); /* don't interrupt tabs */ 896*7502Sroot c -= b_to_q(" ", c, &tp->t_outq); 897*7502Sroot tk_nout += c; 898*7502Sroot splx(s); 899*7502Sroot } 900*7502Sroot tp->t_col += c; 901*7502Sroot return (c ? -1 : '\t'); 902*7502Sroot } 903*7502Sroot tk_nout++; 904*7502Sroot /* 905*7502Sroot * for upper-case-only terminals, 906*7502Sroot * generate escapes. 907*7502Sroot */ 908*7502Sroot if (tp->t_flags&LCASE) { 909*7502Sroot colp = "({)}!|^~'`"; 910*7502Sroot while(*colp++) 911*7502Sroot if(c == *colp++) { 912*7502Sroot if (ttyoutput('\\', tp) >= 0) 913*7502Sroot return (c); 914*7502Sroot c = colp[-2]; 915*7502Sroot break; 916*7502Sroot } 917*7502Sroot if ('A'<=c && c<='Z') { 918*7502Sroot if (ttyoutput('\\', tp) >= 0) 919*7502Sroot return (c); 920*7502Sroot } else if ('a'<=c && c<='z') 921*7502Sroot c += 'A' - 'a'; 922*7502Sroot } 923*7502Sroot /* 924*7502Sroot * turn <nl> to <cr><lf> if desired. 925*7502Sroot */ 926*7502Sroot if (c=='\n' && tp->t_flags&CRMOD) 927*7502Sroot if (ttyoutput('\r', tp) >= 0) 928*7502Sroot return (c); 929*7502Sroot if (c=='~' && tp->t_local<ILDE) 930*7502Sroot c = '`'; 931*7502Sroot if ((tp->t_local&LFLUSHO) == 0 && putc(c, &tp->t_outq)) 932*7502Sroot return (c); 933*7502Sroot /* 934*7502Sroot * Calculate delays. 935*7502Sroot * The numbers here represent clock ticks 936*7502Sroot * and are not necessarily optimal for all terminals. 937*7502Sroot * The delays are indicated by characters above 0200. 938*7502Sroot * In raw mode there are no delays and the 939*7502Sroot * transmission path is 8 bits wide. 940*7502Sroot */ 941*7502Sroot colp = &tp->t_col; 942*7502Sroot ctype = partab[c]; 943*7502Sroot c = 0; 944*7502Sroot switch (ctype&077) { 945*7502Sroot 946*7502Sroot case ORDINARY: 947*7502Sroot (*colp)++; 948*7502Sroot 949*7502Sroot case CONTROL: 950*7502Sroot break; 951*7502Sroot 952*7502Sroot case BACKSPACE: 953*7502Sroot if (*colp) 954*7502Sroot (*colp)--; 955*7502Sroot break; 956*7502Sroot 957*7502Sroot case NEWLINE: 958*7502Sroot ctype = (tp->t_flags >> 8) & 03; 959*7502Sroot if(ctype == 1) { /* tty 37 */ 960*7502Sroot if (*colp) 961*7502Sroot c = max(((unsigned)*colp>>4) + 3, (unsigned)6); 962*7502Sroot } else 963*7502Sroot if(ctype == 2) { /* vt05 */ 964*7502Sroot c = 6; 965*7502Sroot } 966*7502Sroot *colp = 0; 967*7502Sroot break; 968*7502Sroot 969*7502Sroot case TAB: 970*7502Sroot ctype = (tp->t_flags >> 10) & 03; 971*7502Sroot if(ctype == 1) { /* tty 37 */ 972*7502Sroot c = 1 - (*colp | ~07); 973*7502Sroot if(c < 5) 974*7502Sroot c = 0; 975*7502Sroot } 976*7502Sroot *colp |= 07; 977*7502Sroot (*colp)++; 978*7502Sroot break; 979*7502Sroot 980*7502Sroot case VTAB: 981*7502Sroot if(tp->t_flags & VTDELAY) /* tty 37 */ 982*7502Sroot c = 0177; 983*7502Sroot break; 984*7502Sroot 985*7502Sroot case RETURN: 986*7502Sroot ctype = (tp->t_flags >> 12) & 03; 987*7502Sroot if(ctype == 1) { /* tn 300 */ 988*7502Sroot c = 5; 989*7502Sroot } else if(ctype == 2) { /* ti 700 */ 990*7502Sroot c = 10; 991*7502Sroot } else if(ctype == 3) { /* concept 100 */ 992*7502Sroot int i; 993*7502Sroot if ((i = *colp) >= 0) 994*7502Sroot for (; i<9; i++) 995*7502Sroot (void) putc(0177, &tp->t_outq); 996*7502Sroot } 997*7502Sroot *colp = 0; 998*7502Sroot } 999*7502Sroot if(c && (tp->t_local&LFLUSHO) == 0) 1000*7502Sroot (void) putc(c|0200, &tp->t_outq); 1001*7502Sroot return (-1); 1002*7502Sroot } 1003*7502Sroot 1004*7502Sroot /* 1005*7502Sroot * Called from device's read routine after it has 1006*7502Sroot * calculated the tty-structure given as argument. 1007*7502Sroot */ 1008*7502Sroot ttread(tp) 1009*7502Sroot register struct tty *tp; 1010*7502Sroot { 1011*7502Sroot register struct clist *qp; 1012*7502Sroot register c, first; 1013*7502Sroot 1014*7502Sroot if ((tp->t_state&TS_CARR_ON)==0) 1015*7502Sroot return(0); 1016*7502Sroot loop: 1017*7502Sroot (void) spl5(); 1018*7502Sroot if (tp->t_local&LPENDIN) 1019*7502Sroot ttypend(tp); 1020*7502Sroot (void) spl0(); 1021*7502Sroot while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) { 1022*7502Sroot if (u.u_signal[SIGTTIN] == SIG_IGN || 1023*7502Sroot u.u_signal[SIGTTIN] == SIG_HOLD || 1024*7502Sroot /* 1025*7502Sroot (u.u_procp->p_flag&SDETACH) || 1026*7502Sroot */ 1027*7502Sroot u.u_procp->p_flag&SVFORK) 1028*7502Sroot return (0); 1029*7502Sroot gsignal(u.u_procp->p_pgrp, SIGTTIN); 1030*7502Sroot sleep((caddr_t)&lbolt, TTIPRI); 1031*7502Sroot } 1032*7502Sroot if (tp->t_flags&RAW) { 1033*7502Sroot (void) spl5(); 1034*7502Sroot if (tp->t_rawq.c_cc <= 0) { 1035*7502Sroot if ((tp->t_state&TS_CARR_ON)==0 || 1036*7502Sroot (tp->t_state&TS_NBIO)) { 1037*7502Sroot (void) spl0(); 1038*7502Sroot return (0); 1039*7502Sroot } 1040*7502Sroot sleep((caddr_t)&tp->t_rawq, TTIPRI); 1041*7502Sroot (void) spl0(); 1042*7502Sroot goto loop; 1043*7502Sroot } 1044*7502Sroot (void) spl0(); 1045*7502Sroot while (tp->t_rawq.c_cc && passc(getc(&tp->t_rawq))>=0) 1046*7502Sroot ; 1047*7502Sroot return (0); 1048*7502Sroot } else { 1049*7502Sroot qp = tp->t_flags & CBREAK ? &tp->t_rawq : &tp->t_canq; 1050*7502Sroot (void) spl5(); 1051*7502Sroot if (qp->c_cc <= 0) { 1052*7502Sroot if ((tp->t_state&TS_CARR_ON)==0 || 1053*7502Sroot (tp->t_state&TS_NBIO)) { 1054*7502Sroot (void) spl0(); 1055*7502Sroot return (0); 1056*7502Sroot } 1057*7502Sroot sleep((caddr_t)&tp->t_rawq, TTIPRI); 1058*7502Sroot (void) spl0(); 1059*7502Sroot goto loop; 1060*7502Sroot } 1061*7502Sroot (void) spl0(); 1062*7502Sroot first = 1; 1063*7502Sroot while ((c = getc(qp)) >= 0) { 1064*7502Sroot if (tp->t_flags&CRMOD && c == '\r') 1065*7502Sroot c = '\n'; 1066*7502Sroot if (tp->t_flags&LCASE && c <= 0177) 1067*7502Sroot if (tp->t_lstate&LSBKSL) { 1068*7502Sroot if (maptab[c]) 1069*7502Sroot c = maptab[c]; 1070*7502Sroot tp->t_lstate &= ~LSBKSL; 1071*7502Sroot } else if (c >= 'A' && c <= 'Z') 1072*7502Sroot c += 'a' - 'A'; 1073*7502Sroot else if (c == '\\') { 1074*7502Sroot tp->t_lstate |= LSBKSL; 1075*7502Sroot continue; 1076*7502Sroot } 1077*7502Sroot if (c == tlun.t_dsuspc) { 1078*7502Sroot ttsignal(tp, SIGTSTP); 1079*7502Sroot if (first) { 1080*7502Sroot sleep((caddr_t)&lbolt, TTIPRI); 1081*7502Sroot goto loop; 1082*7502Sroot } 1083*7502Sroot break; 1084*7502Sroot } 1085*7502Sroot if (c == tun.t_eofc && (tp->t_flags&CBREAK)==0) 1086*7502Sroot break; 1087*7502Sroot if (passc(c & 0177) < 0) 1088*7502Sroot break; 1089*7502Sroot if ((tp->t_flags&CBREAK)==0 && ttbreakc(c, tp)) 1090*7502Sroot break; 1091*7502Sroot first = 0; 1092*7502Sroot } 1093*7502Sroot tp->t_lstate &= ~LSBKSL; 1094*7502Sroot } 1095*7502Sroot 1096*7502Sroot if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) { 1097*7502Sroot if (putc(tun.t_startc, &tp->t_outq)==0) { 1098*7502Sroot tp->t_state &= ~TS_TBLOCK; 1099*7502Sroot ttstart(tp); 1100*7502Sroot } 1101*7502Sroot tp->t_char = 0; 1102*7502Sroot } 1103*7502Sroot 1104*7502Sroot return (tp->t_rawq.c_cc + tp->t_canq.c_cc); 1105*7502Sroot } 1106*7502Sroot 1107*7502Sroot /* 1108*7502Sroot * Called from the device's write routine after it has 1109*7502Sroot * calculated the tty-structure given as argument. 1110*7502Sroot */ 1111*7502Sroot caddr_t 1112*7502Sroot ttwrite(tp) 1113*7502Sroot register struct tty *tp; 1114*7502Sroot { 1115*7502Sroot #ifdef vax 1116*7502Sroot /* 1117*7502Sroot * THE POSITIONING OF CP, CC, AND CE ARE CRITICAL 1118*7502Sroot * AND MUST NOT BE CHANGED WITHOUT PATCHING 1119*7502Sroot * THE 'ASM' INLINES BELOW. WATCH OUT. 1120*7502Sroot */ 1121*7502Sroot #endif 1122*7502Sroot register char *cp; 1123*7502Sroot register int cc, ce; 1124*7502Sroot register i; 1125*7502Sroot char obuf[OBUFSIZ]; 1126*7502Sroot register c; 1127*7502Sroot int hiwat = TTHIWAT(tp); 1128*7502Sroot int cnt = u.u_count; 1129*7502Sroot 1130*7502Sroot if ((tp->t_state&TS_CARR_ON)==0) 1131*7502Sroot return (NULL); 1132*7502Sroot loop: 1133*7502Sroot while (u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp && 1134*7502Sroot (tp->t_local<OSTOP) && (u.u_procp->p_flag&SVFORK)==0 && 1135*7502Sroot u.u_signal[SIGTTOU] != SIG_IGN && 1136*7502Sroot u.u_signal[SIGTTOU] != SIG_HOLD 1137*7502Sroot /* 1138*7502Sroot && 1139*7502Sroot (u.u_procp->p_flag&SDETACH)==0) { 1140*7502Sroot */ 1141*7502Sroot ) { 1142*7502Sroot gsignal(u.u_procp->p_pgrp, SIGTTOU); 1143*7502Sroot sleep((caddr_t)&lbolt, TTIPRI); 1144*7502Sroot } 1145*7502Sroot while (u.u_count) { 1146*7502Sroot cc = MIN(u.u_count, OBUFSIZ); 1147*7502Sroot cp = obuf; 1148*7502Sroot iomove(cp, (unsigned)cc, B_WRITE); 1149*7502Sroot if (u.u_error) 1150*7502Sroot break; 1151*7502Sroot if (tp->t_outq.c_cc > hiwat) 1152*7502Sroot goto ovhiwat; 1153*7502Sroot if (tp->t_local&LFLUSHO) 1154*7502Sroot continue; 1155*7502Sroot if (tp->t_flags&LCASE || tp->t_local<ILDE) { 1156*7502Sroot while (cc) { 1157*7502Sroot c = *cp++; 1158*7502Sroot tp->t_rocount = 0; 1159*7502Sroot while((c = ttyoutput(c, tp)) >= 0) { 1160*7502Sroot /* out of clists, wait a bit */ 1161*7502Sroot ttstart(tp); 1162*7502Sroot sleep((caddr_t)&lbolt, TTOPRI); 1163*7502Sroot tp->t_rocount = 0; 1164*7502Sroot } 1165*7502Sroot --cc; 1166*7502Sroot if (tp->t_outq.c_cc > hiwat) 1167*7502Sroot goto ovhiwat; 1168*7502Sroot } 1169*7502Sroot continue; 1170*7502Sroot } 1171*7502Sroot while (cc) { 1172*7502Sroot if (tp->t_flags&RAW || tp->t_local&LLITOUT) 1173*7502Sroot ce = cc; 1174*7502Sroot else { 1175*7502Sroot #ifdef vax 1176*7502Sroot asm(" scanc r9,(r10),_partab,$077"); 1177*7502Sroot asm(" subl3 r0,r9,r8"); 1178*7502Sroot #else 1179*7502Sroot ce=0; 1180*7502Sroot while(((partab[*(unsigned char *)(cp+ce)]&077)==0)&&(ce<cc)) 1181*7502Sroot ce++; 1182*7502Sroot #endif 1183*7502Sroot if (ce==0) { 1184*7502Sroot tp->t_rocount = 0; 1185*7502Sroot if (ttyoutput(*cp, tp) >= 0) { 1186*7502Sroot ttstart(tp); 1187*7502Sroot sleep((caddr_t)&lbolt, TTOPRI); 1188*7502Sroot continue; 1189*7502Sroot } 1190*7502Sroot cp++; 1191*7502Sroot cc--; 1192*7502Sroot if (tp->t_outq.c_cc > hiwat) 1193*7502Sroot goto ovhiwat; 1194*7502Sroot } 1195*7502Sroot } 1196*7502Sroot tp->t_rocount = 0; 1197*7502Sroot i=b_to_q(cp,ce,&tp->t_outq); 1198*7502Sroot ce-=i; 1199*7502Sroot tk_nout+=ce; 1200*7502Sroot tp->t_col+=ce; 1201*7502Sroot cp+=ce; 1202*7502Sroot cc-=ce; 1203*7502Sroot if (i) { 1204*7502Sroot ttstart(tp); 1205*7502Sroot sleep((caddr_t)&lbolt, TTOPRI); 1206*7502Sroot } 1207*7502Sroot if (ce || tp->t_outq.c_cc > hiwat) 1208*7502Sroot goto ovhiwat; 1209*7502Sroot } 1210*7502Sroot } 1211*7502Sroot ttstart(tp); 1212*7502Sroot return(NULL); 1213*7502Sroot 1214*7502Sroot ovhiwat: 1215*7502Sroot (void) spl5(); 1216*7502Sroot u.u_base -= cc; 1217*7502Sroot u.u_offset -= cc; 1218*7502Sroot u.u_count += cc; 1219*7502Sroot if (tp->t_outq.c_cc <= hiwat) { 1220*7502Sroot (void) spl0(); 1221*7502Sroot goto loop; 1222*7502Sroot } 1223*7502Sroot ttstart(tp); 1224*7502Sroot if (tp->t_state & TS_NBIO) { 1225*7502Sroot if (u.u_count == cnt) 1226*7502Sroot u.u_error = EWOULDBLOCK; 1227*7502Sroot return (NULL); 1228*7502Sroot } 1229*7502Sroot tp->t_state |= TS_ASLEEP; 1230*7502Sroot sleep((caddr_t)&tp->t_outq, TTOPRI); 1231*7502Sroot (void) spl0(); 1232*7502Sroot goto loop; 1233*7502Sroot } 1234*7502Sroot 1235*7502Sroot /* 1236*7502Sroot * Rubout one character from the rawq of tp 1237*7502Sroot * as cleanly as possible. 1238*7502Sroot */ 1239*7502Sroot ttyrub(c, tp) 1240*7502Sroot register c; 1241*7502Sroot register struct tty *tp; 1242*7502Sroot { 1243*7502Sroot register char *cp; 1244*7502Sroot register int savecol; 1245*7502Sroot int s; 1246*7502Sroot char *nextc(); 1247*7502Sroot 1248*7502Sroot if ((tp->t_flags&ECHO)==0) 1249*7502Sroot return; 1250*7502Sroot tp->t_local &= ~LFLUSHO; 1251*7502Sroot c &= 0377; 1252*7502Sroot if (tp->t_local&LCRTBS) { 1253*7502Sroot if (tp->t_rocount == 0) { 1254*7502Sroot /* 1255*7502Sroot * Screwed by ttwrite; retype 1256*7502Sroot */ 1257*7502Sroot ttyretype(tp); 1258*7502Sroot return; 1259*7502Sroot } 1260*7502Sroot if (c==('\t'|0200) || c==('\n'|0200)) 1261*7502Sroot ttyrubo(tp, 2); 1262*7502Sroot else switch(partab[c&=0177] & 0177) { 1263*7502Sroot 1264*7502Sroot case ORDINARY: 1265*7502Sroot if (tp->t_flags&LCASE && c >= 'A' && c <= 'Z') 1266*7502Sroot ttyrubo(tp, 2); 1267*7502Sroot else 1268*7502Sroot ttyrubo(tp, 1); 1269*7502Sroot break; 1270*7502Sroot 1271*7502Sroot case VTAB: 1272*7502Sroot case BACKSPACE: 1273*7502Sroot case CONTROL: 1274*7502Sroot case RETURN: 1275*7502Sroot if (tp->t_local & LCTLECH) 1276*7502Sroot ttyrubo(tp, 2); 1277*7502Sroot break; 1278*7502Sroot 1279*7502Sroot case TAB: 1280*7502Sroot if (tp->t_rocount < tp->t_rawq.c_cc) { 1281*7502Sroot ttyretype(tp); 1282*7502Sroot return; 1283*7502Sroot } 1284*7502Sroot s = spl5(); 1285*7502Sroot savecol = tp->t_col; 1286*7502Sroot tp->t_lstate |= LSCNTTB; 1287*7502Sroot tp->t_local |= LFLUSHO; 1288*7502Sroot tp->t_col = tp->t_rocol; 1289*7502Sroot for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp)) 1290*7502Sroot ttyecho(*cp, tp); 1291*7502Sroot tp->t_local &= ~LFLUSHO; 1292*7502Sroot tp->t_lstate &= ~LSCNTTB; 1293*7502Sroot splx(s); 1294*7502Sroot /* 1295*7502Sroot * savecol will now be length of the tab 1296*7502Sroot */ 1297*7502Sroot savecol -= tp->t_col; 1298*7502Sroot tp->t_col += savecol; 1299*7502Sroot if (savecol > 8) 1300*7502Sroot savecol = 8; /* overflow screw */ 1301*7502Sroot while (--savecol >= 0) 1302*7502Sroot (void) ttyoutput('\b', tp); 1303*7502Sroot break; 1304*7502Sroot 1305*7502Sroot default: 1306*7502Sroot panic("ttyrub"); 1307*7502Sroot } 1308*7502Sroot } else if (tp->t_local&LPRTERA) { 1309*7502Sroot if ((tp->t_lstate&LSERASE) == 0) { 1310*7502Sroot (void) ttyoutput('\\', tp); 1311*7502Sroot tp->t_lstate |= LSERASE; 1312*7502Sroot } 1313*7502Sroot ttyecho(c, tp); 1314*7502Sroot } else 1315*7502Sroot ttyecho(tp->t_erase, tp); 1316*7502Sroot tp->t_rocount--; 1317*7502Sroot } 1318*7502Sroot 1319*7502Sroot /* 1320*7502Sroot * Crt back over cnt chars perhaps 1321*7502Sroot * erasing them. 1322*7502Sroot */ 1323*7502Sroot ttyrubo(tp, cnt) 1324*7502Sroot register struct tty *tp; 1325*7502Sroot int cnt; 1326*7502Sroot { 1327*7502Sroot 1328*7502Sroot while (--cnt >= 0) 1329*7502Sroot ttyout(tp->t_local&LCRTERA ? "\b \b" : "\b", tp); 1330*7502Sroot } 1331*7502Sroot 1332*7502Sroot /* 1333*7502Sroot * Reprint the rawq line. 1334*7502Sroot * We assume c_cc has already been checked. 1335*7502Sroot */ 1336*7502Sroot ttyretype(tp) 1337*7502Sroot register struct tty *tp; 1338*7502Sroot { 1339*7502Sroot register char *cp; 1340*7502Sroot char *nextc(); 1341*7502Sroot int s; 1342*7502Sroot 1343*7502Sroot if (tlun.t_rprntc != 0377) 1344*7502Sroot ttyecho(tlun.t_rprntc, tp); 1345*7502Sroot (void) ttyoutput('\n', tp); 1346*7502Sroot s = spl5(); 1347*7502Sroot for (cp = tp->t_canq.c_cf; cp; cp = nextc(&tp->t_canq, cp)) 1348*7502Sroot ttyecho(*cp, tp); 1349*7502Sroot for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp)) 1350*7502Sroot ttyecho(*cp, tp); 1351*7502Sroot tp->t_lstate &= ~LSERASE; 1352*7502Sroot splx(s); 1353*7502Sroot tp->t_rocount = tp->t_rawq.c_cc; 1354*7502Sroot tp->t_rocol = 0; 1355*7502Sroot } 1356*7502Sroot 1357*7502Sroot /* 1358*7502Sroot * Echo a typed character to the terminal 1359*7502Sroot */ 1360*7502Sroot ttyecho(c, tp) 1361*7502Sroot register c; 1362*7502Sroot register struct tty *tp; 1363*7502Sroot { 1364*7502Sroot 1365*7502Sroot if ((tp->t_lstate & LSCNTTB) == 0) 1366*7502Sroot tp->t_local &= ~LFLUSHO; 1367*7502Sroot if ((tp->t_flags&ECHO) == 0) 1368*7502Sroot return; 1369*7502Sroot c &= 0377; 1370*7502Sroot if (tp->t_flags&RAW) { 1371*7502Sroot (void) ttyoutput(c, tp); 1372*7502Sroot return; 1373*7502Sroot } 1374*7502Sroot if (c == '\r' && tp->t_flags&CRMOD) 1375*7502Sroot c = '\n'; 1376*7502Sroot if (tp->t_local&LCTLECH) { 1377*7502Sroot if ((c&0177) <= 037 && c!='\t' && c!='\n' || (c&0177)==0177) { 1378*7502Sroot (void) ttyoutput('^', tp); 1379*7502Sroot c &= 0177; 1380*7502Sroot if (c == 0177) 1381*7502Sroot c = '?'; 1382*7502Sroot else if (tp->t_flags&LCASE) 1383*7502Sroot c += 'a' - 1; 1384*7502Sroot else 1385*7502Sroot c += 'A' - 1; 1386*7502Sroot } 1387*7502Sroot } 1388*7502Sroot if ((tp->t_flags&LCASE) && (c >= 'A' && c <= 'Z')) 1389*7502Sroot c += 'a' - 'A'; 1390*7502Sroot (void) ttyoutput(c & 0177, tp); 1391*7502Sroot } 1392*7502Sroot 1393*7502Sroot /* 1394*7502Sroot * Is c a break char for tp? 1395*7502Sroot */ 1396*7502Sroot ttbreakc(c, tp) 1397*7502Sroot register c; 1398*7502Sroot register struct tty *tp; 1399*7502Sroot { 1400*7502Sroot return (c == '\n' || c == tun.t_eofc || c == tun.t_brkc || 1401*7502Sroot c == '\r' && (tp->t_flags&CRMOD)); 1402*7502Sroot } 1403*7502Sroot 1404*7502Sroot /* 1405*7502Sroot * send string cp to tp 1406*7502Sroot */ 1407*7502Sroot ttyout(cp, tp) 1408*7502Sroot register char *cp; 1409*7502Sroot register struct tty *tp; 1410*7502Sroot { 1411*7502Sroot register char c; 1412*7502Sroot 1413*7502Sroot while (c = *cp++) 1414*7502Sroot (void) ttyoutput(c, tp); 1415*7502Sroot } 1416*7502Sroot 1417*7502Sroot ttwakeup(tp) 1418*7502Sroot struct tty *tp; 1419*7502Sroot { 1420*7502Sroot 1421*7502Sroot if (tp->t_rsel) { 1422*7502Sroot selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL); 1423*7502Sroot tp->t_state &= ~TS_RCOLL; 1424*7502Sroot tp->t_rsel = 0; 1425*7502Sroot } 1426*7502Sroot wakeup((caddr_t)&tp->t_rawq); 1427*7502Sroot } 1428*7502Sroot 1429*7502Sroot ttsignal(tp, signo) 1430*7502Sroot struct tty *tp; 1431*7502Sroot int signo; 1432*7502Sroot { 1433*7502Sroot 1434*7502Sroot gsignal(tp->t_pgrp, signo); 1435*7502Sroot } 1436