1 /* tty_pty.c 4.9 81/10/11 */ 2 3 /* 4 * Pseudo-teletype Driver 5 * (Actually two drivers, requiring two entries in 'cdevsw') 6 */ 7 #include "pty.h" 8 9 #if NPTY > 0 10 11 #include "../h/param.h" 12 #include "../h/systm.h" 13 #include "../h/tty.h" 14 #include "../h/dir.h" 15 #include "../h/user.h" 16 #include "../h/conf.h" 17 #include "../h/buf.h" 18 #include "../h/file.h" 19 #include "../h/proc.h" 20 21 #undef NPTY 22 #define NPTY 16 23 24 #define BUFSIZ 100 /* Chunk size iomoved from user */ 25 26 /* 27 * pts == /dev/tty[pP]? 28 * ptc == /dev/ptp[pP]? 29 */ 30 struct tty pt_tty[NPTY]; 31 struct pt_ioctl { 32 int pti_flags; 33 struct clist pti_ioctl, pti_ioans; 34 int pti_gensym; 35 struct proc *pti_selr; 36 } pt_ioctl[NPTY]; 37 38 #define PTCRCOLL 0x01 39 40 /*ARGSUSED*/ 41 ptsopen(dev, flag) 42 dev_t dev; 43 { 44 register struct tty *tp; 45 46 if (minor(dev) >= NPTY) { 47 u.u_error = ENXIO; 48 return; 49 } 50 tp = &pt_tty[minor(dev)]; 51 if ((tp->t_state & ISOPEN) == 0) { 52 ttychars(tp); /* Set up default chars */ 53 tp->t_flags = 0; /* No features (nor raw mode) */ 54 } else if (tp->t_state&XCLUDE && u.u_uid != 0) { 55 u.u_error = EBUSY; 56 return; 57 } 58 if (tp->t_oproc) /* Ctrlr still around. */ 59 tp->t_state |= CARR_ON; 60 while ((tp->t_state & CARR_ON) == 0) { 61 tp->t_state |= WOPEN; 62 sleep((caddr_t)&tp->t_rawq, TTIPRI); 63 } 64 (*linesw[tp->t_line].l_open)(dev, tp); 65 } 66 67 ptsclose(dev) 68 dev_t dev; 69 { /* Close slave part of PTY */ 70 register struct tty *tp; 71 72 tp = &pt_tty[minor(dev)]; 73 (*linesw[tp->t_line].l_close)(tp); 74 } 75 76 ptsread(dev) 77 dev_t dev; 78 { 79 register struct tty *tp; 80 81 tp = &pt_tty[minor(dev)]; 82 if (tp->t_oproc) { 83 (*linesw[tp->t_line].l_read)(tp); 84 wakeup((caddr_t)&tp->t_rawq.c_cf); 85 } 86 } 87 88 ptswrite(dev) 89 dev_t dev; 90 { 91 register struct tty *tp; 92 93 tp = &pt_tty[minor(dev)]; 94 if (tp->t_oproc) 95 (*linesw[tp->t_line].l_write)(tp); 96 } 97 98 ptsstart(tp) 99 struct tty *tp; 100 { 101 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 102 103 if (tp->t_state & TTSTOP) 104 return; 105 if (pti->pti_selr) { 106 selwakeup(pti->pti_selr, pti->pti_flags & PTCRCOLL); 107 pti->pti_selr = 0; 108 pti->pti_flags &= ~PTCRCOLL; 109 } 110 wakeup((caddr_t)&tp->t_outq.c_cf); 111 } 112 113 /*ARGSUSED*/ 114 ptcopen(dev, flag) 115 dev_t dev; 116 int flag; 117 { 118 register struct tty *tp; 119 120 if (minor(dev) >= NPTY) { 121 u.u_error = ENXIO; 122 return; 123 } 124 tp = &pt_tty[minor(dev)]; 125 if (tp->t_oproc) { 126 u.u_error = EIO; 127 return; 128 } 129 tp->t_oproc = ptsstart; 130 if (tp->t_state & WOPEN) 131 wakeup((caddr_t)&tp->t_rawq); 132 tp->t_state |= CARR_ON; 133 } 134 135 ptcclose(dev) 136 dev_t dev; 137 { 138 register struct tty *tp; 139 140 tp = &pt_tty[minor(dev)]; 141 if (tp->t_state & ISOPEN) 142 gsignal(tp->t_pgrp, SIGHUP); 143 tp->t_state &= ~CARR_ON; /* virtual carrier gone */ 144 flushtty(tp, FREAD|FWRITE); 145 tp->t_oproc = 0; /* mark closed */ 146 } 147 148 ptcread(dev) 149 dev_t dev; 150 { 151 register struct tty *tp; 152 153 tp = &pt_tty[minor(dev)]; 154 if ((tp->t_state&(CARR_ON|ISOPEN)) == 0) 155 return; 156 while (tp->t_outq.c_cc == 0 || (tp->t_state&TTSTOP)) 157 sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI); 158 while (tp->t_outq.c_cc && passc(getc(&tp->t_outq)) >= 0); 159 if (tp->t_outq.c_cc <= TTLOWAT(tp) && (tp->t_state&ASLEEP)) { 160 tp->t_state &= ~ASLEEP; 161 wakeup((caddr_t)&tp->t_outq); 162 } 163 } 164 165 ptcselect(dev) 166 dev_t dev; 167 { 168 register struct tty *tp = &pt_tty[minor(dev)]; 169 struct pt_ioctl *pti; 170 struct proc *p; 171 172 if ((tp->t_state&(CARR_ON|ISOPEN)) == 0) 173 return (1); 174 if (tp->t_outq.c_cc) 175 return (1); 176 pti = &pt_ioctl[minor(dev)]; 177 if ((p = pti->pti_selr) && p->p_wchan == (caddr_t)select) 178 pti->pti_flags |= PTCRCOLL; 179 else 180 pti->pti_selr = u.u_procp; 181 return (0); 182 } 183 184 ptcwrite(dev) 185 dev_t dev; 186 { 187 register struct tty *tp; 188 register char *cp, *ce; 189 register int cc; 190 char locbuf[BUFSIZ]; 191 192 tp = &pt_tty[minor(dev)]; 193 if ((tp->t_state&(CARR_ON|ISOPEN)) == 0) 194 return; 195 while (u.u_count) { 196 cc = MIN(u.u_count, BUFSIZ); 197 cp = locbuf; 198 iomove(cp, (unsigned)cc, B_WRITE); 199 if (u.u_error) 200 break; 201 ce = cp + cc; 202 while (cp < ce) { 203 while (tp->t_delct && tp->t_rawq.c_cc >= TTYHOG - 2) { 204 wakeup((caddr_t)&tp->t_rawq); 205 /* Better than just flushing it! */ 206 /* Wait for something to be read */ 207 sleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI); 208 } 209 (*linesw[tp->t_line].l_rint)(*cp++, tp); 210 } 211 } 212 } 213 214 /*ARGSUSED*/ 215 ptyioctl(dev, cmd, addr, flag) 216 caddr_t addr; 217 dev_t dev; 218 { 219 register struct tty *tp; 220 register int tbd; 221 222 tp = &pt_tty[minor(dev)]; 223 /* IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG ??? */ 224 if (cdevsw[major(dev)].d_open == ptcopen && cmd == TIOCSETP) 225 while (getc(&tp->t_outq) >= 0); 226 if (ttioctl(tp, cmd, addr, dev) == 0) 227 u.u_error = ENOTTY; 228 } 229 #endif 230