09750 # 09751 /* 09752 * general TTY subroutines 09753 */ 09754 #include "../h/param.h" 09755 #include "../h/systm.h" 09756 #include "../h/dir.h" 09757 #include "../h/user.h" 09758 #include "../h/tty.h" 09759 #include "../h/proc.h" 09760 #include "../h/mx.h" 09761 #include "../h/inode.h" 09762 #include "../h/file.h" 09763 #include "../h/reg.h" 09764 #include "../h/conf.h" 09765 09766 char partab[]; 09767 09768 09769 /* 09770 * Input mapping table-- if an entry is non-zero, when the 09771 * corresponding character is typed preceded by "\" the escape 09772 * sequence is replaced by the table value. Mostly used for 09773 * upper-case only terminals. 09774 */ 09775 09776 char maptab[] ={ 09777 000,000,000,000,000,000,000,000, 09778 000,000,000,000,000,000,000,000, 09779 000,000,000,000,000,000,000,000, 09780 000,000,000,000,000,000,000,000, 09781 000,'|',000,000,000,000,000,'`', 09782 '{','}',000,000,000,000,000,000, 09783 000,000,000,000,000,000,000,000, 09784 000,000,000,000,000,000,000,000, 09785 000,000,000,000,000,000,000,000, 09786 000,000,000,000,000,000,000,000, 09787 000,000,000,000,000,000,000,000, 09788 000,000,000,000,000,000,'~',000, 09789 000,'A','B','C','D','E','F','G', 09790 'H','I','J','K','L','M','N','O', 09791 'P','Q','R','S','T','U','V','W', 09792 'X','Y','Z',000,000,000,000,000, 09793 }; 09794 09795 09796 /* 09797 * shorthand 09798 */ 09799 #define q1 tp->t_rawq 09800 #define q2 tp->t_canq 09801 #define q3 tp->t_outq 09802 #define q4 tp->t_un.t_ctlq 09803 09804 09805 /* 09806 * routine called on first teletype open. 09807 * establishes a process group for distribution 09808 * of quits and interrupts from the tty. 09809 */ 09810 ttyopen(dev, tp) 09811 dev_t dev; 09812 register struct tty *tp; 09813 { 09814 register struct proc *pp; 09815 09816 pp = u.u_procp; 09817 tp->t_dev = dev; 09818 if(pp->p_pgrp == 0) { 09819 u.u_ttyp = tp; 09820 u.u_ttyd = dev; 09821 if (tp->t_pgrp==0) 09822 tp->t_pgrp = pp->p_pid; 09823 pp->p_pgrp = tp->t_pgrp; 09824 } 09825 tp->t_state &= ~WOPEN; 09826 tp->t_state |= ISOPEN; 09827 } 09828 09829 09830 /* 09831 * set default control characters. 09832 */ 09833 ttychars(tp) 09834 register struct tty *tp; 09835 { 09836 tun.t_intrc = CINTR; 09837 tun.t_quitc = CQUIT; 09838 tun.t_startc = CSTART; 09839 tun.t_stopc = CSTOP; 09840 tun.t_eofc = CEOT; 09841 tun.t_brkc = CBRK; 09842 tp->t_erase = CERASE; 09843 tp->t_kill = CKILL; 09844 } 09845 09846 /* 09847 * clean tp on last close 09848 */ 09849 ttyclose(tp) 09850 register struct tty *tp; 09851 { 09852 09853 tp->t_pgrp = 0; 09854 wflushtty(tp); 09855 tp->t_state = 0; 09856 } 09857 09858 /* 09859 * stty/gtty writearound 09860 */ 09861 stty() 09862 { 09863 u.u_arg[2] = u.u_arg[1]; 09864 u.u_arg[1] = TIOCSETP; 09865 ioctl(); 09866 } 09867 09868 gtty() 09869 { 09870 u.u_arg[2] = u.u_arg[1]; 09871 u.u_arg[1] = TIOCGETP; 09872 ioctl(); 09873 } 09874 09875 /* 09876 * ioctl system call 09877 * Check legality, execute common code, and switch out to individual 09878 * device routine. 09879 */ 09880 ioctl() 09881 { 09882 register struct file *fp; 09883 register struct inode *ip; 09884 register struct a { 09885 int fdes; 09886 int cmd; 09887 caddr_t cmarg; 09888 } *uap; 09889 register dev_t dev; 09890 register fmt; 09891 09892 uap = (struct a *)u.u_ap; 09893 if ((fp = getf(uap->fdes)) == NULL) 09894 return; 09895 if (uap->cmd==FIOCLEX) { 09896 u.u_pofile[uap->fdes] |= EXCLOSE; 09897 return; 09898 } 09899 if (uap->cmd==FIONCLEX) { 09900 u.u_pofile[uap->fdes] &= ~EXCLOSE; 09901 return; 09902 } 09903 ip = fp->f_inode; 09904 fmt = ip->i_mode & IFMT; 09905 if (fmt != IFCHR && fmt != IFMPC) { 09906 u.u_error = ENOTTY; 09907 return; 09908 } 09909 dev = (dev_t)ip->i_un.i_rdev; 09910 (*cdevsw[major(dev)].d_ioctl)(dev, uap->cmd, uap->cmarg, fp->f_flag); 09911 } 09912 09913 /* 09914 * Common code for several tty ioctl commands 09915 */ 09916 ttioccomm(com, tp, addr, dev) 09917 register struct tty *tp; 09918 caddr_t addr; 09919 { 09920 unsigned t; 09921 struct ttiocb iocb; 09922 extern int nldisp; 09923 09924 switch(com) { 09925 09926 /* 09927 * get discipline number 09928 */ 09929 case TIOCGETD: 09930 t = tp->t_line; 09931 if (copyout((caddr_t)&t, addr, sizeof(t))) 09932 u.u_error = EFAULT; 09933 break; 09934 09935 /* 09936 * set line discipline 09937 */ 09938 case TIOCSETD: 09939 if (copyin(addr, (caddr_t)&t, sizeof(t))) { 09940 u.u_error = EFAULT; 09941 break; 09942 } 09943 if (t >= nldisp) { 09944 u.u_error = ENXIO; 09945 break; 09946 } 09947 if (tp->t_line) 09948 (*linesw[tp->t_line].l_close)(tp); 09949 if (t) 09950 (*linesw[t].l_open)(dev, tp, addr); 09951 if (u.u_error==0) 09952 tp->t_line = t; 09953 break; 09954 09955 /* 09956 * prevent more opens on channel 09957 */ 09958 case TIOCEXCL: 09959 tp->t_state |= XCLUDE; 09960 break; 09961 case TIOCNXCL: 09962 tp->t_state &= ~XCLUDE; 09963 break; 09964 09965 /* 09966 * Set new parameters 09967 */ 09968 case TIOCSETP: 09969 wflushtty(tp); 09970 case TIOCSETN: 09971 if (copyin(addr, (caddr_t)&iocb, sizeof(iocb))) { 09972 u.u_error = EFAULT; 09973 return(1); 09974 } 09975 tp->t_ispeed = iocb.ioc_ispeed; 09976 tp->t_ospeed = iocb.ioc_ospeed; 09977 tp->t_erase = iocb.ioc_erase; 09978 tp->t_kill = iocb.ioc_kill; 09979 tp->t_flags = iocb.ioc_flags; 09980 break; 09981 09982 /* 09983 * send current parameters to user 09984 */ 09985 case TIOCGETP: 09986 iocb.ioc_ispeed = tp->t_ispeed; 09987 iocb.ioc_ospeed = tp->t_ospeed; 09988 iocb.ioc_erase = tp->t_erase; 09989 iocb.ioc_kill = tp->t_kill; 09990 iocb.ioc_flags = tp->t_flags; 09991 if (copyout((caddr_t)&iocb, addr, sizeof(iocb))) 09992 u.u_error = EFAULT; 09993 break; 09994 09995 /* 09996 * Hang up line on last close 09997 */ 09998 09999 case TIOCHPCL: 10000 tp->t_state |= HUPCLS; 10001 break; 10002 10003 case TIOCFLUSH: 10004 flushtty(tp); 10005 break; 10006 10007 /* 10008 * ioctl entries to line discipline 10009 */ 10010 case DIOCSETP: 10011 case DIOCGETP: 10012 (*linesw[tp->t_line].l_ioctl)(com, tp, addr); 10013 break; 10014 10015 /* 10016 * set and fetch special characters 10017 */ 10018 case TIOCSETC: 10019 if (copyin(addr, (caddr_t)&tun, sizeof(struct tc))) 10020 u.u_error = EFAULT; 10021 break; 10022 10023 case TIOCGETC: 10024 if (copyout((caddr_t)&tun, addr, sizeof(struct tc))) 10025 u.u_error = EFAULT; 10026 break; 10027 10028 default: 10029 return(0); 10030 } 10031 return(1); 10032 } 10033 10034 /* 10035 * Wait for output to drain, then flush input waiting. 10036 */ 10037 wflushtty(tp) 10038 register struct tty *tp; 10039 { 10040 10041 spl5(); 10042 while (tp->t_outq.c_cc && tp->t_state&CARR_ON) { 10043 (*tp->t_oproc)(tp); 10044 tp->t_state |= ASLEEP; 10045 sleep((caddr_t)&tp->t_outq, TTOPRI); 10046 } 10047 flushtty(tp); 10048 spl0(); 10049 } 10050 10051 /* 10052 * flush all TTY queues 10053 */ 10054 flushtty(tp) 10055 register struct tty *tp; 10056 { 10057 register s; 10058 10059 while (getc(&tp->t_canq) >= 0) 10060 ; 10061 wakeup((caddr_t)&tp->t_rawq); 10062 wakeup((caddr_t)&tp->t_outq); 10063 s = spl6(); 10064 tp->t_state &= ~TTSTOP; 10065 (*cdevsw[major(tp->t_dev)].d_stop)(tp); 10066 while (getc(&tp->t_outq) >= 0) 10067 ; 10068 while (getc(&tp->t_rawq) >= 0) 10069 ; 10070 tp->t_delct = 0; 10071 splx(s); 10072 } 10073 10074 10075 10076 /* 10077 * transfer raw input list to canonical list, 10078 * doing erase-kill processing and handling escapes. 10079 * It waits until a full line has been typed in cooked mode, 10080 * or until any character has been typed in raw mode. 10081 */ 10082 canon(tp) 10083 register struct tty *tp; 10084 { 10085 register char *bp; 10086 char *bp1; 10087 register int c; 10088 int mc; 10089 10090 spl5(); 10091 while ((tp->t_flags&(RAW|CBREAK))==0 && tp->t_delct==0) 10092 || (tp->t_flags&(RAW|CBREAK))!=0 && tp->t_rawq.c_cc==0) { 10093 if ((tp->t_state&CARR_ON)==0 || tp->t_chan!=NULL) { 10094 return(0); 10095 } 10096 sleep((caddr_t)&tp->t_rawq, TTIPRI); 10097 } 10098 spl0(); 10099 loop: 10100 bp = &canonb[2]; 10101 while ((c=getc(&tp->t_rawq)) >= 0) { 10102 if ((tp->t_flags&(RAW|CBREAK))==0) { 10103 if (c==0377) { 10104 tp->t_delct--; 10105 break; 10106 } 10107 if (bp[-1]!='\\') { 10108 if (c==tp->t_erase) { 10109 if (bp > &canonb[2]) 10110 bp--; 10111 continue; 10112 } 10113 if (c==tp->t_kill) 10114 goto loop; 10115 if (c==tun.t_eofc) 10116 continue; 10117 } else { 10118 mc = maptab[c]; 10119 if (c==tp->t_erase || c==tp->t_kill) 10120 mc = c; 10121 if (mc && (mc==c || (tp->t_flags&LCASE))) { 10122 if (bp[-2] != '\\') 10123 c = mc; 10124 bp--; 10125 } 10126 } 10127 } 10128 *bp++ = c; 10129 if (bp>=canonb+CANBSIZ) 10130 break; 10131 } 10132 bp1 = &canonb[2]; 10133 b_to_q(bp1, bp-bp1, &tp->t_canq); 10134 10135 if (tp->t_state&TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) { 10136 if (putc(tun.t_startc, &tp->t_outq)==0) { 10137 tp->t_state &= ~TBLOCK; 10138 ttstart(tp); 10139 } 10140 tp->t_char = 0; 10141 } 10142 10143 return(bp-bp1); 10144 } 10145 10146 10147 /* 10148 * block transfer input handler. 10149 */ 10150 ttyrend(tp, pb, pe) 10151 register struct tty *tp; 10152 register char *pb, *pe; 10153 { 10154 int tandem; 10155 10156 tandem = tp->t_flags&TANDEM; 10157 if (tp->t_flags&RAW) { 10158 b_to_q(pb, pe-pb, &tp->t_rawq); 10159 if (tp->t_chan) 10160 sdata(tp->t_chan); else 10161 wakeup((caddr_t)&tp->t_rawq); 10162 } else { 10163 tp->t_flags &= ~TANDEM; 10164 while (pb < pe) 10165 ttyinput(*pb++, tp); 10166 tp->t_flags |= tandem; 10167 } 10168 if (tandem) 10169 ttyblock(tp); 10170 } 10171 10172 /* 10173 * Place a character on raw TTY input queue, putting in delimiters 10174 * and waking up top half as needed. 10175 * Also echo if required. 10176 * The arguments are the character and the appropriate 10177 * tty structure. 10178 */ 10179 ttyinput(c, tp) 10180 register c; 10181 register struct tty *tp; 10182 { 10183 register int t_flags; 10184 register struct chan *cp; 10185 10186 tk_nin += 1; 10187 c &= 0377; 10188 t_flags = tp->t_flags; 10189 if (t_flags&TANDEM) 10190 ttyblock(tp); 10191 if ((t_flags&RAW)==0) { 10192 c &= 0177; 10193 if (tp->t_state&TTSTOP) { 10194 if (c==tun.t_startc) { 10195 tp->t_state &= ~TTSTOP; 10196 ttstart(tp); 10197 return; 10198 } 10199 if (c==tun.t_stopc) 10200 return; 10201 tp->t_state &= ~TTSTOP; 10202 ttstart(tp); 10203 } else { 10204 if (c==tun.t_stopc) { 10205 tp->t_state |= TTSTOP; 10206 (*cdevsw[major(tp->t_dev)].d_stop)(tp); 10207 return; 10208 } 10209 if (c==tun.t_startc) 10210 return; 10211 } 10212 if (c==tun.t_quitc || c==tun.t_intrc) { 10213 flushtty(tp); 10214 c = (c==tun.t_intrc) ? SIGINT:SIGQUIT; 10215 if (tp->t_chan) 10216 scontrol(tp->t_chan, M_SIG, c); 10217 else 10218 signal(tp->t_pgrp, c); 10219 return; 10220 } 10221 if (c=='\r' && t_flags&CRMOD) 10222 c = '\n'; 10223 } 10224 if (tp->t_rawq.c_cc>TTYHOG) { 10225 flushtty(tp); 10226 return; 10227 } 10228 if (t_flags&LCASE && c>='A' && c<='Z') 10229 c += 'a'-'A'; 10230 putc(c, &tp->t_rawq); 10231 if (t_flags&(RAW|CBREAK)||(c=='\n'||c==tun.t_eofc||c==tun.t_brkc)) { 10232 if ((t_flags&(RAW|CBREAK))==0 && putc(0377, &tp->t_rawq)==0) 10233 tp->t_delct++; 10234 if ((cp=tp->t_chan)!=NULL) 10235 sdata(cp); else 10236 wakeup((caddr_t)&tp->t_rawq); 10237 } 10238 if (t_flags&ECHO) { 10239 ttyoutput(c, tp); 10240 if (c==tp->t_kill && (t_flags&(RAW|CBREAK))==0) 10241 ttyoutput('\n', tp); 10242 ttstart(tp); 10243 } 10244 } 10245 10246 10247 /* 10248 * Send stop character on input overflow. 10249 */ 10250 ttyblock(tp) 10251 register struct tty *tp; 10252 { 10253 register x; 10254 x = q1.c_cc + q2.c_cc; 10255 if (q1.c_cc > TTYHOG) { 10256 flushtty(tp); 10257 tp->t_state &= ~TBLOCK; 10258 } 10259 if (x >= TTYHOG/2) { 10260 if (putc(tun.t_stopc, &tp->t_outq)==0) { 10261 tp->t_state |= TBLOCK; 10262 tp->t_char++; 10263 ttstart(tp); 10264 } 10265 } 10266 } 10267 10268 /* 10269 * put character on TTY output queue, adding delays, 10270 * expanding tabs, and handling the CR/NL bit. 10271 * It is called both from the top half for output, and from 10272 * interrupt level for echoing. 10273 * The arguments are the character and the tty structure. 10274 */ 10275 ttyoutput(c, tp) 10276 register c; 10277 register struct tty *tp; 10278 { 10279 register char *colp; 10280 register ctype; 10281 10282 tk_nout += 1; 10283 /* 10284 * Ignore EOT in normal mode to avoid hanging up 10285 * certain terminals. 10286 * In raw mode dump the char unchanged. 10287 */ 10288 10289 if ((tp->t_flags&RAW)==0) { 10290 c &= 0177; 10291 if (c==CEOT) 10292 return; 10293 } else { 10294 putc(c, &tp->t_outq); 10295 return; 10296 } 10297 10298 /* 10299 * Turn tabs to spaces as required 10300 */ 10301 if (c=='\t' && (tp->t_flags&TBDELAY)==XTABS) { 10302 c = 8; 10303 do 10304 ttyoutput(' ', tp); 10305 while (--c >= 0 && tp->t_col&07); 10306 return; 10307 } 10308 /* 10309 * for upper-case-only terminals, 10310 * generate escapes. 10311 */ 10312 if (tp->t_flags&LCASE) { 10313 colp = "({)}!|^~'`"; 10314 while(*colp++) 10315 if(c == *colp++) { 10316 ttyoutput('\\', tp); 10317 c = colp[-2]; 10318 break; 10319 } 10320 if ('a'<=c && c<='z') 10321 c += 'A' - 'a'; 10322 } 10323 /* 10324 * turn to if desired. 10325 */ 10326 if (c=='\n' && tp->t_flags&CRMOD) 10327 ttyoutput('\r', tp); 10328 putc(c, &tp->t_outq); 10329 /* 10330 * Calculate delays. 10331 * The numbers here represent clock ticks 10332 * and are not necessarily optimal for all terminals. 10333 * The delays are indicated by characters above 0200. 10334 * In raw mode there are no delays and the 10335 * transmission path is 8 bits wide. 10336 */ 10337 colp = &tp->t_col; 10338 ctype = partab[c]; 10339 c = 0; 10340 switch (ctype&077) { 10341 10342 /* ordinary */ 10343 case 0: 10344 (*colp)++; 10345 10346 /* non-printing */ 10347 case 1: 10348 break; 10349 10350 /* backspace */ 10351 case 2: 10352 if (*colp) 10353 (*colp)--; 10354 break; 10355 10356 /* newline */ 10357 case 3: 10358 ctype = (tp->t_flags >> 8) & 03; 10359 if(ctype == 1) { /* tty 37 */ 10360 if (*colp) 10361 c = max(((unsigned)*colp>>4) + 3, (unsigned)6); 10362 } else 10363 if(ctype == 2) { /* vt05 */ 10364 c = 6; 10365 } 10366 *colp = 0; 10367 break; 10368 10369 /* tab */ 10370 case 4: 10371 ctype = (tp->t_flags >> 10) & 03; 10372 if(ctype == 1) { /* tty 37 */ 10373 c = 1 - (*colp | ~07); 10374 if(c < 5) 10375 c = 0; 10376 } 10377 *colp |= 07; 10378 (*colp)++; 10379 break; 10380 10381 /* vertical motion */ 10382 case 5: 10383 if(tp->t_flags & VTDELAY) /* tty 37 */ 10384 c = 0177; 10385 break; 10386 10387 /* carriage return */ 10388 case 6: 10389 ctype = (tp->t_flags >> 12) & 03; 10390 if(ctype == 1) { /* tn 300 */ 10391 c = 5; 10392 } else if(ctype == 2) { /* ti 700 */ 10393 c = 10; 10394 } 10395 *colp = 0; 10396 } 10397 if(c) 10398 putc(c|0200, &tp->t_outq); 10399 } 10400 10401 /* 10402 * Restart typewriter output following a delay 10403 * timeout. 10404 * The name of the routine is passed to the timeout 10405 * subroutine and it is called during a clock interrupt. 10406 */ 10407 ttrstrt(tp) 10408 register struct tty *tp; 10409 { 10410 10411 tp->t_state &= ~TIMEOUT; 10412 ttstart(tp); 10413 } 10414 10415 /* 10416 * Start output on the typewriter. It is used from the top half 10417 * after some characters have been put on the output queue, 10418 * from the interrupt routine to transmit the next 10419 * character, and after a timeout has finished. 10420 */ 10421 ttstart(tp) 10422 register struct tty *tp; 10423 { 10424 register s; 10425 10426 s = spl5(); 10427 if((tp->t_state&(TIMEOUT|TTSTOP|BUSY)) == 0) 10428 (*tp->t_oproc)(tp); 10429 splx(s); 10430 } 10431 10432 /* 10433 * Called from device's read routine after it has 10434 * calculated the tty-structure given as argument. 10435 */ 10436 ttread(tp) 10437 register struct tty *tp; 10438 { 10439 10440 if ((tp->t_state&CARR_ON)==0) 10441 return(0); 10442 if (tp->t_canq.c_cc || canon(tp)) 10443 while (tp->t_canq.c_cc && passc(getc(&tp->t_canq))>=0) 10444 ; 10445 return(tp->t_rawq.c_cc + tp->t_canq.c_cc); 10446 } 10447 10448 /* 10449 * Called from the device's write routine after it has 10450 * calculated the tty-structure given as argument. 10451 */ 10452 caddr_t 10453 ttwrite(tp) 10454 register struct tty *tp; 10455 { 10456 register c; 10457 10458 if ((tp->t_state&CARR_ON)==0) 10459 return(NULL); 10460 while (u.u_count) { 10461 spl5(); 10462 while (tp->t_outq.c_cc > TTHIWAT) { 10463 ttstart(tp); 10464 tp->t_state |= ASLEEP; 10465 if (tp->t_chan) 10466 return((caddr_t)&tp->t_outq); 10467 sleep((caddr_t)&tp->t_outq, TTOPRI); 10468 } 10469 spl0(); 10470 if ((c = cpass()) < 0) 10471 break; 10472 ttyoutput(c, tp); 10473 } 10474 ttstart(tp); 10475 return(NULL); 10476 } 10477 10478 10479 10480 10481 10482 10483 10484 10485 10486 10487 10488 10489 10490 10491 10492 10493 10494 10495 10496 10497 10498 10499