Deleted Added
full compact
pty.c (66067) pty.c (69774)
1/*
2 * Copyright (c) 1982, 1986, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)tty_pty.c 8.4 (Berkeley) 2/20/95
1/*
2 * Copyright (c) 1982, 1986, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)tty_pty.c 8.4 (Berkeley) 2/20/95
34 * $FreeBSD: head/sys/kern/tty_pty.c 66067 2000-09-19 10:28:44Z phk $
34 * $FreeBSD: head/sys/kern/tty_pty.c 69774 2000-12-08 20:09:00Z phk $
35 */
36
37/*
38 * Pseudo-teletype Driver
39 * (Actually two drivers, requiring two entries in 'cdevsw')
40 */
41#include "opt_compat.h"
42#include <sys/param.h>
43#include <sys/systm.h>
44#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
45#include <sys/ioctl_compat.h>
46#endif
47#include <sys/proc.h>
48#include <sys/tty.h>
49#include <sys/conf.h>
50#include <sys/fcntl.h>
51#include <sys/poll.h>
52#include <sys/kernel.h>
53#include <sys/vnode.h>
54#include <sys/signalvar.h>
55#include <sys/malloc.h>
56
35 */
36
37/*
38 * Pseudo-teletype Driver
39 * (Actually two drivers, requiring two entries in 'cdevsw')
40 */
41#include "opt_compat.h"
42#include <sys/param.h>
43#include <sys/systm.h>
44#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
45#include <sys/ioctl_compat.h>
46#endif
47#include <sys/proc.h>
48#include <sys/tty.h>
49#include <sys/conf.h>
50#include <sys/fcntl.h>
51#include <sys/poll.h>
52#include <sys/kernel.h>
53#include <sys/vnode.h>
54#include <sys/signalvar.h>
55#include <sys/malloc.h>
56
57MALLOC_DEFINE(M_PTY, "ptys", "pty data structures");
57static MALLOC_DEFINE(M_PTY, "ptys", "pty data structures");
58
59static void ptsstart __P((struct tty *tp));
60static void ptsstop __P((struct tty *tp, int rw));
61static void ptcwakeup __P((struct tty *tp, int flag));
62static dev_t ptyinit __P((int n));
63
64static d_open_t ptsopen;
65static d_close_t ptsclose;
66static d_read_t ptsread;
67static d_write_t ptswrite;
68static d_ioctl_t ptyioctl;
69static d_open_t ptcopen;
70static d_close_t ptcclose;
71static d_read_t ptcread;
72static d_write_t ptcwrite;
73static d_poll_t ptcpoll;
74
75#define CDEV_MAJOR_S 5
76static struct cdevsw pts_cdevsw = {
77 /* open */ ptsopen,
78 /* close */ ptsclose,
79 /* read */ ptsread,
80 /* write */ ptswrite,
81 /* ioctl */ ptyioctl,
82 /* poll */ ttypoll,
83 /* mmap */ nommap,
84 /* strategy */ nostrategy,
85 /* name */ "pts",
86 /* maj */ CDEV_MAJOR_S,
87 /* dump */ nodump,
88 /* psize */ nopsize,
89 /* flags */ D_TTY,
90 /* bmaj */ -1
91};
92
93#define CDEV_MAJOR_C 6
94static struct cdevsw ptc_cdevsw = {
95 /* open */ ptcopen,
96 /* close */ ptcclose,
97 /* read */ ptcread,
98 /* write */ ptcwrite,
99 /* ioctl */ ptyioctl,
100 /* poll */ ptcpoll,
101 /* mmap */ nommap,
102 /* strategy */ nostrategy,
103 /* name */ "ptc",
104 /* maj */ CDEV_MAJOR_C,
105 /* dump */ nodump,
106 /* psize */ nopsize,
107 /* flags */ D_TTY,
108 /* bmaj */ -1
109};
110
111#define BUFSIZ 100 /* Chunk size iomoved to/from user */
112
113struct pt_ioctl {
114 int pt_flags;
115 struct selinfo pt_selr, pt_selw;
116 u_char pt_send;
117 u_char pt_ucntl;
118 struct tty pt_tty;
119 dev_t devs, devc;
120 struct prison *pt_prison;
121};
122
123#define PF_PKT 0x08 /* packet mode */
124#define PF_STOPPED 0x10 /* user told stopped */
125#define PF_REMOTE 0x20 /* remote and flow controlled input */
126#define PF_NOSTOP 0x40
127#define PF_UCNTL 0x80 /* user control mode */
128
129/*
130 * This function creates and initializes a pts/ptc pair
131 *
132 * pts == /dev/tty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv]
133 * ptc == /dev/pty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv]
134 *
135 * XXX: define and add mapping of upper minor bits to allow more
136 * than 256 ptys.
137 */
138static dev_t
139ptyinit(n)
140 int n;
141{
142 dev_t devs, devc;
143 char *names = "pqrsPQRS";
144 struct pt_ioctl *pt;
145
146 /* For now we only map the lower 8 bits of the minor */
147 if (n & ~0xff)
148 return (NODEV);
149
150 pt = malloc(sizeof(*pt), M_PTY, M_WAITOK);
151 bzero(pt, sizeof(*pt));
152 pt->devs = devs = make_dev(&pts_cdevsw, n,
153 UID_ROOT, GID_WHEEL, 0666, "tty%c%r", names[n / 32], n % 32);
154 pt->devc = devc = make_dev(&ptc_cdevsw, n,
155 UID_ROOT, GID_WHEEL, 0666, "pty%c%r", names[n / 32], n % 32);
156
157 devs->si_drv1 = devc->si_drv1 = pt;
158 devs->si_tty = devc->si_tty = &pt->pt_tty;
159 ttyregister(&pt->pt_tty);
160 return (devc);
161}
162
163/*ARGSUSED*/
164static int
165ptsopen(dev, flag, devtype, p)
166 dev_t dev;
167 int flag, devtype;
168 struct proc *p;
169{
170 register struct tty *tp;
171 int error;
172 struct pt_ioctl *pti;
173
174 if (!dev->si_drv1)
175 ptyinit(minor(dev));
176 if (!dev->si_drv1)
177 return(ENXIO);
178 pti = dev->si_drv1;
179 tp = dev->si_tty;
180 if ((tp->t_state & TS_ISOPEN) == 0) {
181 ttychars(tp); /* Set up default chars */
182 tp->t_iflag = TTYDEF_IFLAG;
183 tp->t_oflag = TTYDEF_OFLAG;
184 tp->t_lflag = TTYDEF_LFLAG;
185 tp->t_cflag = TTYDEF_CFLAG;
186 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
187 } else if (tp->t_state & TS_XCLUDE && suser(p)) {
188 return (EBUSY);
189 } else if (pti->pt_prison != p->p_prison) {
190 return (EBUSY);
191 }
192 if (tp->t_oproc) /* Ctrlr still around. */
193 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
194 while ((tp->t_state & TS_CARR_ON) == 0) {
195 if (flag&FNONBLOCK)
196 break;
197 error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH,
198 "ptsopn", 0);
199 if (error)
200 return (error);
201 }
202 error = (*linesw[tp->t_line].l_open)(dev, tp);
203 if (error == 0)
204 ptcwakeup(tp, FREAD|FWRITE);
205 return (error);
206}
207
208static int
209ptsclose(dev, flag, mode, p)
210 dev_t dev;
211 int flag, mode;
212 struct proc *p;
213{
214 register struct tty *tp;
215 int err;
216
217 tp = dev->si_tty;
218 err = (*linesw[tp->t_line].l_close)(tp, flag);
219 ptsstop(tp, FREAD|FWRITE);
220 (void) ttyclose(tp);
221 return (err);
222}
223
224static int
225ptsread(dev, uio, flag)
226 dev_t dev;
227 struct uio *uio;
228 int flag;
229{
230 struct proc *p = curproc;
231 register struct tty *tp = dev->si_tty;
232 register struct pt_ioctl *pti = dev->si_drv1;
233 int error = 0;
234
235again:
236 if (pti->pt_flags & PF_REMOTE) {
237 while (isbackground(p, tp)) {
238 if (SIGISMEMBER(p->p_sigignore, SIGTTIN) ||
239 SIGISMEMBER(p->p_sigmask, SIGTTIN) ||
240 p->p_pgrp->pg_jobc == 0 || p->p_flag & P_PPWAIT)
241 return (EIO);
242 pgsignal(p->p_pgrp, SIGTTIN, 1);
243 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ptsbg",
244 0);
245 if (error)
246 return (error);
247 }
248 if (tp->t_canq.c_cc == 0) {
249 if (flag & IO_NDELAY)
250 return (EWOULDBLOCK);
251 error = ttysleep(tp, TSA_PTS_READ(tp), TTIPRI | PCATCH,
252 "ptsin", 0);
253 if (error)
254 return (error);
255 goto again;
256 }
257 while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0)
258 if (ureadc(getc(&tp->t_canq), uio) < 0) {
259 error = EFAULT;
260 break;
261 }
262 if (tp->t_canq.c_cc == 1)
263 (void) getc(&tp->t_canq);
264 if (tp->t_canq.c_cc)
265 return (error);
266 } else
267 if (tp->t_oproc)
268 error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
269 ptcwakeup(tp, FWRITE);
270 return (error);
271}
272
273/*
274 * Write to pseudo-tty.
275 * Wakeups of controlling tty will happen
276 * indirectly, when tty driver calls ptsstart.
277 */
278static int
279ptswrite(dev, uio, flag)
280 dev_t dev;
281 struct uio *uio;
282 int flag;
283{
284 register struct tty *tp;
285
286 tp = dev->si_tty;
287 if (tp->t_oproc == 0)
288 return (EIO);
289 return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
290}
291
292/*
293 * Start output on pseudo-tty.
294 * Wake up process selecting or sleeping for input from controlling tty.
295 */
296static void
297ptsstart(tp)
298 struct tty *tp;
299{
300 register struct pt_ioctl *pti = tp->t_dev->si_drv1;
301
302 if (tp->t_state & TS_TTSTOP)
303 return;
304 if (pti->pt_flags & PF_STOPPED) {
305 pti->pt_flags &= ~PF_STOPPED;
306 pti->pt_send = TIOCPKT_START;
307 }
308 ptcwakeup(tp, FREAD);
309}
310
311static void
312ptcwakeup(tp, flag)
313 struct tty *tp;
314 int flag;
315{
316 struct pt_ioctl *pti = tp->t_dev->si_drv1;
317
318 if (flag & FREAD) {
319 selwakeup(&pti->pt_selr);
320 wakeup(TSA_PTC_READ(tp));
321 }
322 if (flag & FWRITE) {
323 selwakeup(&pti->pt_selw);
324 wakeup(TSA_PTC_WRITE(tp));
325 }
326}
327
328static int
329ptcopen(dev, flag, devtype, p)
330 dev_t dev;
331 int flag, devtype;
332 struct proc *p;
333{
334 register struct tty *tp;
335 struct pt_ioctl *pti;
336
337 if (!dev->si_drv1)
338 ptyinit(minor(dev));
339 if (!dev->si_drv1)
340 return(ENXIO);
341 tp = dev->si_tty;
342 if (tp->t_oproc)
343 return (EIO);
344 tp->t_timeout = -1;
345 tp->t_oproc = ptsstart;
346 tp->t_stop = ptsstop;
347 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
348 tp->t_lflag &= ~EXTPROC;
349 pti = dev->si_drv1;
350 pti->pt_prison = p->p_prison;
351 pti->pt_flags = 0;
352 pti->pt_send = 0;
353 pti->pt_ucntl = 0;
354 return (0);
355}
356
357static int
358ptcclose(dev, flags, fmt, p)
359 dev_t dev;
360 int flags;
361 int fmt;
362 struct proc *p;
363{
364 register struct tty *tp;
365
366 tp = dev->si_tty;
367 (void)(*linesw[tp->t_line].l_modem)(tp, 0);
368
369 /*
370 * XXX MDMBUF makes no sense for ptys but would inhibit the above
371 * l_modem(). CLOCAL makes sense but isn't supported. Special
372 * l_modem()s that ignore carrier drop make no sense for ptys but
373 * may be in use because other parts of the line discipline make
374 * sense for ptys. Recover by doing everything that a normal
375 * ttymodem() would have done except for sending a SIGHUP.
376 */
377 if (tp->t_state & TS_ISOPEN) {
378 tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED);
379 tp->t_state |= TS_ZOMBIE;
380 ttyflush(tp, FREAD | FWRITE);
381 }
382
383 tp->t_oproc = 0; /* mark closed */
384 return (0);
385}
386
387static int
388ptcread(dev, uio, flag)
389 dev_t dev;
390 struct uio *uio;
391 int flag;
392{
393 register struct tty *tp = dev->si_tty;
394 struct pt_ioctl *pti = dev->si_drv1;
395 char buf[BUFSIZ];
396 int error = 0, cc;
397
398 /*
399 * We want to block until the slave
400 * is open, and there's something to read;
401 * but if we lost the slave or we're NBIO,
402 * then return the appropriate error instead.
403 */
404 for (;;) {
405 if (tp->t_state&TS_ISOPEN) {
406 if (pti->pt_flags&PF_PKT && pti->pt_send) {
407 error = ureadc((int)pti->pt_send, uio);
408 if (error)
409 return (error);
410 if (pti->pt_send & TIOCPKT_IOCTL) {
411 cc = min(uio->uio_resid,
412 sizeof(tp->t_termios));
413 uiomove((caddr_t)&tp->t_termios, cc,
414 uio);
415 }
416 pti->pt_send = 0;
417 return (0);
418 }
419 if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) {
420 error = ureadc((int)pti->pt_ucntl, uio);
421 if (error)
422 return (error);
423 pti->pt_ucntl = 0;
424 return (0);
425 }
426 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
427 break;
428 }
429 if ((tp->t_state & TS_CONNECTED) == 0)
430 return (0); /* EOF */
431 if (flag & IO_NDELAY)
432 return (EWOULDBLOCK);
433 error = tsleep(TSA_PTC_READ(tp), TTIPRI | PCATCH, "ptcin", 0);
434 if (error)
435 return (error);
436 }
437 if (pti->pt_flags & (PF_PKT|PF_UCNTL))
438 error = ureadc(0, uio);
439 while (uio->uio_resid > 0 && error == 0) {
440 cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ));
441 if (cc <= 0)
442 break;
443 error = uiomove(buf, cc, uio);
444 }
445 ttwwakeup(tp);
446 return (error);
447}
448
449static void
450ptsstop(tp, flush)
451 register struct tty *tp;
452 int flush;
453{
454 struct pt_ioctl *pti = tp->t_dev->si_drv1;
455 int flag;
456
457 /* note: FLUSHREAD and FLUSHWRITE already ok */
458 if (flush == 0) {
459 flush = TIOCPKT_STOP;
460 pti->pt_flags |= PF_STOPPED;
461 } else
462 pti->pt_flags &= ~PF_STOPPED;
463 pti->pt_send |= flush;
464 /* change of perspective */
465 flag = 0;
466 if (flush & FREAD)
467 flag |= FWRITE;
468 if (flush & FWRITE)
469 flag |= FREAD;
470 ptcwakeup(tp, flag);
471}
472
473static int
474ptcpoll(dev, events, p)
475 dev_t dev;
476 int events;
477 struct proc *p;
478{
479 register struct tty *tp = dev->si_tty;
480 struct pt_ioctl *pti = dev->si_drv1;
481 int revents = 0;
482 int s;
483
484 if ((tp->t_state & TS_CONNECTED) == 0)
485 return (seltrue(dev, events, p) | POLLHUP);
486
487 /*
488 * Need to block timeouts (ttrstart).
489 */
490 s = spltty();
491
492 if (events & (POLLIN | POLLRDNORM))
493 if ((tp->t_state & TS_ISOPEN) &&
494 ((tp->t_outq.c_cc && (tp->t_state & TS_TTSTOP) == 0) ||
495 ((pti->pt_flags & PF_PKT) && pti->pt_send) ||
496 ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl)))
497 revents |= events & (POLLIN | POLLRDNORM);
498
499 if (events & (POLLOUT | POLLWRNORM))
500 if (tp->t_state & TS_ISOPEN &&
501 ((pti->pt_flags & PF_REMOTE) ?
502 (tp->t_canq.c_cc == 0) :
503 ((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG - 2) ||
504 (tp->t_canq.c_cc == 0 && (tp->t_iflag & ICANON)))))
505 revents |= events & (POLLOUT | POLLWRNORM);
506
507 if (events & POLLHUP)
508 if ((tp->t_state & TS_CARR_ON) == 0)
509 revents |= POLLHUP;
510
511 if (revents == 0) {
512 if (events & (POLLIN | POLLRDNORM))
513 selrecord(p, &pti->pt_selr);
514
515 if (events & (POLLOUT | POLLWRNORM))
516 selrecord(p, &pti->pt_selw);
517 }
518 splx(s);
519
520 return (revents);
521}
522
523static int
524ptcwrite(dev, uio, flag)
525 dev_t dev;
526 register struct uio *uio;
527 int flag;
528{
529 register struct tty *tp = dev->si_tty;
530 register u_char *cp = 0;
531 register int cc = 0;
532 u_char locbuf[BUFSIZ];
533 int cnt = 0;
534 struct pt_ioctl *pti = dev->si_drv1;
535 int error = 0;
536
537again:
538 if ((tp->t_state&TS_ISOPEN) == 0)
539 goto block;
540 if (pti->pt_flags & PF_REMOTE) {
541 if (tp->t_canq.c_cc)
542 goto block;
543 while ((uio->uio_resid > 0 || cc > 0) &&
544 tp->t_canq.c_cc < TTYHOG - 1) {
545 if (cc == 0) {
546 cc = min(uio->uio_resid, BUFSIZ);
547 cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc);
548 cp = locbuf;
549 error = uiomove((caddr_t)cp, cc, uio);
550 if (error)
551 return (error);
552 /* check again for safety */
553 if ((tp->t_state & TS_ISOPEN) == 0) {
554 /* adjust as usual */
555 uio->uio_resid += cc;
556 return (EIO);
557 }
558 }
559 if (cc > 0) {
560 cc = b_to_q((char *)cp, cc, &tp->t_canq);
561 /*
562 * XXX we don't guarantee that the canq size
563 * is >= TTYHOG, so the above b_to_q() may
564 * leave some bytes uncopied. However, space
565 * is guaranteed for the null terminator if
566 * we don't fail here since (TTYHOG - 1) is
567 * not a multiple of CBSIZE.
568 */
569 if (cc > 0)
570 break;
571 }
572 }
573 /* adjust for data copied in but not written */
574 uio->uio_resid += cc;
575 (void) putc(0, &tp->t_canq);
576 ttwakeup(tp);
577 wakeup(TSA_PTS_READ(tp));
578 return (0);
579 }
580 while (uio->uio_resid > 0 || cc > 0) {
581 if (cc == 0) {
582 cc = min(uio->uio_resid, BUFSIZ);
583 cp = locbuf;
584 error = uiomove((caddr_t)cp, cc, uio);
585 if (error)
586 return (error);
587 /* check again for safety */
588 if ((tp->t_state & TS_ISOPEN) == 0) {
589 /* adjust for data copied in but not written */
590 uio->uio_resid += cc;
591 return (EIO);
592 }
593 }
594 while (cc > 0) {
595 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
596 (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) {
597 wakeup(TSA_HUP_OR_INPUT(tp));
598 goto block;
599 }
600 (*linesw[tp->t_line].l_rint)(*cp++, tp);
601 cnt++;
602 cc--;
603 }
604 cc = 0;
605 }
606 return (0);
607block:
608 /*
609 * Come here to wait for slave to open, for space
610 * in outq, or space in rawq, or an empty canq.
611 */
612 if ((tp->t_state & TS_CONNECTED) == 0) {
613 /* adjust for data copied in but not written */
614 uio->uio_resid += cc;
615 return (EIO);
616 }
617 if (flag & IO_NDELAY) {
618 /* adjust for data copied in but not written */
619 uio->uio_resid += cc;
620 if (cnt == 0)
621 return (EWOULDBLOCK);
622 return (0);
623 }
624 error = tsleep(TSA_PTC_WRITE(tp), TTOPRI | PCATCH, "ptcout", 0);
625 if (error) {
626 /* adjust for data copied in but not written */
627 uio->uio_resid += cc;
628 return (error);
629 }
630 goto again;
631}
632
633/*ARGSUSED*/
634static int
635ptyioctl(dev, cmd, data, flag, p)
636 dev_t dev;
637 u_long cmd;
638 caddr_t data;
639 int flag;
640 struct proc *p;
641{
642 register struct tty *tp = dev->si_tty;
643 register struct pt_ioctl *pti = dev->si_drv1;
644 register u_char *cc = tp->t_cc;
645 int stop, error;
646
647 if (devsw(dev)->d_open == ptcopen) {
648 switch (cmd) {
649
650 case TIOCGPGRP:
651 /*
652 * We avoid calling ttioctl on the controller since,
653 * in that case, tp must be the controlling terminal.
654 */
655 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
656 return (0);
657
658 case TIOCPKT:
659 if (*(int *)data) {
660 if (pti->pt_flags & PF_UCNTL)
661 return (EINVAL);
662 pti->pt_flags |= PF_PKT;
663 } else
664 pti->pt_flags &= ~PF_PKT;
665 return (0);
666
667 case TIOCUCNTL:
668 if (*(int *)data) {
669 if (pti->pt_flags & PF_PKT)
670 return (EINVAL);
671 pti->pt_flags |= PF_UCNTL;
672 } else
673 pti->pt_flags &= ~PF_UCNTL;
674 return (0);
675
676 case TIOCREMOTE:
677 if (*(int *)data)
678 pti->pt_flags |= PF_REMOTE;
679 else
680 pti->pt_flags &= ~PF_REMOTE;
681 ttyflush(tp, FREAD|FWRITE);
682 return (0);
683 }
684
685 /*
686 * The rest of the ioctls shouldn't be called until
687 * the slave is open.
688 */
689 if ((tp->t_state & TS_ISOPEN) == 0)
690 return (EAGAIN);
691
692 switch (cmd) {
693#ifdef COMPAT_43
694 case TIOCSETP:
695 case TIOCSETN:
696#endif
697 case TIOCSETD:
698 case TIOCSETA:
699 case TIOCSETAW:
700 case TIOCSETAF:
701 /*
702 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
703 * ttywflush(tp) will hang if there are characters in
704 * the outq.
705 */
706 ndflush(&tp->t_outq, tp->t_outq.c_cc);
707 break;
708
709 case TIOCSIG:
710 if (*(unsigned int *)data >= NSIG ||
711 *(unsigned int *)data == 0)
712 return(EINVAL);
713 if ((tp->t_lflag&NOFLSH) == 0)
714 ttyflush(tp, FREAD|FWRITE);
715 pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
716 if ((*(unsigned int *)data == SIGINFO) &&
717 ((tp->t_lflag&NOKERNINFO) == 0))
718 ttyinfo(tp);
719 return(0);
720 }
721 }
722 if (cmd == TIOCEXT) {
723 /*
724 * When the EXTPROC bit is being toggled, we need
725 * to send an TIOCPKT_IOCTL if the packet driver
726 * is turned on.
727 */
728 if (*(int *)data) {
729 if (pti->pt_flags & PF_PKT) {
730 pti->pt_send |= TIOCPKT_IOCTL;
731 ptcwakeup(tp, FREAD);
732 }
733 tp->t_lflag |= EXTPROC;
734 } else {
735 if ((tp->t_lflag & EXTPROC) &&
736 (pti->pt_flags & PF_PKT)) {
737 pti->pt_send |= TIOCPKT_IOCTL;
738 ptcwakeup(tp, FREAD);
739 }
740 tp->t_lflag &= ~EXTPROC;
741 }
742 return(0);
743 }
744 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
745 if (error == ENOIOCTL)
746 error = ttioctl(tp, cmd, data, flag);
747 if (error == ENOIOCTL) {
748 if (pti->pt_flags & PF_UCNTL &&
749 (cmd & ~0xff) == UIOCCMD(0)) {
750 if (cmd & 0xff) {
751 pti->pt_ucntl = (u_char)cmd;
752 ptcwakeup(tp, FREAD);
753 }
754 return (0);
755 }
756 error = ENOTTY;
757 }
758 /*
759 * If external processing and packet mode send ioctl packet.
760 */
761 if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) {
762 switch(cmd) {
763 case TIOCSETA:
764 case TIOCSETAW:
765 case TIOCSETAF:
766#ifdef COMPAT_43
767 case TIOCSETP:
768 case TIOCSETN:
769#endif
770#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
771 case TIOCSETC:
772 case TIOCSLTC:
773 case TIOCLBIS:
774 case TIOCLBIC:
775 case TIOCLSET:
776#endif
777 pti->pt_send |= TIOCPKT_IOCTL;
778 ptcwakeup(tp, FREAD);
779 default:
780 break;
781 }
782 }
783 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
784 && CCEQ(cc[VSTART], CTRL('q'));
785 if (pti->pt_flags & PF_NOSTOP) {
786 if (stop) {
787 pti->pt_send &= ~TIOCPKT_NOSTOP;
788 pti->pt_send |= TIOCPKT_DOSTOP;
789 pti->pt_flags &= ~PF_NOSTOP;
790 ptcwakeup(tp, FREAD);
791 }
792 } else {
793 if (!stop) {
794 pti->pt_send &= ~TIOCPKT_DOSTOP;
795 pti->pt_send |= TIOCPKT_NOSTOP;
796 pti->pt_flags |= PF_NOSTOP;
797 ptcwakeup(tp, FREAD);
798 }
799 }
800 return (error);
801}
802
803
804static void ptc_drvinit __P((void *unused));
805
806static void pty_clone __P((void *arg, char *name, int namelen, dev_t *dev));
807
808static void
809pty_clone(arg, name, namelen, dev)
810 void *arg;
811 char *name;
812 int namelen;
813 dev_t *dev;
814{
815 int u;
816
817 if (*dev != NODEV)
818 return;
819 if (bcmp(name, "pty", 3) != 0)
820 return;
821 if (name[5] != '\0')
822 return;
823 switch (name[3]) {
824 case 'p': u = 0; break;
825 case 'q': u = 32; break;
826 case 'r': u = 64; break;
827 case 's': u = 96; break;
828 case 'P': u = 128; break;
829 case 'Q': u = 160; break;
830 case 'R': u = 192; break;
831 case 'S': u = 224; break;
832 default: return;
833 }
834 if (name[4] >= '0' && name[4] <= '9')
835 u += name[4] - '0';
836 else if (name[4] >= 'a' && name[4] <= 'v')
837 u += name[4] - 'a' + 10;
838 else
839 return;
840 *dev = ptyinit(u);
841 return;
842}
843
844static void
845ptc_drvinit(unused)
846 void *unused;
847{
848 EVENTHANDLER_REGISTER(dev_clone, pty_clone, 0, 1000);
849 cdevsw_add(&pts_cdevsw);
850 cdevsw_add(&ptc_cdevsw);
851}
852
853SYSINIT(ptcdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR_C,ptc_drvinit,NULL)
58
59static void ptsstart __P((struct tty *tp));
60static void ptsstop __P((struct tty *tp, int rw));
61static void ptcwakeup __P((struct tty *tp, int flag));
62static dev_t ptyinit __P((int n));
63
64static d_open_t ptsopen;
65static d_close_t ptsclose;
66static d_read_t ptsread;
67static d_write_t ptswrite;
68static d_ioctl_t ptyioctl;
69static d_open_t ptcopen;
70static d_close_t ptcclose;
71static d_read_t ptcread;
72static d_write_t ptcwrite;
73static d_poll_t ptcpoll;
74
75#define CDEV_MAJOR_S 5
76static struct cdevsw pts_cdevsw = {
77 /* open */ ptsopen,
78 /* close */ ptsclose,
79 /* read */ ptsread,
80 /* write */ ptswrite,
81 /* ioctl */ ptyioctl,
82 /* poll */ ttypoll,
83 /* mmap */ nommap,
84 /* strategy */ nostrategy,
85 /* name */ "pts",
86 /* maj */ CDEV_MAJOR_S,
87 /* dump */ nodump,
88 /* psize */ nopsize,
89 /* flags */ D_TTY,
90 /* bmaj */ -1
91};
92
93#define CDEV_MAJOR_C 6
94static struct cdevsw ptc_cdevsw = {
95 /* open */ ptcopen,
96 /* close */ ptcclose,
97 /* read */ ptcread,
98 /* write */ ptcwrite,
99 /* ioctl */ ptyioctl,
100 /* poll */ ptcpoll,
101 /* mmap */ nommap,
102 /* strategy */ nostrategy,
103 /* name */ "ptc",
104 /* maj */ CDEV_MAJOR_C,
105 /* dump */ nodump,
106 /* psize */ nopsize,
107 /* flags */ D_TTY,
108 /* bmaj */ -1
109};
110
111#define BUFSIZ 100 /* Chunk size iomoved to/from user */
112
113struct pt_ioctl {
114 int pt_flags;
115 struct selinfo pt_selr, pt_selw;
116 u_char pt_send;
117 u_char pt_ucntl;
118 struct tty pt_tty;
119 dev_t devs, devc;
120 struct prison *pt_prison;
121};
122
123#define PF_PKT 0x08 /* packet mode */
124#define PF_STOPPED 0x10 /* user told stopped */
125#define PF_REMOTE 0x20 /* remote and flow controlled input */
126#define PF_NOSTOP 0x40
127#define PF_UCNTL 0x80 /* user control mode */
128
129/*
130 * This function creates and initializes a pts/ptc pair
131 *
132 * pts == /dev/tty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv]
133 * ptc == /dev/pty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv]
134 *
135 * XXX: define and add mapping of upper minor bits to allow more
136 * than 256 ptys.
137 */
138static dev_t
139ptyinit(n)
140 int n;
141{
142 dev_t devs, devc;
143 char *names = "pqrsPQRS";
144 struct pt_ioctl *pt;
145
146 /* For now we only map the lower 8 bits of the minor */
147 if (n & ~0xff)
148 return (NODEV);
149
150 pt = malloc(sizeof(*pt), M_PTY, M_WAITOK);
151 bzero(pt, sizeof(*pt));
152 pt->devs = devs = make_dev(&pts_cdevsw, n,
153 UID_ROOT, GID_WHEEL, 0666, "tty%c%r", names[n / 32], n % 32);
154 pt->devc = devc = make_dev(&ptc_cdevsw, n,
155 UID_ROOT, GID_WHEEL, 0666, "pty%c%r", names[n / 32], n % 32);
156
157 devs->si_drv1 = devc->si_drv1 = pt;
158 devs->si_tty = devc->si_tty = &pt->pt_tty;
159 ttyregister(&pt->pt_tty);
160 return (devc);
161}
162
163/*ARGSUSED*/
164static int
165ptsopen(dev, flag, devtype, p)
166 dev_t dev;
167 int flag, devtype;
168 struct proc *p;
169{
170 register struct tty *tp;
171 int error;
172 struct pt_ioctl *pti;
173
174 if (!dev->si_drv1)
175 ptyinit(minor(dev));
176 if (!dev->si_drv1)
177 return(ENXIO);
178 pti = dev->si_drv1;
179 tp = dev->si_tty;
180 if ((tp->t_state & TS_ISOPEN) == 0) {
181 ttychars(tp); /* Set up default chars */
182 tp->t_iflag = TTYDEF_IFLAG;
183 tp->t_oflag = TTYDEF_OFLAG;
184 tp->t_lflag = TTYDEF_LFLAG;
185 tp->t_cflag = TTYDEF_CFLAG;
186 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
187 } else if (tp->t_state & TS_XCLUDE && suser(p)) {
188 return (EBUSY);
189 } else if (pti->pt_prison != p->p_prison) {
190 return (EBUSY);
191 }
192 if (tp->t_oproc) /* Ctrlr still around. */
193 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
194 while ((tp->t_state & TS_CARR_ON) == 0) {
195 if (flag&FNONBLOCK)
196 break;
197 error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH,
198 "ptsopn", 0);
199 if (error)
200 return (error);
201 }
202 error = (*linesw[tp->t_line].l_open)(dev, tp);
203 if (error == 0)
204 ptcwakeup(tp, FREAD|FWRITE);
205 return (error);
206}
207
208static int
209ptsclose(dev, flag, mode, p)
210 dev_t dev;
211 int flag, mode;
212 struct proc *p;
213{
214 register struct tty *tp;
215 int err;
216
217 tp = dev->si_tty;
218 err = (*linesw[tp->t_line].l_close)(tp, flag);
219 ptsstop(tp, FREAD|FWRITE);
220 (void) ttyclose(tp);
221 return (err);
222}
223
224static int
225ptsread(dev, uio, flag)
226 dev_t dev;
227 struct uio *uio;
228 int flag;
229{
230 struct proc *p = curproc;
231 register struct tty *tp = dev->si_tty;
232 register struct pt_ioctl *pti = dev->si_drv1;
233 int error = 0;
234
235again:
236 if (pti->pt_flags & PF_REMOTE) {
237 while (isbackground(p, tp)) {
238 if (SIGISMEMBER(p->p_sigignore, SIGTTIN) ||
239 SIGISMEMBER(p->p_sigmask, SIGTTIN) ||
240 p->p_pgrp->pg_jobc == 0 || p->p_flag & P_PPWAIT)
241 return (EIO);
242 pgsignal(p->p_pgrp, SIGTTIN, 1);
243 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ptsbg",
244 0);
245 if (error)
246 return (error);
247 }
248 if (tp->t_canq.c_cc == 0) {
249 if (flag & IO_NDELAY)
250 return (EWOULDBLOCK);
251 error = ttysleep(tp, TSA_PTS_READ(tp), TTIPRI | PCATCH,
252 "ptsin", 0);
253 if (error)
254 return (error);
255 goto again;
256 }
257 while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0)
258 if (ureadc(getc(&tp->t_canq), uio) < 0) {
259 error = EFAULT;
260 break;
261 }
262 if (tp->t_canq.c_cc == 1)
263 (void) getc(&tp->t_canq);
264 if (tp->t_canq.c_cc)
265 return (error);
266 } else
267 if (tp->t_oproc)
268 error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
269 ptcwakeup(tp, FWRITE);
270 return (error);
271}
272
273/*
274 * Write to pseudo-tty.
275 * Wakeups of controlling tty will happen
276 * indirectly, when tty driver calls ptsstart.
277 */
278static int
279ptswrite(dev, uio, flag)
280 dev_t dev;
281 struct uio *uio;
282 int flag;
283{
284 register struct tty *tp;
285
286 tp = dev->si_tty;
287 if (tp->t_oproc == 0)
288 return (EIO);
289 return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
290}
291
292/*
293 * Start output on pseudo-tty.
294 * Wake up process selecting or sleeping for input from controlling tty.
295 */
296static void
297ptsstart(tp)
298 struct tty *tp;
299{
300 register struct pt_ioctl *pti = tp->t_dev->si_drv1;
301
302 if (tp->t_state & TS_TTSTOP)
303 return;
304 if (pti->pt_flags & PF_STOPPED) {
305 pti->pt_flags &= ~PF_STOPPED;
306 pti->pt_send = TIOCPKT_START;
307 }
308 ptcwakeup(tp, FREAD);
309}
310
311static void
312ptcwakeup(tp, flag)
313 struct tty *tp;
314 int flag;
315{
316 struct pt_ioctl *pti = tp->t_dev->si_drv1;
317
318 if (flag & FREAD) {
319 selwakeup(&pti->pt_selr);
320 wakeup(TSA_PTC_READ(tp));
321 }
322 if (flag & FWRITE) {
323 selwakeup(&pti->pt_selw);
324 wakeup(TSA_PTC_WRITE(tp));
325 }
326}
327
328static int
329ptcopen(dev, flag, devtype, p)
330 dev_t dev;
331 int flag, devtype;
332 struct proc *p;
333{
334 register struct tty *tp;
335 struct pt_ioctl *pti;
336
337 if (!dev->si_drv1)
338 ptyinit(minor(dev));
339 if (!dev->si_drv1)
340 return(ENXIO);
341 tp = dev->si_tty;
342 if (tp->t_oproc)
343 return (EIO);
344 tp->t_timeout = -1;
345 tp->t_oproc = ptsstart;
346 tp->t_stop = ptsstop;
347 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
348 tp->t_lflag &= ~EXTPROC;
349 pti = dev->si_drv1;
350 pti->pt_prison = p->p_prison;
351 pti->pt_flags = 0;
352 pti->pt_send = 0;
353 pti->pt_ucntl = 0;
354 return (0);
355}
356
357static int
358ptcclose(dev, flags, fmt, p)
359 dev_t dev;
360 int flags;
361 int fmt;
362 struct proc *p;
363{
364 register struct tty *tp;
365
366 tp = dev->si_tty;
367 (void)(*linesw[tp->t_line].l_modem)(tp, 0);
368
369 /*
370 * XXX MDMBUF makes no sense for ptys but would inhibit the above
371 * l_modem(). CLOCAL makes sense but isn't supported. Special
372 * l_modem()s that ignore carrier drop make no sense for ptys but
373 * may be in use because other parts of the line discipline make
374 * sense for ptys. Recover by doing everything that a normal
375 * ttymodem() would have done except for sending a SIGHUP.
376 */
377 if (tp->t_state & TS_ISOPEN) {
378 tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED);
379 tp->t_state |= TS_ZOMBIE;
380 ttyflush(tp, FREAD | FWRITE);
381 }
382
383 tp->t_oproc = 0; /* mark closed */
384 return (0);
385}
386
387static int
388ptcread(dev, uio, flag)
389 dev_t dev;
390 struct uio *uio;
391 int flag;
392{
393 register struct tty *tp = dev->si_tty;
394 struct pt_ioctl *pti = dev->si_drv1;
395 char buf[BUFSIZ];
396 int error = 0, cc;
397
398 /*
399 * We want to block until the slave
400 * is open, and there's something to read;
401 * but if we lost the slave or we're NBIO,
402 * then return the appropriate error instead.
403 */
404 for (;;) {
405 if (tp->t_state&TS_ISOPEN) {
406 if (pti->pt_flags&PF_PKT && pti->pt_send) {
407 error = ureadc((int)pti->pt_send, uio);
408 if (error)
409 return (error);
410 if (pti->pt_send & TIOCPKT_IOCTL) {
411 cc = min(uio->uio_resid,
412 sizeof(tp->t_termios));
413 uiomove((caddr_t)&tp->t_termios, cc,
414 uio);
415 }
416 pti->pt_send = 0;
417 return (0);
418 }
419 if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) {
420 error = ureadc((int)pti->pt_ucntl, uio);
421 if (error)
422 return (error);
423 pti->pt_ucntl = 0;
424 return (0);
425 }
426 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
427 break;
428 }
429 if ((tp->t_state & TS_CONNECTED) == 0)
430 return (0); /* EOF */
431 if (flag & IO_NDELAY)
432 return (EWOULDBLOCK);
433 error = tsleep(TSA_PTC_READ(tp), TTIPRI | PCATCH, "ptcin", 0);
434 if (error)
435 return (error);
436 }
437 if (pti->pt_flags & (PF_PKT|PF_UCNTL))
438 error = ureadc(0, uio);
439 while (uio->uio_resid > 0 && error == 0) {
440 cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ));
441 if (cc <= 0)
442 break;
443 error = uiomove(buf, cc, uio);
444 }
445 ttwwakeup(tp);
446 return (error);
447}
448
449static void
450ptsstop(tp, flush)
451 register struct tty *tp;
452 int flush;
453{
454 struct pt_ioctl *pti = tp->t_dev->si_drv1;
455 int flag;
456
457 /* note: FLUSHREAD and FLUSHWRITE already ok */
458 if (flush == 0) {
459 flush = TIOCPKT_STOP;
460 pti->pt_flags |= PF_STOPPED;
461 } else
462 pti->pt_flags &= ~PF_STOPPED;
463 pti->pt_send |= flush;
464 /* change of perspective */
465 flag = 0;
466 if (flush & FREAD)
467 flag |= FWRITE;
468 if (flush & FWRITE)
469 flag |= FREAD;
470 ptcwakeup(tp, flag);
471}
472
473static int
474ptcpoll(dev, events, p)
475 dev_t dev;
476 int events;
477 struct proc *p;
478{
479 register struct tty *tp = dev->si_tty;
480 struct pt_ioctl *pti = dev->si_drv1;
481 int revents = 0;
482 int s;
483
484 if ((tp->t_state & TS_CONNECTED) == 0)
485 return (seltrue(dev, events, p) | POLLHUP);
486
487 /*
488 * Need to block timeouts (ttrstart).
489 */
490 s = spltty();
491
492 if (events & (POLLIN | POLLRDNORM))
493 if ((tp->t_state & TS_ISOPEN) &&
494 ((tp->t_outq.c_cc && (tp->t_state & TS_TTSTOP) == 0) ||
495 ((pti->pt_flags & PF_PKT) && pti->pt_send) ||
496 ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl)))
497 revents |= events & (POLLIN | POLLRDNORM);
498
499 if (events & (POLLOUT | POLLWRNORM))
500 if (tp->t_state & TS_ISOPEN &&
501 ((pti->pt_flags & PF_REMOTE) ?
502 (tp->t_canq.c_cc == 0) :
503 ((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG - 2) ||
504 (tp->t_canq.c_cc == 0 && (tp->t_iflag & ICANON)))))
505 revents |= events & (POLLOUT | POLLWRNORM);
506
507 if (events & POLLHUP)
508 if ((tp->t_state & TS_CARR_ON) == 0)
509 revents |= POLLHUP;
510
511 if (revents == 0) {
512 if (events & (POLLIN | POLLRDNORM))
513 selrecord(p, &pti->pt_selr);
514
515 if (events & (POLLOUT | POLLWRNORM))
516 selrecord(p, &pti->pt_selw);
517 }
518 splx(s);
519
520 return (revents);
521}
522
523static int
524ptcwrite(dev, uio, flag)
525 dev_t dev;
526 register struct uio *uio;
527 int flag;
528{
529 register struct tty *tp = dev->si_tty;
530 register u_char *cp = 0;
531 register int cc = 0;
532 u_char locbuf[BUFSIZ];
533 int cnt = 0;
534 struct pt_ioctl *pti = dev->si_drv1;
535 int error = 0;
536
537again:
538 if ((tp->t_state&TS_ISOPEN) == 0)
539 goto block;
540 if (pti->pt_flags & PF_REMOTE) {
541 if (tp->t_canq.c_cc)
542 goto block;
543 while ((uio->uio_resid > 0 || cc > 0) &&
544 tp->t_canq.c_cc < TTYHOG - 1) {
545 if (cc == 0) {
546 cc = min(uio->uio_resid, BUFSIZ);
547 cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc);
548 cp = locbuf;
549 error = uiomove((caddr_t)cp, cc, uio);
550 if (error)
551 return (error);
552 /* check again for safety */
553 if ((tp->t_state & TS_ISOPEN) == 0) {
554 /* adjust as usual */
555 uio->uio_resid += cc;
556 return (EIO);
557 }
558 }
559 if (cc > 0) {
560 cc = b_to_q((char *)cp, cc, &tp->t_canq);
561 /*
562 * XXX we don't guarantee that the canq size
563 * is >= TTYHOG, so the above b_to_q() may
564 * leave some bytes uncopied. However, space
565 * is guaranteed for the null terminator if
566 * we don't fail here since (TTYHOG - 1) is
567 * not a multiple of CBSIZE.
568 */
569 if (cc > 0)
570 break;
571 }
572 }
573 /* adjust for data copied in but not written */
574 uio->uio_resid += cc;
575 (void) putc(0, &tp->t_canq);
576 ttwakeup(tp);
577 wakeup(TSA_PTS_READ(tp));
578 return (0);
579 }
580 while (uio->uio_resid > 0 || cc > 0) {
581 if (cc == 0) {
582 cc = min(uio->uio_resid, BUFSIZ);
583 cp = locbuf;
584 error = uiomove((caddr_t)cp, cc, uio);
585 if (error)
586 return (error);
587 /* check again for safety */
588 if ((tp->t_state & TS_ISOPEN) == 0) {
589 /* adjust for data copied in but not written */
590 uio->uio_resid += cc;
591 return (EIO);
592 }
593 }
594 while (cc > 0) {
595 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
596 (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) {
597 wakeup(TSA_HUP_OR_INPUT(tp));
598 goto block;
599 }
600 (*linesw[tp->t_line].l_rint)(*cp++, tp);
601 cnt++;
602 cc--;
603 }
604 cc = 0;
605 }
606 return (0);
607block:
608 /*
609 * Come here to wait for slave to open, for space
610 * in outq, or space in rawq, or an empty canq.
611 */
612 if ((tp->t_state & TS_CONNECTED) == 0) {
613 /* adjust for data copied in but not written */
614 uio->uio_resid += cc;
615 return (EIO);
616 }
617 if (flag & IO_NDELAY) {
618 /* adjust for data copied in but not written */
619 uio->uio_resid += cc;
620 if (cnt == 0)
621 return (EWOULDBLOCK);
622 return (0);
623 }
624 error = tsleep(TSA_PTC_WRITE(tp), TTOPRI | PCATCH, "ptcout", 0);
625 if (error) {
626 /* adjust for data copied in but not written */
627 uio->uio_resid += cc;
628 return (error);
629 }
630 goto again;
631}
632
633/*ARGSUSED*/
634static int
635ptyioctl(dev, cmd, data, flag, p)
636 dev_t dev;
637 u_long cmd;
638 caddr_t data;
639 int flag;
640 struct proc *p;
641{
642 register struct tty *tp = dev->si_tty;
643 register struct pt_ioctl *pti = dev->si_drv1;
644 register u_char *cc = tp->t_cc;
645 int stop, error;
646
647 if (devsw(dev)->d_open == ptcopen) {
648 switch (cmd) {
649
650 case TIOCGPGRP:
651 /*
652 * We avoid calling ttioctl on the controller since,
653 * in that case, tp must be the controlling terminal.
654 */
655 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
656 return (0);
657
658 case TIOCPKT:
659 if (*(int *)data) {
660 if (pti->pt_flags & PF_UCNTL)
661 return (EINVAL);
662 pti->pt_flags |= PF_PKT;
663 } else
664 pti->pt_flags &= ~PF_PKT;
665 return (0);
666
667 case TIOCUCNTL:
668 if (*(int *)data) {
669 if (pti->pt_flags & PF_PKT)
670 return (EINVAL);
671 pti->pt_flags |= PF_UCNTL;
672 } else
673 pti->pt_flags &= ~PF_UCNTL;
674 return (0);
675
676 case TIOCREMOTE:
677 if (*(int *)data)
678 pti->pt_flags |= PF_REMOTE;
679 else
680 pti->pt_flags &= ~PF_REMOTE;
681 ttyflush(tp, FREAD|FWRITE);
682 return (0);
683 }
684
685 /*
686 * The rest of the ioctls shouldn't be called until
687 * the slave is open.
688 */
689 if ((tp->t_state & TS_ISOPEN) == 0)
690 return (EAGAIN);
691
692 switch (cmd) {
693#ifdef COMPAT_43
694 case TIOCSETP:
695 case TIOCSETN:
696#endif
697 case TIOCSETD:
698 case TIOCSETA:
699 case TIOCSETAW:
700 case TIOCSETAF:
701 /*
702 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
703 * ttywflush(tp) will hang if there are characters in
704 * the outq.
705 */
706 ndflush(&tp->t_outq, tp->t_outq.c_cc);
707 break;
708
709 case TIOCSIG:
710 if (*(unsigned int *)data >= NSIG ||
711 *(unsigned int *)data == 0)
712 return(EINVAL);
713 if ((tp->t_lflag&NOFLSH) == 0)
714 ttyflush(tp, FREAD|FWRITE);
715 pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
716 if ((*(unsigned int *)data == SIGINFO) &&
717 ((tp->t_lflag&NOKERNINFO) == 0))
718 ttyinfo(tp);
719 return(0);
720 }
721 }
722 if (cmd == TIOCEXT) {
723 /*
724 * When the EXTPROC bit is being toggled, we need
725 * to send an TIOCPKT_IOCTL if the packet driver
726 * is turned on.
727 */
728 if (*(int *)data) {
729 if (pti->pt_flags & PF_PKT) {
730 pti->pt_send |= TIOCPKT_IOCTL;
731 ptcwakeup(tp, FREAD);
732 }
733 tp->t_lflag |= EXTPROC;
734 } else {
735 if ((tp->t_lflag & EXTPROC) &&
736 (pti->pt_flags & PF_PKT)) {
737 pti->pt_send |= TIOCPKT_IOCTL;
738 ptcwakeup(tp, FREAD);
739 }
740 tp->t_lflag &= ~EXTPROC;
741 }
742 return(0);
743 }
744 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
745 if (error == ENOIOCTL)
746 error = ttioctl(tp, cmd, data, flag);
747 if (error == ENOIOCTL) {
748 if (pti->pt_flags & PF_UCNTL &&
749 (cmd & ~0xff) == UIOCCMD(0)) {
750 if (cmd & 0xff) {
751 pti->pt_ucntl = (u_char)cmd;
752 ptcwakeup(tp, FREAD);
753 }
754 return (0);
755 }
756 error = ENOTTY;
757 }
758 /*
759 * If external processing and packet mode send ioctl packet.
760 */
761 if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) {
762 switch(cmd) {
763 case TIOCSETA:
764 case TIOCSETAW:
765 case TIOCSETAF:
766#ifdef COMPAT_43
767 case TIOCSETP:
768 case TIOCSETN:
769#endif
770#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
771 case TIOCSETC:
772 case TIOCSLTC:
773 case TIOCLBIS:
774 case TIOCLBIC:
775 case TIOCLSET:
776#endif
777 pti->pt_send |= TIOCPKT_IOCTL;
778 ptcwakeup(tp, FREAD);
779 default:
780 break;
781 }
782 }
783 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
784 && CCEQ(cc[VSTART], CTRL('q'));
785 if (pti->pt_flags & PF_NOSTOP) {
786 if (stop) {
787 pti->pt_send &= ~TIOCPKT_NOSTOP;
788 pti->pt_send |= TIOCPKT_DOSTOP;
789 pti->pt_flags &= ~PF_NOSTOP;
790 ptcwakeup(tp, FREAD);
791 }
792 } else {
793 if (!stop) {
794 pti->pt_send &= ~TIOCPKT_DOSTOP;
795 pti->pt_send |= TIOCPKT_NOSTOP;
796 pti->pt_flags |= PF_NOSTOP;
797 ptcwakeup(tp, FREAD);
798 }
799 }
800 return (error);
801}
802
803
804static void ptc_drvinit __P((void *unused));
805
806static void pty_clone __P((void *arg, char *name, int namelen, dev_t *dev));
807
808static void
809pty_clone(arg, name, namelen, dev)
810 void *arg;
811 char *name;
812 int namelen;
813 dev_t *dev;
814{
815 int u;
816
817 if (*dev != NODEV)
818 return;
819 if (bcmp(name, "pty", 3) != 0)
820 return;
821 if (name[5] != '\0')
822 return;
823 switch (name[3]) {
824 case 'p': u = 0; break;
825 case 'q': u = 32; break;
826 case 'r': u = 64; break;
827 case 's': u = 96; break;
828 case 'P': u = 128; break;
829 case 'Q': u = 160; break;
830 case 'R': u = 192; break;
831 case 'S': u = 224; break;
832 default: return;
833 }
834 if (name[4] >= '0' && name[4] <= '9')
835 u += name[4] - '0';
836 else if (name[4] >= 'a' && name[4] <= 'v')
837 u += name[4] - 'a' + 10;
838 else
839 return;
840 *dev = ptyinit(u);
841 return;
842}
843
844static void
845ptc_drvinit(unused)
846 void *unused;
847{
848 EVENTHANDLER_REGISTER(dev_clone, pty_clone, 0, 1000);
849 cdevsw_add(&pts_cdevsw);
850 cdevsw_add(&ptc_cdevsw);
851}
852
853SYSINIT(ptcdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR_C,ptc_drvinit,NULL)