Commit | Line | Data |
---|---|---|
da7c5cc6 | 1 | /* |
0880b18e | 2 | * Copyright (c) 1982, 1986 Regents of the University of California. |
da7c5cc6 KM |
3 | * All rights reserved. The Berkeley software License Agreement |
4 | * specifies the terms and conditions for redistribution. | |
5 | * | |
0880b18e | 6 | * @(#)tty_pty.c 7.1 (Berkeley) %G% |
da7c5cc6 | 7 | */ |
be4367b3 | 8 | |
45372428 MT |
9 | /* |
10 | * Pseudo-teletype Driver | |
11 | * (Actually two drivers, requiring two entries in 'cdevsw') | |
45372428 | 12 | */ |
647d645f MT |
13 | #include "pty.h" |
14 | ||
f12183e4 | 15 | #if NPTY > 0 |
94368568 JB |
16 | #include "param.h" |
17 | #include "systm.h" | |
18 | #include "ioctl.h" | |
19 | #include "tty.h" | |
20 | #include "dir.h" | |
21 | #include "user.h" | |
22 | #include "conf.h" | |
23 | #include "file.h" | |
24 | #include "proc.h" | |
25 | #include "uio.h" | |
26 | #include "kernel.h" | |
941944c9 | 27 | |
b3c8737d | 28 | #if NPTY == 1 |
5bb90914 | 29 | #undef NPTY |
c91c01fe | 30 | #define NPTY 32 /* crude XXX */ |
b3c8737d | 31 | #endif |
45372428 | 32 | |
2bb0bef9 | 33 | #define BUFSIZ 100 /* Chunk size iomoved to/from user */ |
e1d74936 | 34 | |
45372428 | 35 | /* |
5bb90914 JB |
36 | * pts == /dev/tty[pqrs]? |
37 | * ptc == /dev/pty[pqrs]? | |
45372428 | 38 | */ |
e1d74936 BJ |
39 | struct tty pt_tty[NPTY]; |
40 | struct pt_ioctl { | |
1a954a11 | 41 | int pt_flags; |
1a954a11 | 42 | struct proc *pt_selr, *pt_selw; |
5bb90914 JB |
43 | u_char pt_send; |
44 | u_char pt_ucntl; | |
e1d74936 | 45 | } pt_ioctl[NPTY]; |
5bb90914 | 46 | int npty = NPTY; /* for pstat -t */ |
45372428 | 47 | |
1a954a11 BJ |
48 | #define PF_RCOLL 0x01 |
49 | #define PF_WCOLL 0x02 | |
50 | #define PF_NBIO 0x04 | |
51 | #define PF_PKT 0x08 /* packet mode */ | |
1e6d24b1 | 52 | #define PF_STOPPED 0x10 /* user told stopped */ |
defdbcd1 | 53 | #define PF_REMOTE 0x20 /* remote and flow controlled input */ |
0a2bd708 | 54 | #define PF_NOSTOP 0x40 |
5bb90914 | 55 | #define PF_UCNTL 0x80 /* user control mode */ |
45372428 MT |
56 | |
57 | /*ARGSUSED*/ | |
58 | ptsopen(dev, flag) | |
73c77d38 | 59 | dev_t dev; |
e1d74936 | 60 | { |
45372428 | 61 | register struct tty *tp; |
5bb90914 | 62 | int error; |
45372428 | 63 | |
5bb90914 JB |
64 | #ifdef lint |
65 | npty = npty; | |
66 | #endif | |
f21c8fb8 BJ |
67 | if (minor(dev) >= NPTY) |
68 | return (ENXIO); | |
45372428 | 69 | tp = &pt_tty[minor(dev)]; |
941944c9 | 70 | if ((tp->t_state & TS_ISOPEN) == 0) { |
bdda6b91 | 71 | ttychars(tp); /* Set up default chars */ |
d2f24af0 | 72 | tp->t_ispeed = tp->t_ospeed = EXTB; |
bdda6b91 | 73 | tp->t_flags = 0; /* No features (nor raw mode) */ |
f21c8fb8 BJ |
74 | } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) |
75 | return (EBUSY); | |
e1d74936 | 76 | if (tp->t_oproc) /* Ctrlr still around. */ |
941944c9 BJ |
77 | tp->t_state |= TS_CARR_ON; |
78 | while ((tp->t_state & TS_CARR_ON) == 0) { | |
79 | tp->t_state |= TS_WOPEN; | |
45372428 MT |
80 | sleep((caddr_t)&tp->t_rawq, TTIPRI); |
81 | } | |
5bb90914 JB |
82 | error = (*linesw[tp->t_line].l_open)(dev, tp); |
83 | ptcwakeup(tp, FREAD|FWRITE); | |
84 | return (error); | |
45372428 MT |
85 | } |
86 | ||
87 | ptsclose(dev) | |
73c77d38 | 88 | dev_t dev; |
941944c9 | 89 | { |
45372428 MT |
90 | register struct tty *tp; |
91 | ||
92 | tp = &pt_tty[minor(dev)]; | |
93 | (*linesw[tp->t_line].l_close)(tp); | |
4b39cb77 | 94 | ttyclose(tp); |
5bb90914 | 95 | ptcwakeup(tp, FREAD|FWRITE); |
45372428 MT |
96 | } |
97 | ||
ae9a0a69 | 98 | ptsread(dev, uio) |
73c77d38 | 99 | dev_t dev; |
ae9a0a69 | 100 | struct uio *uio; |
e1d74936 | 101 | { |
defdbcd1 BJ |
102 | register struct tty *tp = &pt_tty[minor(dev)]; |
103 | register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; | |
840510a3 | 104 | int error = 0; |
defdbcd1 BJ |
105 | |
106 | again: | |
107 | if (pti->pt_flags & PF_REMOTE) { | |
108 | while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) { | |
5bb90914 JB |
109 | if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) || |
110 | (u.u_procp->p_sigmask & sigmask(SIGTTIN)) || | |
defdbcd1 | 111 | u.u_procp->p_flag&SVFORK) |
840510a3 | 112 | return (EIO); |
defdbcd1 BJ |
113 | gsignal(u.u_procp->p_pgrp, SIGTTIN); |
114 | sleep((caddr_t)&lbolt, TTIPRI); | |
941944c9 | 115 | } |
5bb90914 | 116 | if (tp->t_canq.c_cc == 0) { |
840510a3 BJ |
117 | if (tp->t_state & TS_NBIO) |
118 | return (EWOULDBLOCK); | |
5bb90914 | 119 | sleep((caddr_t)&tp->t_canq, TTIPRI); |
defdbcd1 BJ |
120 | goto again; |
121 | } | |
5bb90914 JB |
122 | while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0) |
123 | if (ureadc(getc(&tp->t_canq), uio) < 0) { | |
840510a3 | 124 | error = EFAULT; |
ae9a0a69 BJ |
125 | break; |
126 | } | |
5bb90914 JB |
127 | if (tp->t_canq.c_cc == 1) |
128 | (void) getc(&tp->t_canq); | |
129 | if (tp->t_canq.c_cc) | |
840510a3 | 130 | return (error); |
defdbcd1 BJ |
131 | } else |
132 | if (tp->t_oproc) | |
840510a3 | 133 | error = (*linesw[tp->t_line].l_read)(tp, uio); |
5bb90914 | 134 | ptcwakeup(tp, FWRITE); |
840510a3 | 135 | return (error); |
45372428 MT |
136 | } |
137 | ||
941944c9 BJ |
138 | /* |
139 | * Write to pseudo-tty. | |
140 | * Wakeups of controlling tty will happen | |
141 | * indirectly, when tty driver calls ptsstart. | |
142 | */ | |
ae9a0a69 | 143 | ptswrite(dev, uio) |
73c77d38 | 144 | dev_t dev; |
ae9a0a69 | 145 | struct uio *uio; |
e1d74936 | 146 | { |
45372428 MT |
147 | register struct tty *tp; |
148 | ||
149 | tp = &pt_tty[minor(dev)]; | |
840510a3 BJ |
150 | if (tp->t_oproc == 0) |
151 | return (EIO); | |
152 | return ((*linesw[tp->t_line].l_write)(tp, uio)); | |
45372428 MT |
153 | } |
154 | ||
941944c9 BJ |
155 | /* |
156 | * Start output on pseudo-tty. | |
157 | * Wake up process selecting or sleeping for input from controlling tty. | |
158 | */ | |
45372428 | 159 | ptsstart(tp) |
e1d74936 BJ |
160 | struct tty *tp; |
161 | { | |
1e6d24b1 | 162 | register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; |
e1d74936 | 163 | |
941944c9 | 164 | if (tp->t_state & TS_TTSTOP) |
45372428 | 165 | return; |
1e6d24b1 BJ |
166 | if (pti->pt_flags & PF_STOPPED) { |
167 | pti->pt_flags &= ~PF_STOPPED; | |
168 | pti->pt_send = TIOCPKT_START; | |
169 | } | |
5bb90914 | 170 | ptcwakeup(tp, FREAD); |
d427b3b2 BJ |
171 | } |
172 | ||
5bb90914 | 173 | ptcwakeup(tp, flag) |
d427b3b2 BJ |
174 | struct tty *tp; |
175 | { | |
176 | struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; | |
177 | ||
5bb90914 JB |
178 | if (flag & FREAD) { |
179 | if (pti->pt_selr) { | |
180 | selwakeup(pti->pt_selr, pti->pt_flags & PF_RCOLL); | |
181 | pti->pt_selr = 0; | |
182 | pti->pt_flags &= ~PF_RCOLL; | |
183 | } | |
184 | wakeup((caddr_t)&tp->t_outq.c_cf); | |
185 | } | |
186 | if (flag & FWRITE) { | |
187 | if (pti->pt_selw) { | |
188 | selwakeup(pti->pt_selw, pti->pt_flags & PF_WCOLL); | |
189 | pti->pt_selw = 0; | |
190 | pti->pt_flags &= ~PF_WCOLL; | |
191 | } | |
192 | wakeup((caddr_t)&tp->t_rawq.c_cf); | |
e1d74936 | 193 | } |
45372428 MT |
194 | } |
195 | ||
196 | /*ARGSUSED*/ | |
197 | ptcopen(dev, flag) | |
e1d74936 BJ |
198 | dev_t dev; |
199 | int flag; | |
200 | { | |
45372428 | 201 | register struct tty *tp; |
1a954a11 | 202 | struct pt_ioctl *pti; |
45372428 | 203 | |
f21c8fb8 BJ |
204 | if (minor(dev) >= NPTY) |
205 | return (ENXIO); | |
45372428 | 206 | tp = &pt_tty[minor(dev)]; |
f21c8fb8 BJ |
207 | if (tp->t_oproc) |
208 | return (EIO); | |
e1d74936 | 209 | tp->t_oproc = ptsstart; |
f2f3b49b | 210 | (void)(*linesw[tp->t_line].l_modem)(tp, 1); |
941944c9 | 211 | tp->t_state |= TS_CARR_ON; |
1a954a11 BJ |
212 | pti = &pt_ioctl[minor(dev)]; |
213 | pti->pt_flags = 0; | |
214 | pti->pt_send = 0; | |
5bb90914 | 215 | pti->pt_ucntl = 0; |
f21c8fb8 | 216 | return (0); |
45372428 MT |
217 | } |
218 | ||
219 | ptcclose(dev) | |
e1d74936 BJ |
220 | dev_t dev; |
221 | { | |
45372428 MT |
222 | register struct tty *tp; |
223 | ||
224 | tp = &pt_tty[minor(dev)]; | |
f2f3b49b | 225 | (void)(*linesw[tp->t_line].l_modem)(tp, 0); |
e1d74936 | 226 | tp->t_oproc = 0; /* mark closed */ |
45372428 MT |
227 | } |
228 | ||
ae9a0a69 | 229 | ptcread(dev, uio) |
1a954a11 | 230 | dev_t dev; |
ae9a0a69 | 231 | struct uio *uio; |
e1d74936 | 232 | { |
840510a3 | 233 | register struct tty *tp = &pt_tty[minor(dev)]; |
5bb90914 | 234 | struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; |
2bb0bef9 SL |
235 | char buf[BUFSIZ]; |
236 | int error = 0, cc; | |
45372428 | 237 | |
5bb90914 JB |
238 | /* |
239 | * We want to block until the slave | |
240 | * is open, and there's something to read; | |
241 | * but if we lost the slave or we're NBIO, | |
242 | * then return the appropriate error instead. | |
243 | */ | |
244 | for (;;) { | |
245 | if (tp->t_state&TS_ISOPEN) { | |
246 | if (pti->pt_flags&PF_PKT && pti->pt_send) { | |
8011f5df | 247 | error = ureadc((int)pti->pt_send, uio); |
5bb90914 JB |
248 | if (error) |
249 | return (error); | |
250 | pti->pt_send = 0; | |
251 | return (0); | |
252 | } | |
253 | if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) { | |
8011f5df | 254 | error = ureadc((int)pti->pt_ucntl, uio); |
5bb90914 JB |
255 | if (error) |
256 | return (error); | |
257 | pti->pt_ucntl = 0; | |
258 | return (0); | |
259 | } | |
260 | if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) | |
261 | break; | |
1a954a11 | 262 | } |
2bb0bef9 SL |
263 | if ((tp->t_state&TS_CARR_ON) == 0) |
264 | return (EIO); | |
840510a3 BJ |
265 | if (pti->pt_flags&PF_NBIO) |
266 | return (EWOULDBLOCK); | |
45372428 | 267 | sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI); |
8b8271ac | 268 | } |
5bb90914 JB |
269 | if (pti->pt_flags & (PF_PKT|PF_UCNTL)) |
270 | error = ureadc(0, uio); | |
2bb0bef9 SL |
271 | while (uio->uio_resid > 0 && error == 0) { |
272 | cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ)); | |
273 | if (cc <= 0) | |
ae9a0a69 | 274 | break; |
2bb0bef9 SL |
275 | error = uiomove(buf, cc, UIO_READ, uio); |
276 | } | |
941944c9 BJ |
277 | if (tp->t_outq.c_cc <= TTLOWAT(tp)) { |
278 | if (tp->t_state&TS_ASLEEP) { | |
279 | tp->t_state &= ~TS_ASLEEP; | |
280 | wakeup((caddr_t)&tp->t_outq); | |
281 | } | |
282 | if (tp->t_wsel) { | |
283 | selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); | |
284 | tp->t_wsel = 0; | |
285 | tp->t_state &= ~TS_WCOLL; | |
286 | } | |
45372428 | 287 | } |
840510a3 | 288 | return (error); |
45372428 MT |
289 | } |
290 | ||
1a954a11 BJ |
291 | ptsstop(tp, flush) |
292 | register struct tty *tp; | |
293 | int flush; | |
294 | { | |
295 | struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; | |
5bb90914 | 296 | int flag; |
1a954a11 | 297 | |
1e6d24b1 BJ |
298 | /* note: FLUSHREAD and FLUSHWRITE already ok */ |
299 | if (flush == 0) { | |
300 | flush = TIOCPKT_STOP; | |
301 | pti->pt_flags |= PF_STOPPED; | |
5bb90914 | 302 | } else |
1e6d24b1 | 303 | pti->pt_flags &= ~PF_STOPPED; |
0a2bd708 | 304 | pti->pt_send |= flush; |
5bb90914 JB |
305 | /* change of perspective */ |
306 | flag = 0; | |
307 | if (flush & FREAD) | |
308 | flag |= FWRITE; | |
309 | if (flush & FWRITE) | |
310 | flag |= FREAD; | |
9d2a90b1 | 311 | ptcwakeup(tp, flag); |
1a954a11 BJ |
312 | } |
313 | ||
941944c9 | 314 | ptcselect(dev, rw) |
e1d74936 | 315 | dev_t dev; |
941944c9 | 316 | int rw; |
e1d74936 BJ |
317 | { |
318 | register struct tty *tp = &pt_tty[minor(dev)]; | |
defdbcd1 | 319 | struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; |
e1d74936 | 320 | struct proc *p; |
d427b3b2 | 321 | int s; |
e1d74936 | 322 | |
5bb90914 | 323 | if ((tp->t_state&TS_CARR_ON) == 0) |
e1d74936 | 324 | return (1); |
941944c9 BJ |
325 | switch (rw) { |
326 | ||
327 | case FREAD: | |
892f2f35 MK |
328 | /* |
329 | * Need to block timeouts (ttrstart). | |
330 | */ | |
331 | s = spltty(); | |
7cbd29e4 MK |
332 | if ((tp->t_state&TS_ISOPEN) && |
333 | tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) { | |
334 | splx(s); | |
335 | return (1); | |
336 | } | |
892f2f35 | 337 | splx(s); |
7cbd29e4 MK |
338 | /* FALLTHROUGH */ |
339 | ||
340 | case 0: /* exceptional */ | |
5bb90914 JB |
341 | if ((tp->t_state&TS_ISOPEN) && |
342 | (pti->pt_flags&PF_PKT && pti->pt_send || | |
892f2f35 | 343 | pti->pt_flags&PF_UCNTL && pti->pt_ucntl)) |
941944c9 | 344 | return (1); |
1a954a11 BJ |
345 | if ((p = pti->pt_selr) && p->p_wchan == (caddr_t)&selwait) |
346 | pti->pt_flags |= PF_RCOLL; | |
941944c9 | 347 | else |
1a954a11 | 348 | pti->pt_selr = u.u_procp; |
d427b3b2 | 349 | break; |
941944c9 | 350 | |
7cbd29e4 | 351 | |
941944c9 | 352 | case FWRITE: |
892f2f35 MK |
353 | if (tp->t_state&TS_ISOPEN) { |
354 | if (pti->pt_flags & PF_REMOTE) { | |
355 | if (tp->t_canq.c_cc == 0) | |
356 | return (1); | |
357 | } else { | |
358 | if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2) | |
359 | return (1); | |
360 | if (tp->t_canq.c_cc == 0 && | |
aec7dd3b | 361 | (tp->t_flags & (RAW|CBREAK)) == 0) |
892f2f35 MK |
362 | return (1); |
363 | } | |
d427b3b2 | 364 | } |
1a954a11 BJ |
365 | if ((p = pti->pt_selw) && p->p_wchan == (caddr_t)&selwait) |
366 | pti->pt_flags |= PF_WCOLL; | |
941944c9 | 367 | else |
1a954a11 | 368 | pti->pt_selw = u.u_procp; |
d427b3b2 | 369 | break; |
7cbd29e4 | 370 | |
941944c9 | 371 | } |
d427b3b2 | 372 | return (0); |
e1d74936 BJ |
373 | } |
374 | ||
ae9a0a69 | 375 | ptcwrite(dev, uio) |
941944c9 | 376 | dev_t dev; |
5bb90914 | 377 | register struct uio *uio; |
e1d74936 | 378 | { |
840510a3 | 379 | register struct tty *tp = &pt_tty[minor(dev)]; |
5bb90914 JB |
380 | register struct iovec *iov; |
381 | register char *cp; | |
382 | register int cc = 0; | |
45372428 | 383 | char locbuf[BUFSIZ]; |
941944c9 | 384 | int cnt = 0; |
defdbcd1 | 385 | struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; |
840510a3 | 386 | int error = 0; |
45372428 | 387 | |
defdbcd1 | 388 | again: |
5bb90914 JB |
389 | if ((tp->t_state&TS_ISOPEN) == 0) |
390 | goto block; | |
9d2a90b1 | 391 | if (pti->pt_flags & PF_REMOTE) { |
5bb90914 JB |
392 | if (tp->t_canq.c_cc) |
393 | goto block; | |
9d2a90b1 JB |
394 | while (uio->uio_iovcnt > 0 && tp->t_canq.c_cc < TTYHOG - 1) { |
395 | iov = uio->uio_iov; | |
396 | if (iov->iov_len == 0) { | |
397 | uio->uio_iovcnt--; | |
398 | uio->uio_iov++; | |
399 | continue; | |
400 | } | |
401 | if (cc == 0) { | |
402 | cc = MIN(iov->iov_len, BUFSIZ); | |
403 | cc = MIN(cc, TTYHOG - 1 - tp->t_canq.c_cc); | |
404 | cp = locbuf; | |
405 | error = uiomove(cp, cc, UIO_WRITE, uio); | |
406 | if (error) | |
407 | return (error); | |
408 | /* check again for safety */ | |
409 | if ((tp->t_state&TS_ISOPEN) == 0) | |
410 | return (EIO); | |
411 | } | |
412 | if (cc) | |
413 | (void) b_to_q(cp, cc, &tp->t_canq); | |
414 | cc = 0; | |
defdbcd1 | 415 | } |
5bb90914 JB |
416 | (void) putc(0, &tp->t_canq); |
417 | ttwakeup(tp); | |
418 | wakeup((caddr_t)&tp->t_canq); | |
419 | return (0); | |
420 | } | |
421 | while (uio->uio_iovcnt > 0) { | |
422 | iov = uio->uio_iov; | |
423 | if (cc == 0) { | |
424 | if (iov->iov_len == 0) { | |
425 | uio->uio_iovcnt--; | |
426 | uio->uio_iov++; | |
427 | continue; | |
45372428 | 428 | } |
5bb90914 JB |
429 | cc = MIN(iov->iov_len, BUFSIZ); |
430 | cp = locbuf; | |
431 | error = uiomove(cp, cc, UIO_WRITE, uio); | |
432 | if (error) | |
433 | return (error); | |
434 | /* check again for safety */ | |
435 | if ((tp->t_state&TS_ISOPEN) == 0) | |
436 | return (EIO); | |
437 | } | |
9d2a90b1 JB |
438 | while (cc > 0) { |
439 | if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 && | |
892f2f35 MK |
440 | (tp->t_canq.c_cc > 0 || |
441 | tp->t_flags & (RAW|CBREAK))) { | |
9d2a90b1 JB |
442 | wakeup((caddr_t)&tp->t_rawq); |
443 | goto block; | |
444 | } | |
36612a8f | 445 | (*linesw[tp->t_line].l_rint)(*cp++, tp); |
941944c9 | 446 | cnt++; |
9d2a90b1 | 447 | cc--; |
45372428 | 448 | } |
5bb90914 JB |
449 | cc = 0; |
450 | } | |
451 | return (0); | |
452 | block: | |
453 | /* | |
9d2a90b1 JB |
454 | * Come here to wait for slave to open, for space |
455 | * in outq, or space in rawq. | |
5bb90914 JB |
456 | */ |
457 | if ((tp->t_state&TS_CARR_ON) == 0) | |
458 | return (EIO); | |
459 | if (pti->pt_flags & PF_NBIO) { | |
5bb90914 JB |
460 | iov->iov_base -= cc; |
461 | iov->iov_len += cc; | |
462 | uio->uio_resid += cc; | |
463 | uio->uio_offset -= cc; | |
9d2a90b1 JB |
464 | if (cnt == 0) |
465 | return (EWOULDBLOCK); | |
5bb90914 JB |
466 | return (0); |
467 | } | |
468 | sleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI); | |
469 | goto again; | |
45372428 MT |
470 | } |
471 | ||
45372428 | 472 | /*ARGSUSED*/ |
4b72e2f9 SL |
473 | ptyioctl(dev, cmd, data, flag) |
474 | caddr_t data; | |
e1d74936 BJ |
475 | dev_t dev; |
476 | { | |
0a2bd708 BJ |
477 | register struct tty *tp = &pt_tty[minor(dev)]; |
478 | register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; | |
5bb90914 | 479 | int stop, error; |
f2f3b49b | 480 | extern ttyinput(); |
45372428 | 481 | |
f2f3b49b MK |
482 | /* |
483 | * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. | |
484 | * ttywflush(tp) will hang if there are characters in the outq. | |
485 | */ | |
4b72e2f9 SL |
486 | if (cdevsw[major(dev)].d_open == ptcopen) |
487 | switch (cmd) { | |
488 | ||
489 | case TIOCPKT: | |
5bb90914 JB |
490 | if (*(int *)data) { |
491 | if (pti->pt_flags & PF_UCNTL) | |
492 | return (EINVAL); | |
1a954a11 | 493 | pti->pt_flags |= PF_PKT; |
5bb90914 | 494 | } else |
1a954a11 | 495 | pti->pt_flags &= ~PF_PKT; |
f21c8fb8 | 496 | return (0); |
4b72e2f9 | 497 | |
5bb90914 JB |
498 | case TIOCUCNTL: |
499 | if (*(int *)data) { | |
500 | if (pti->pt_flags & PF_PKT) | |
501 | return (EINVAL); | |
502 | pti->pt_flags |= PF_UCNTL; | |
503 | } else | |
504 | pti->pt_flags &= ~PF_UCNTL; | |
505 | return (0); | |
506 | ||
4b72e2f9 SL |
507 | case TIOCREMOTE: |
508 | if (*(int *)data) | |
defdbcd1 BJ |
509 | pti->pt_flags |= PF_REMOTE; |
510 | else | |
511 | pti->pt_flags &= ~PF_REMOTE; | |
88a7a62a | 512 | ttyflush(tp, FREAD|FWRITE); |
f21c8fb8 | 513 | return (0); |
4b72e2f9 SL |
514 | |
515 | case FIONBIO: | |
516 | if (*(int *)data) | |
1a954a11 | 517 | pti->pt_flags |= PF_NBIO; |
8b8271ac | 518 | else |
1a954a11 | 519 | pti->pt_flags &= ~PF_NBIO; |
f21c8fb8 | 520 | return (0); |
4b72e2f9 SL |
521 | |
522 | case TIOCSETP: | |
f2f3b49b MK |
523 | case TIOCSETN: |
524 | case TIOCSETD: | |
4b72e2f9 SL |
525 | while (getc(&tp->t_outq) >= 0) |
526 | ; | |
527 | break; | |
8b8271ac | 528 | } |
477d62ec | 529 | error = ttioctl(tp, cmd, data, flag); |
f2f3b49b MK |
530 | /* |
531 | * Since we use the tty queues internally, | |
532 | * pty's can't be switched to disciplines which overwrite | |
533 | * the queues. We can't tell anything about the discipline | |
534 | * from here... | |
535 | */ | |
536 | if (linesw[tp->t_line].l_rint != ttyinput) { | |
537 | (*linesw[tp->t_line].l_close)(tp); | |
538 | tp->t_line = 0; | |
539 | (void)(*linesw[tp->t_line].l_open)(dev, tp); | |
540 | error = ENOTTY; | |
541 | } | |
5bb90914 JB |
542 | if (error < 0) { |
543 | if (pti->pt_flags & PF_UCNTL && | |
97d7430f | 544 | (cmd & ~0xff) == UIOCCMD(0)) { |
5bb90914 JB |
545 | if (cmd & 0xff) { |
546 | pti->pt_ucntl = (u_char)cmd; | |
547 | ptcwakeup(tp, FREAD); | |
548 | } | |
549 | return (0); | |
550 | } | |
f21c8fb8 | 551 | error = ENOTTY; |
5bb90914 JB |
552 | } |
553 | stop = (tp->t_flags & RAW) == 0 && | |
554 | tp->t_stopc == CTRL(s) && tp->t_startc == CTRL(q); | |
0a2bd708 BJ |
555 | if (pti->pt_flags & PF_NOSTOP) { |
556 | if (stop) { | |
b31eb1ff | 557 | pti->pt_send &= ~TIOCPKT_NOSTOP; |
0a2bd708 BJ |
558 | pti->pt_send |= TIOCPKT_DOSTOP; |
559 | pti->pt_flags &= ~PF_NOSTOP; | |
5bb90914 | 560 | ptcwakeup(tp, FREAD); |
0a2bd708 BJ |
561 | } |
562 | } else { | |
5bb90914 | 563 | if (!stop) { |
0a2bd708 BJ |
564 | pti->pt_send &= ~TIOCPKT_DOSTOP; |
565 | pti->pt_send |= TIOCPKT_NOSTOP; | |
566 | pti->pt_flags |= PF_NOSTOP; | |
5bb90914 | 567 | ptcwakeup(tp, FREAD); |
0a2bd708 BJ |
568 | } |
569 | } | |
f21c8fb8 | 570 | return (error); |
45372428 | 571 | } |
4f07e6e5 | 572 | #endif |