Commit | Line | Data |
---|---|---|
89b8a44c | 1 | /* tty_pty.c 4.10 81/11/18 */ |
be4367b3 | 2 | |
45372428 MT |
3 | /* |
4 | * Pseudo-teletype Driver | |
5 | * (Actually two drivers, requiring two entries in 'cdevsw') | |
45372428 | 6 | */ |
647d645f MT |
7 | #include "pty.h" |
8 | ||
f12183e4 | 9 | #if NPTY > 0 |
647d645f | 10 | |
45372428 MT |
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" | |
bdda6b91 | 18 | #include "../h/file.h" |
e1d74936 BJ |
19 | #include "../h/proc.h" |
20 | ||
21 | #undef NPTY | |
22 | #define NPTY 16 | |
45372428 | 23 | |
bdda6b91 | 24 | #define BUFSIZ 100 /* Chunk size iomoved from user */ |
e1d74936 | 25 | |
45372428 | 26 | /* |
e1d74936 BJ |
27 | * pts == /dev/tty[pP]? |
28 | * ptc == /dev/ptp[pP]? | |
45372428 | 29 | */ |
e1d74936 BJ |
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]; | |
45372428 | 37 | |
e1d74936 | 38 | #define PTCRCOLL 0x01 |
45372428 MT |
39 | |
40 | /*ARGSUSED*/ | |
41 | ptsopen(dev, flag) | |
42 | dev_t dev; | |
e1d74936 | 43 | { |
45372428 MT |
44 | register struct tty *tp; |
45 | ||
e1d74936 | 46 | if (minor(dev) >= NPTY) { |
45372428 MT |
47 | u.u_error = ENXIO; |
48 | return; | |
49 | } | |
50 | tp = &pt_tty[minor(dev)]; | |
e1d74936 | 51 | if ((tp->t_state & ISOPEN) == 0) { |
bdda6b91 BJ |
52 | ttychars(tp); /* Set up default chars */ |
53 | tp->t_flags = 0; /* No features (nor raw mode) */ | |
e1d74936 | 54 | } else if (tp->t_state&XCLUDE && u.u_uid != 0) { |
45372428 MT |
55 | u.u_error = EBUSY; |
56 | return; | |
57 | } | |
e1d74936 | 58 | if (tp->t_oproc) /* Ctrlr still around. */ |
45372428 | 59 | tp->t_state |= CARR_ON; |
e1d74936 | 60 | while ((tp->t_state & CARR_ON) == 0) { |
45372428 MT |
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; | |
bdda6b91 | 69 | { /* Close slave part of PTY */ |
45372428 MT |
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; | |
e1d74936 BJ |
78 | { |
79 | register struct tty *tp; | |
45372428 MT |
80 | |
81 | tp = &pt_tty[minor(dev)]; | |
e1d74936 | 82 | if (tp->t_oproc) { |
45372428 | 83 | (*linesw[tp->t_line].l_read)(tp); |
45372428 MT |
84 | wakeup((caddr_t)&tp->t_rawq.c_cf); |
85 | } | |
86 | } | |
87 | ||
88 | ptswrite(dev) | |
89 | dev_t dev; | |
e1d74936 | 90 | { |
45372428 MT |
91 | register struct tty *tp; |
92 | ||
93 | tp = &pt_tty[minor(dev)]; | |
e1d74936 | 94 | if (tp->t_oproc) |
45372428 MT |
95 | (*linesw[tp->t_line].l_write)(tp); |
96 | } | |
97 | ||
98 | ptsstart(tp) | |
e1d74936 BJ |
99 | struct tty *tp; |
100 | { | |
101 | struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; | |
102 | ||
103 | if (tp->t_state & TTSTOP) | |
45372428 | 104 | return; |
e1d74936 BJ |
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 | } | |
45372428 MT |
110 | wakeup((caddr_t)&tp->t_outq.c_cf); |
111 | } | |
112 | ||
113 | /*ARGSUSED*/ | |
114 | ptcopen(dev, flag) | |
e1d74936 BJ |
115 | dev_t dev; |
116 | int flag; | |
117 | { | |
45372428 MT |
118 | register struct tty *tp; |
119 | ||
e1d74936 | 120 | if (minor(dev) >= NPTY) { |
45372428 MT |
121 | u.u_error = ENXIO; |
122 | return; | |
123 | } | |
124 | tp = &pt_tty[minor(dev)]; | |
e1d74936 | 125 | if (tp->t_oproc) { |
45372428 MT |
126 | u.u_error = EIO; |
127 | return; | |
128 | } | |
e1d74936 BJ |
129 | tp->t_oproc = ptsstart; |
130 | if (tp->t_state & WOPEN) | |
45372428 MT |
131 | wakeup((caddr_t)&tp->t_rawq); |
132 | tp->t_state |= CARR_ON; | |
133 | } | |
134 | ||
135 | ptcclose(dev) | |
e1d74936 BJ |
136 | dev_t dev; |
137 | { | |
45372428 MT |
138 | register struct tty *tp; |
139 | ||
140 | tp = &pt_tty[minor(dev)]; | |
e1d74936 | 141 | if (tp->t_state & ISOPEN) |
45372428 | 142 | gsignal(tp->t_pgrp, SIGHUP); |
e1d74936 BJ |
143 | tp->t_state &= ~CARR_ON; /* virtual carrier gone */ |
144 | flushtty(tp, FREAD|FWRITE); | |
145 | tp->t_oproc = 0; /* mark closed */ | |
45372428 MT |
146 | } |
147 | ||
148 | ptcread(dev) | |
149 | dev_t dev; | |
e1d74936 | 150 | { |
45372428 MT |
151 | register struct tty *tp; |
152 | ||
153 | tp = &pt_tty[minor(dev)]; | |
e1d74936 | 154 | if ((tp->t_state&(CARR_ON|ISOPEN)) == 0) |
45372428 | 155 | return; |
e1d74936 | 156 | while (tp->t_outq.c_cc == 0 || (tp->t_state&TTSTOP)) |
45372428 | 157 | sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI); |
e1d74936 BJ |
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)) { | |
45372428 | 160 | tp->t_state &= ~ASLEEP; |
e1d74936 | 161 | wakeup((caddr_t)&tp->t_outq); |
45372428 MT |
162 | } |
163 | } | |
164 | ||
e1d74936 BJ |
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)]; | |
89b8a44c | 177 | if ((p = pti->pti_selr) && p->p_wchan == (caddr_t)&selwait) |
e1d74936 BJ |
178 | pti->pti_flags |= PTCRCOLL; |
179 | else | |
180 | pti->pti_selr = u.u_procp; | |
181 | return (0); | |
182 | } | |
183 | ||
45372428 MT |
184 | ptcwrite(dev) |
185 | dev_t dev; | |
e1d74936 | 186 | { |
45372428 MT |
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)]; | |
e1d74936 | 193 | if ((tp->t_state&(CARR_ON|ISOPEN)) == 0) |
45372428 | 194 | return; |
e1d74936 | 195 | while (u.u_count) { |
45372428 MT |
196 | cc = MIN(u.u_count, BUFSIZ); |
197 | cp = locbuf; | |
198 | iomove(cp, (unsigned)cc, B_WRITE); | |
e1d74936 | 199 | if (u.u_error) |
45372428 MT |
200 | break; |
201 | ce = cp + cc; | |
e1d74936 BJ |
202 | while (cp < ce) { |
203 | while (tp->t_delct && tp->t_rawq.c_cc >= TTYHOG - 2) { | |
45372428 MT |
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 | } | |
36612a8f | 209 | (*linesw[tp->t_line].l_rint)(*cp++, tp); |
45372428 MT |
210 | } |
211 | } | |
212 | } | |
213 | ||
45372428 MT |
214 | /*ARGSUSED*/ |
215 | ptyioctl(dev, cmd, addr, flag) | |
e1d74936 BJ |
216 | caddr_t addr; |
217 | dev_t dev; | |
218 | { | |
45372428 | 219 | register struct tty *tp; |
45372428 MT |
220 | |
221 | tp = &pt_tty[minor(dev)]; | |
e1d74936 BJ |
222 | /* IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG ??? */ |
223 | if (cdevsw[major(dev)].d_open == ptcopen && cmd == TIOCSETP) | |
224 | while (getc(&tp->t_outq) >= 0); | |
225 | if (ttioctl(tp, cmd, addr, dev) == 0) | |
45372428 MT |
226 | u.u_error = ENOTTY; |
227 | } | |
4f07e6e5 | 228 | #endif |