1*903Sbill /* tty.c 3.17 09/20/80 */ 239Sbill 339Sbill /* 4*903Sbill * 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/mx.h" 1339Sbill #include "../h/inode.h" 1439Sbill #include "../h/file.h" 1539Sbill #include "../h/reg.h" 1639Sbill #include "../h/conf.h" 1739Sbill #include "../h/buf.h" 18340Sbill #include "../h/dk.h" 1939Sbill 2039Sbill char partab[]; 2139Sbill 22146Sbill /* 23146Sbill * When running dz's using only SAE (silo alarm) on input 24146Sbill * it is necessary to call dzrint() at clock interrupt time. 25146Sbill * This is unsafe unless spl5()s in tty code are changed to 26146Sbill * spl6()s to block clock interrupts. Note that the dh driver 27146Sbill * currently in use works the same way as the dz, even though 28146Sbill * we could try to more intelligently manage its silo. 29146Sbill * Thus don't take this out if you have no dz's unless you 30146Sbill * change clock.c and dhtimer(). 31146Sbill */ 32146Sbill #define spl5 spl6 3339Sbill 3439Sbill /* 3539Sbill * Input mapping table-- if an entry is non-zero, when the 3639Sbill * corresponding character is typed preceded by "\" the escape 3739Sbill * sequence is replaced by the table value. Mostly used for 3839Sbill * upper-case only terminals. 3939Sbill */ 4039Sbill 4139Sbill char maptab[] ={ 4239Sbill 000,000,000,000,000,000,000,000, 4339Sbill 000,000,000,000,000,000,000,000, 4439Sbill 000,000,000,000,000,000,000,000, 4539Sbill 000,000,000,000,000,000,000,000, 4639Sbill 000,'|',000,000,000,000,000,'`', 4739Sbill '{','}',000,000,000,000,000,000, 4839Sbill 000,000,000,000,000,000,000,000, 4939Sbill 000,000,000,000,000,000,000,000, 5039Sbill 000,000,000,000,000,000,000,000, 5139Sbill 000,000,000,000,000,000,000,000, 5239Sbill 000,000,000,000,000,000,000,000, 5339Sbill 000,000,000,000,000,000,'~',000, 5439Sbill 000,'A','B','C','D','E','F','G', 5539Sbill 'H','I','J','K','L','M','N','O', 5639Sbill 'P','Q','R','S','T','U','V','W', 5739Sbill 'X','Y','Z',000,000,000,000,000, 5839Sbill }; 5939Sbill 6039Sbill #define OBUFSIZ 100 6139Sbill 6239Sbill /* 6339Sbill * set default control characters. 6439Sbill */ 6539Sbill ttychars(tp) 6639Sbill register struct tty *tp; 6739Sbill { 68174Sbill 6939Sbill tun.t_intrc = CINTR; 7039Sbill tun.t_quitc = CQUIT; 7139Sbill tun.t_startc = CSTART; 7239Sbill tun.t_stopc = CSTOP; 7339Sbill tun.t_eofc = CEOT; 7439Sbill tun.t_brkc = CBRK; 7539Sbill tp->t_erase = CERASE; 7639Sbill tp->t_kill = CKILL; 77174Sbill /* begin local */ 78208Sbill tlun.t_suspc = CTRL(z); 79208Sbill tlun.t_dsuspc = CTRL(y); 80174Sbill tlun.t_rprntc = CTRL(r); 81174Sbill tlun.t_flushc = CTRL(o); 82174Sbill tlun.t_werasc = CTRL(w); 83174Sbill tlun.t_lnextc = CTRL(v); 84174Sbill tlun.t_lintr = CTRL(c); 85174Sbill tlun.t_lerase = CTRL(h); 86174Sbill tlun.t_lkill = CTRL(u); 87174Sbill tp->t_local = 0; 88174Sbill tp->t_lstate = 0; 89174Sbill /* end local */ 9039Sbill } 9139Sbill 9239Sbill /* 93*903Sbill * Wait for output to drain, then flush input waiting. 9439Sbill */ 95*903Sbill wflushtty(tp) 9639Sbill register struct tty *tp; 9739Sbill { 9839Sbill 99*903Sbill (void) spl5(); 100*903Sbill while (tp->t_outq.c_cc && tp->t_state&CARR_ON) { 101*903Sbill (*tp->t_oproc)(tp); 102*903Sbill tp->t_state |= ASLEEP; 103*903Sbill sleep((caddr_t)&tp->t_outq, TTOPRI); 104*903Sbill } 105*903Sbill flushtty(tp, FREAD|FWRITE); 106*903Sbill (void) spl0(); 10739Sbill } 10839Sbill 10939Sbill /* 110*903Sbill * flush all TTY queues 11139Sbill */ 112*903Sbill flushtty(tp, rw) 113*903Sbill register struct tty *tp; 11439Sbill { 115*903Sbill register s; 116*903Sbill 117*903Sbill if (tp->t_line == NETLDISC) 118*903Sbill return; 119*903Sbill s = spl6(); 120*903Sbill if (rw & FREAD) { 121*903Sbill while (getc(&tp->t_canq) >= 0) 122*903Sbill ; 123*903Sbill wakeup((caddr_t)&tp->t_rawq); 124*903Sbill } 125*903Sbill if (rw & FWRITE) { 126*903Sbill wakeup((caddr_t)&tp->t_outq); 127*903Sbill tp->t_state &= ~TTSTOP; 128*903Sbill (*cdevsw[major(tp->t_dev)].d_stop)(tp); 129*903Sbill while (getc(&tp->t_outq) >= 0) 130*903Sbill ; 131*903Sbill } 132*903Sbill if (rw & FREAD) { 133*903Sbill while (getc(&tp->t_rawq) >= 0) 134*903Sbill ; 135*903Sbill tp->t_delct = 0; 136*903Sbill tp->t_rocount = 0; /* local */ 137*903Sbill tp->t_rocol = 0; 138*903Sbill tp->t_lstate = 0; 139*903Sbill } 140*903Sbill splx(s); 14139Sbill } 14239Sbill 143*903Sbill /* 144*903Sbill * Send stop character on input overflow. 145*903Sbill */ 146*903Sbill ttyblock(tp) 147*903Sbill register struct tty *tp; 14839Sbill { 149*903Sbill register x; 150*903Sbill x = tp->t_rawq.c_cc + tp->t_canq.c_cc; 151*903Sbill if (tp->t_rawq.c_cc > TTYHOG) { 152*903Sbill flushtty(tp, FREAD|FWRITE); 153*903Sbill tp->t_state &= ~TBLOCK; 154*903Sbill } 155*903Sbill if (x >= TTYHOG/2) { 156*903Sbill if (putc(tun.t_stopc, &tp->t_outq)==0) { 157*903Sbill tp->t_state |= TBLOCK; 158*903Sbill tp->t_char++; 159*903Sbill ttstart(tp); 160*903Sbill } 161*903Sbill } 16239Sbill } 16339Sbill 16439Sbill /* 165*903Sbill * Restart typewriter output following a delay 166*903Sbill * timeout. 167*903Sbill * The name of the routine is passed to the timeout 168*903Sbill * subroutine and it is called during a clock interrupt. 169121Sbill */ 170*903Sbill ttrstrt(tp) 171121Sbill register struct tty *tp; 172121Sbill { 173121Sbill 174*903Sbill tp->t_state &= ~TIMEOUT; 175*903Sbill ttstart(tp); 176121Sbill } 177121Sbill 178121Sbill /* 179*903Sbill * Start output on the typewriter. It is used from the top half 180*903Sbill * after some characters have been put on the output queue, 181*903Sbill * from the interrupt routine to transmit the next 182*903Sbill * character, and after a timeout has finished. 18339Sbill */ 184*903Sbill ttstart(tp) 185*903Sbill register struct tty *tp; 18639Sbill { 187*903Sbill register s; 18839Sbill 189*903Sbill s = spl5(); 190*903Sbill if((tp->t_state&(TIMEOUT|TTSTOP|BUSY)) == 0) 191*903Sbill (*tp->t_oproc)(tp); 192*903Sbill splx(s); 19339Sbill } 19439Sbill 19539Sbill /* 196*903Sbill * Common code for tty ioctls. 19739Sbill */ 198*903Sbill ttioctl(com, tp, addr, dev, flag) 19939Sbill register struct tty *tp; 20039Sbill caddr_t addr; 20139Sbill { 20239Sbill unsigned t; 203174Sbill struct sgttyb iocb; 204191Sbill struct clist tq; 20539Sbill extern int nldisp; 206887Sbill register c; 207728Sbill int temp; 20839Sbill 209*903Sbill /* 210*903Sbill * If the ioctl involves modification, 211*903Sbill * insist on being able to write the device, 212*903Sbill * and hang if in the background. 213*903Sbill */ 21439Sbill switch(com) { 21539Sbill 216*903Sbill case TIOCHPCL: 217*903Sbill case TIOCFLUSH: 218*903Sbill case TIOCSETC: 219*903Sbill case TIOCSLTC: 220*903Sbill case TIOCSPGRP: 221*903Sbill case TIOCLBIS: 222*903Sbill case TIOCLBIC: 223*903Sbill case TIOCLSET: 224*903Sbill case TIOCSTI: 225*903Sbill if ((flag & FWRITE) == 0) { 226*903Sbill u.u_error = EBADF; 227*903Sbill return (1); 228*903Sbill } 229*903Sbill while (tp->t_line == NTTYDISC && 230*903Sbill u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp && 231*903Sbill (u.u_procp->p_flag&SVFORK) == 0 && 232*903Sbill u.u_signal[SIGTTOU] != SIG_IGN && 233*903Sbill u.u_signal[SIGTTOU] != SIG_HOLD && 234*903Sbill (u.u_procp->p_flag&SDETACH)==0) { 235*903Sbill gsignal(u.u_procp->p_pgrp, SIGTTOU); 236*903Sbill sleep((caddr_t)&lbolt, TTOPRI); 237*903Sbill } 238*903Sbill break; 239*903Sbill } 240*903Sbill 24139Sbill /* 242*903Sbill * Process the ioctl. 24339Sbill */ 244*903Sbill switch(com) { 245*903Sbill 246*903Sbill /* 247*903Sbill * Get discipline number 248*903Sbill */ 24939Sbill case TIOCGETD: 25039Sbill t = tp->t_line; 25139Sbill if (copyout((caddr_t)&t, addr, sizeof(t))) 25239Sbill u.u_error = EFAULT; 25339Sbill break; 25439Sbill 25539Sbill /* 256*903Sbill * Set line discipline 25739Sbill */ 25839Sbill case TIOCSETD: 25939Sbill if (copyin(addr, (caddr_t)&t, sizeof(t))) { 26039Sbill u.u_error = EFAULT; 26139Sbill break; 26239Sbill } 26339Sbill if (t >= nldisp) { 26439Sbill u.u_error = ENXIO; 26539Sbill break; 26639Sbill } 267174Sbill (void) spl5(); 26839Sbill if (tp->t_line) 26939Sbill (*linesw[tp->t_line].l_close)(tp); 27039Sbill if (t) 27139Sbill (*linesw[t].l_open)(dev, tp, addr); 27239Sbill if (u.u_error==0) 27339Sbill tp->t_line = t; 274174Sbill (void) spl0(); 27539Sbill break; 27639Sbill 27739Sbill /* 278*903Sbill * Prevent more opens on channel 27939Sbill */ 28039Sbill case TIOCEXCL: 28139Sbill tp->t_state |= XCLUDE; 28239Sbill break; 28339Sbill 28439Sbill case TIOCNXCL: 28539Sbill tp->t_state &= ~XCLUDE; 28639Sbill break; 28739Sbill 28839Sbill /* 28939Sbill * Set new parameters 29039Sbill */ 29139Sbill case TIOCSETP: 292191Sbill case TIOCSETN: 29339Sbill if (copyin(addr, (caddr_t)&iocb, sizeof(iocb))) { 29439Sbill u.u_error = EFAULT; 29539Sbill return(1); 29639Sbill } 297121Sbill (void) spl5(); 298174Sbill if (tp->t_line == 0) { 299174Sbill if (com == TIOCSETP) 300174Sbill wflushtty(tp); 301174Sbill while (canon(tp)>=0) 302174Sbill ; 303174Sbill } else if (tp->t_line == NTTYDISC) { 304174Sbill if (tp->t_flags&RAW || iocb.sg_flags&RAW || 305174Sbill com == TIOCSETP) 306174Sbill wflushtty(tp); 307174Sbill else if ((tp->t_flags&CBREAK) != (iocb.sg_flags&CBREAK)) { 308174Sbill if (iocb.sg_flags & CBREAK) { 309174Sbill catq(&tp->t_rawq, &tp->t_canq); 310174Sbill tq = tp->t_rawq; 311174Sbill tp->t_rawq = tp->t_canq; 312174Sbill tp->t_canq = tq; 313174Sbill } else { 314174Sbill tp->t_local |= LPENDIN; 315174Sbill if (tp->t_canq.c_cc) 316174Sbill panic("ioccom canq"); 317174Sbill if (tp->t_chan) 318174Sbill (void) sdata(tp->t_chan); 319174Sbill else 320174Sbill wakeup((caddr_t)&tp->t_rawq); 321174Sbill } 322174Sbill } 323174Sbill } 32439Sbill if ((tp->t_state&SPEEDS)==0) { 325174Sbill tp->t_ispeed = iocb.sg_ispeed; 326174Sbill tp->t_ospeed = iocb.sg_ospeed; 32739Sbill } 328174Sbill tp->t_erase = iocb.sg_erase; 329174Sbill tp->t_kill = iocb.sg_kill; 330174Sbill tp->t_flags = iocb.sg_flags; 331121Sbill (void) spl0(); 33239Sbill break; 33339Sbill 33439Sbill /* 335*903Sbill * Send current parameters to user 33639Sbill */ 33739Sbill case TIOCGETP: 338174Sbill iocb.sg_ispeed = tp->t_ispeed; 339174Sbill iocb.sg_ospeed = tp->t_ospeed; 340174Sbill iocb.sg_erase = tp->t_erase; 341174Sbill iocb.sg_kill = tp->t_kill; 342174Sbill iocb.sg_flags = tp->t_flags; 34339Sbill if (copyout((caddr_t)&iocb, addr, sizeof(iocb))) 34439Sbill u.u_error = EFAULT; 34539Sbill break; 34639Sbill 34739Sbill /* 34839Sbill * Hang up line on last close 34939Sbill */ 35039Sbill case TIOCHPCL: 35139Sbill tp->t_state |= HUPCLS; 35239Sbill break; 35339Sbill 35439Sbill case TIOCFLUSH: 355872Sbill flushtty(tp, FREAD|FWRITE); 35639Sbill break; 35739Sbill 35839Sbill /* 359*903Sbill * Ioctl entries to line discipline 36039Sbill */ 36139Sbill case DIOCSETP: 36239Sbill case DIOCGETP: 363121Sbill if ((*linesw[tp->t_line].l_ioctl)(com, tp, addr)) 364121Sbill u.u_error = ENOTTY; 36539Sbill break; 36639Sbill 36739Sbill /* 368*903Sbill * Set and fetch special characters 36939Sbill */ 37039Sbill case TIOCSETC: 371174Sbill if (copyin(addr, (caddr_t)&tun, sizeof(struct tchars))) 37239Sbill u.u_error = EFAULT; 37339Sbill break; 37439Sbill 37539Sbill case TIOCGETC: 376174Sbill if (copyout((caddr_t)&tun, addr, sizeof(struct tchars))) 37739Sbill u.u_error = EFAULT; 37839Sbill break; 37939Sbill 380174Sbill /* local ioctls */ 381*903Sbill /* 382*903Sbill * Set/get local special characters. 383*903Sbill */ 384174Sbill case TIOCSLTC: 385174Sbill if (copyin(addr, (caddr_t)&tlun, sizeof (struct ltchars))) 386174Sbill u.u_error = EFAULT; 387174Sbill break; 388174Sbill 389174Sbill case TIOCGLTC: 390174Sbill if (copyout((caddr_t)&tlun, addr, sizeof (struct ltchars))) 391174Sbill u.u_error = EFAULT; 392174Sbill break; 393174Sbill 394*903Sbill /* 395*903Sbill * Return number of characters immediately available. 396*903Sbill */ 397174Sbill case FIONREAD: { 398340Sbill off_t nread; 399174Sbill 400340Sbill switch (tp->t_line) { 401340Sbill 402340Sbill case NETLDISC: 403340Sbill nread = tp->t_rec ? tp->t_inbuf : 0; 404340Sbill break; 405340Sbill 406894Sbill case 0: 407894Sbill (void) spl5(); 408894Sbill while (canon(tp)>=0) 409894Sbill ; 410894Sbill (void) spl0(); 411894Sbill /* fall into ... */ 412894Sbill 413340Sbill case NTTYDISC: 414340Sbill nread = tp->t_canq.c_cc; 415340Sbill if (tp->t_flags & (RAW|CBREAK)) 416340Sbill nread += tp->t_rawq.c_cc; 417340Sbill break; 418340Sbill 419340Sbill } 420174Sbill if (copyout((caddr_t)&nread, addr, sizeof (off_t))) 421174Sbill u.u_error = EFAULT; 422174Sbill break; 423174Sbill } 424174Sbill 425174Sbill /* 426174Sbill * Should allow SPGRP and GPGRP only if tty open for reading. 427174Sbill */ 428174Sbill case TIOCSPGRP: 429728Sbill if (copyin(addr, (caddr_t)&tp->t_pgrp, sizeof (tp->t_pgrp))) 430728Sbill u.u_error = EFAULT; 431174Sbill break; 432174Sbill 433174Sbill case TIOCGPGRP: 434174Sbill if (copyout((caddr_t)&tp->t_pgrp, addr, sizeof(tp->t_pgrp))) 435174Sbill u.u_error = EFAULT; 436174Sbill break; 437174Sbill 438174Sbill /* 439174Sbill * Modify local mode word. 440174Sbill */ 441174Sbill case TIOCLBIS: 442728Sbill if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local))) 443728Sbill u.u_error = EFAULT; 444728Sbill else 445728Sbill tp->t_local |= temp; 446174Sbill break; 447174Sbill 448174Sbill case TIOCLBIC: 449728Sbill if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local))) 450728Sbill u.u_error = EFAULT; 451728Sbill else 452728Sbill tp->t_local &= ~temp; 453174Sbill break; 454174Sbill 455174Sbill case TIOCLSET: 456728Sbill if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local))) 457728Sbill u.u_error = EFAULT; 458728Sbill else 459728Sbill tp->t_local = temp; 460174Sbill break; 461174Sbill 462174Sbill case TIOCLGET: 463174Sbill if (copyout((caddr_t)&tp->t_local, addr, sizeof(tp->t_local))) 464174Sbill u.u_error = EFAULT; 465174Sbill break; 466174Sbill 467*903Sbill /* 468*903Sbill * Return number of characters in 469*903Sbill * the output. 470*903Sbill */ 471213Sbill case TIOCOUTQ: 472213Sbill if (copyout((caddr_t)&tp->t_outq.c_cc, addr, sizeof(tp->t_outq.c_cc))) 473213Sbill u.u_error = EFAULT; 474213Sbill break; 475213Sbill 476*903Sbill /* 477*903Sbill * Simulate typing of a character at the terminal. 478*903Sbill */ 479887Sbill case TIOCSTI: 480887Sbill c = fubyte(addr); 481887Sbill if (u.u_uid && u.u_ttyp != tp || c < 0) 482887Sbill u.u_error = EFAULT; 483887Sbill else 484887Sbill (*linesw[tp->t_line].l_rint)(c, tp); 485887Sbill break; 486174Sbill /* end of locals */ 487887Sbill 48839Sbill default: 48939Sbill return(0); 49039Sbill } 49139Sbill return(1); 49239Sbill } 493