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
--- 16 unchanged lines hidden (view full) ---
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * @(#)tty_pty.c 8.4 (Berkeley) 2/20/95
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD: head/sys/kern/tty_pty.c 130262 2004-06-09 10:16:14Z phk $");
34
35/*
36 * Pseudo-teletype Driver
37 * (Actually two drivers, requiring two entries in 'cdevsw')
38 */
39#include "opt_compat.h"
40#include "opt_tty.h"
41#include <sys/param.h>
--- 56 unchanged lines hidden (view full) ---
98 .d_poll = ptcpoll,
99 .d_name = "ptc",
100 .d_maj = CDEV_MAJOR_C,
101 .d_flags = D_TTY | D_NEEDGIANT,
102};
103
104#define BUFSIZ 100 /* Chunk size iomoved to/from user */
105
106struct pt_ioctl {
107 int pt_flags;
108 struct selinfo pt_selr, pt_selw;
109 u_char pt_send;
110 u_char pt_ucntl;
111 struct tty *pt_tty;
112 dev_t devs, devc;
113 struct prison *pt_prison;
114};
--- 17 unchanged lines hidden (view full) ---
132 *
133 * XXX: define and add mapping of upper minor bits to allow more
134 * than 256 ptys.
135 */
136static dev_t
137ptyinit(dev_t devc)
138{
139 dev_t devs;
140 struct pt_ioctl *pt;
141 int n;
142
143 n = minor(devc);
144 /* For now we only map the lower 8 bits of the minor */
145 if (n & ~0xff)
146 return (NODEV);
147
148 devc->si_flags &= ~SI_CHEAPCLONE;
--- 11 unchanged lines hidden (view full) ---
160}
161
162/*ARGSUSED*/
163static int
164ptsopen(dev_t dev, int flag, int devtype, struct thread *td)
165{
166 struct tty *tp;
167 int error;
168 struct pt_ioctl *pti;
169
170 if (!dev->si_drv1)
171 return(ENXIO);
172 pti = dev->si_drv1;
173 tp = dev->si_tty;
174 if ((tp->t_state & TS_ISOPEN) == 0) {
175 ttychars(tp); /* Set up default chars */
176 tp->t_iflag = TTYDEF_IFLAG;
177 tp->t_oflag = TTYDEF_OFLAG;
178 tp->t_lflag = TTYDEF_LFLAG;
179 tp->t_cflag = TTYDEF_CFLAG;
180 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
181 } else if (tp->t_state & TS_XCLUDE && suser(td))
182 return (EBUSY);
183 else if (pti->pt_prison != td->td_ucred->cr_prison)
184 return (EBUSY);
185 if (tp->t_oproc) /* Ctrlr still around. */
186 (void)ttyld_modem(tp, 1);
187 while ((tp->t_state & TS_CARR_ON) == 0) {
188 if (flag&FNONBLOCK)
189 break;
190 error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH,
191 "ptsopn", 0);
--- 19 unchanged lines hidden (view full) ---
211}
212
213static int
214ptsread(dev_t dev, struct uio *uio, int flag)
215{
216 struct thread *td = curthread;
217 struct proc *p = td->td_proc;
218 struct tty *tp = dev->si_tty;
219 struct pt_ioctl *pti = dev->si_drv1;
220 struct pgrp *pg;
221 int error = 0;
222
223again:
224 if (pti->pt_flags & PF_REMOTE) {
225 while (isbackground(p, tp)) {
226 sx_slock(&proctree_lock);
227 PROC_LOCK(p);
228 if (SIGISMEMBER(p->p_sigacts->ps_sigignore, SIGTTIN) ||
229 SIGISMEMBER(td->td_sigmask, SIGTTIN) ||
230 p->p_pgrp->pg_jobc == 0 || p->p_flag & P_PPWAIT) {
231 PROC_UNLOCK(p);
232 sx_sunlock(&proctree_lock);
--- 53 unchanged lines hidden (view full) ---
286
287/*
288 * Start output on pseudo-tty.
289 * Wake up process selecting or sleeping for input from controlling tty.
290 */
291static void
292ptsstart(struct tty *tp)
293{
294 struct pt_ioctl *pti = tp->t_dev->si_drv1;
295
296 if (tp->t_state & TS_TTSTOP)
297 return;
298 if (pti->pt_flags & PF_STOPPED) {
299 pti->pt_flags &= ~PF_STOPPED;
300 pti->pt_send = TIOCPKT_START;
301 }
302 ptcwakeup(tp, FREAD);
303}
304
305static void
306ptcwakeup(struct tty *tp, int flag)
307{
308 struct pt_ioctl *pti = tp->t_dev->si_drv1;
309
310 if (flag & FREAD) {
311 selwakeuppri(&pti->pt_selr, TTIPRI);
312 wakeup(TSA_PTC_READ(tp));
313 }
314 if (flag & FWRITE) {
315 selwakeuppri(&pti->pt_selw, TTOPRI);
316 wakeup(TSA_PTC_WRITE(tp));
317 }
318}
319
320static int
321ptcopen(dev_t dev, int flag, int devtype, struct thread *td)
322{
323 struct tty *tp;
324 struct pt_ioctl *pti;
325
326 if (!dev->si_drv1)
327 ptyinit(dev);
328 if (!dev->si_drv1)
329 return(ENXIO);
330 tp = dev->si_tty;
331 if (tp->t_oproc)
332 return (EIO);
333 tp->t_timeout = -1;
334 tp->t_oproc = ptsstart;
335 tp->t_stop = ptsstop;
336 (void)ttyld_modem(tp, 1);
337 tp->t_lflag &= ~EXTPROC;
338 pti = dev->si_drv1;
339 pti->pt_prison = td->td_ucred->cr_prison;
340 pti->pt_flags = 0;
341 pti->pt_send = 0;
342 pti->pt_ucntl = 0;
343 return (0);
344}
345
346static int
347ptcclose(dev_t dev, int flags, int fmt, struct thread *td)
348{
349 struct tty *tp;
350
--- 17 unchanged lines hidden (view full) ---
368 tp->t_oproc = 0; /* mark closed */
369 return (0);
370}
371
372static int
373ptcread(dev_t dev, struct uio *uio, int flag)
374{
375 struct tty *tp = dev->si_tty;
376 struct pt_ioctl *pti = dev->si_drv1;
377 char buf[BUFSIZ];
378 int error = 0, cc;
379
380 /*
381 * We want to block until the slave
382 * is open, and there's something to read;
383 * but if we lost the slave or we're NBIO,
384 * then return the appropriate error instead.
385 */
386 for (;;) {
387 if (tp->t_state&TS_ISOPEN) {
388 if (pti->pt_flags&PF_PKT && pti->pt_send) {
389 error = ureadc((int)pti->pt_send, uio);
390 if (error)
391 return (error);
392 if (pti->pt_send & TIOCPKT_IOCTL) {
393 cc = min(uio->uio_resid,
394 sizeof(tp->t_termios));
395 uiomove(&tp->t_termios, cc, uio);
396 }
397 pti->pt_send = 0;
398 return (0);
399 }
400 if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) {
401 error = ureadc((int)pti->pt_ucntl, uio);
402 if (error)
403 return (error);
404 pti->pt_ucntl = 0;
405 return (0);
406 }
407 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
408 break;
409 }
410 if ((tp->t_state & TS_CONNECTED) == 0)
411 return (0); /* EOF */
412 if (flag & IO_NDELAY)
413 return (EWOULDBLOCK);
414 error = tsleep(TSA_PTC_READ(tp), TTIPRI | PCATCH, "ptcin", 0);
415 if (error)
416 return (error);
417 }
418 if (pti->pt_flags & (PF_PKT|PF_UCNTL))
419 error = ureadc(0, uio);
420 while (uio->uio_resid > 0 && error == 0) {
421 cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ));
422 if (cc <= 0)
423 break;
424 error = uiomove(buf, cc, uio);
425 }
426 ttwwakeup(tp);
427 return (error);
428}
429
430static void
431ptsstop(struct tty *tp, int flush)
432{
433 struct pt_ioctl *pti = tp->t_dev->si_drv1;
434 int flag;
435
436 /* note: FLUSHREAD and FLUSHWRITE already ok */
437 if (flush == 0) {
438 flush = TIOCPKT_STOP;
439 pti->pt_flags |= PF_STOPPED;
440 } else
441 pti->pt_flags &= ~PF_STOPPED;
442 pti->pt_send |= flush;
443 /* change of perspective */
444 flag = 0;
445 if (flush & FREAD)
446 flag |= FWRITE;
447 if (flush & FWRITE)
448 flag |= FREAD;
449 ptcwakeup(tp, flag);
450}
451
452static int
453ptcpoll(dev_t dev, int events, struct thread *td)
454{
455 struct tty *tp = dev->si_tty;
456 struct pt_ioctl *pti = dev->si_drv1;
457 int revents = 0;
458 int s;
459
460 if ((tp->t_state & TS_CONNECTED) == 0)
461 return (events &
462 (POLLHUP | POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM));
463
464 /*
465 * Need to block timeouts (ttrstart).
466 */
467 s = spltty();
468
469 if (events & (POLLIN | POLLRDNORM))
470 if ((tp->t_state & TS_ISOPEN) &&
471 ((tp->t_outq.c_cc && (tp->t_state & TS_TTSTOP) == 0) ||
472 ((pti->pt_flags & PF_PKT) && pti->pt_send) ||
473 ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl)))
474 revents |= events & (POLLIN | POLLRDNORM);
475
476 if (events & (POLLOUT | POLLWRNORM))
477 if (tp->t_state & TS_ISOPEN &&
478 ((pti->pt_flags & PF_REMOTE) ?
479 (tp->t_canq.c_cc == 0) :
480 ((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG - 2) ||
481 (tp->t_canq.c_cc == 0 && (tp->t_lflag & ICANON)))))
482 revents |= events & (POLLOUT | POLLWRNORM);
483
484 if (events & POLLHUP)
485 if ((tp->t_state & TS_CARR_ON) == 0)
486 revents |= POLLHUP;
487
488 if (revents == 0) {
489 if (events & (POLLIN | POLLRDNORM))
490 selrecord(td, &pti->pt_selr);
491
492 if (events & (POLLOUT | POLLWRNORM))
493 selrecord(td, &pti->pt_selw);
494 }
495 splx(s);
496
497 return (revents);
498}
499
500static int
501ptcwrite(dev_t dev, struct uio *uio, int flag)
502{
503 struct tty *tp = dev->si_tty;
504 u_char *cp = 0;
505 int cc = 0;
506 u_char locbuf[BUFSIZ];
507 int cnt = 0;
508 struct pt_ioctl *pti = dev->si_drv1;
509 int error = 0;
510
511again:
512 if ((tp->t_state&TS_ISOPEN) == 0)
513 goto block;
514 if (pti->pt_flags & PF_REMOTE) {
515 if (tp->t_canq.c_cc)
516 goto block;
517 while ((uio->uio_resid > 0 || cc > 0) &&
518 tp->t_canq.c_cc < TTYHOG - 1) {
519 if (cc == 0) {
520 cc = min(uio->uio_resid, BUFSIZ);
521 cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc);
522 cp = locbuf;
--- 81 unchanged lines hidden (view full) ---
604 goto again;
605}
606
607/*ARGSUSED*/
608static int
609ptyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
610{
611 struct tty *tp = dev->si_tty;
612 struct pt_ioctl *pti = dev->si_drv1;
613 u_char *cc = tp->t_cc;
614 int stop, error;
615
616 if (devsw(dev)->d_open == ptcopen) {
617 switch (cmd) {
618
619 case TIOCGPGRP:
620 /*
621 * We avoid calling ttioctl on the controller since,
622 * in that case, tp must be the controlling terminal.
623 */
624 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
625 return (0);
626
627 case TIOCPKT:
628 if (*(int *)data) {
629 if (pti->pt_flags & PF_UCNTL)
630 return (EINVAL);
631 pti->pt_flags |= PF_PKT;
632 } else
633 pti->pt_flags &= ~PF_PKT;
634 return (0);
635
636 case TIOCUCNTL:
637 if (*(int *)data) {
638 if (pti->pt_flags & PF_PKT)
639 return (EINVAL);
640 pti->pt_flags |= PF_UCNTL;
641 } else
642 pti->pt_flags &= ~PF_UCNTL;
643 return (0);
644
645 case TIOCREMOTE:
646 if (*(int *)data)
647 pti->pt_flags |= PF_REMOTE;
648 else
649 pti->pt_flags &= ~PF_REMOTE;
650 ttyflush(tp, FREAD|FWRITE);
651 return (0);
652 }
653
654 /*
655 * The rest of the ioctls shouldn't be called until
656 * the slave is open.
657 */
--- 36 unchanged lines hidden (view full) ---
694 }
695 if (cmd == TIOCEXT) {
696 /*
697 * When the EXTPROC bit is being toggled, we need
698 * to send an TIOCPKT_IOCTL if the packet driver
699 * is turned on.
700 */
701 if (*(int *)data) {
702 if (pti->pt_flags & PF_PKT) {
703 pti->pt_send |= TIOCPKT_IOCTL;
704 ptcwakeup(tp, FREAD);
705 }
706 tp->t_lflag |= EXTPROC;
707 } else {
708 if ((tp->t_lflag & EXTPROC) &&
709 (pti->pt_flags & PF_PKT)) {
710 pti->pt_send |= TIOCPKT_IOCTL;
711 ptcwakeup(tp, FREAD);
712 }
713 tp->t_lflag &= ~EXTPROC;
714 }
715 return(0);
716 }
717 error = ttyioctl(dev, cmd, data, flag, td);
718 if (error == ENOTTY) {
719 if (pti->pt_flags & PF_UCNTL &&
720 (cmd & ~0xff) == UIOCCMD(0)) {
721 if (cmd & 0xff) {
722 pti->pt_ucntl = (u_char)cmd;
723 ptcwakeup(tp, FREAD);
724 }
725 return (0);
726 }
727 error = ENOTTY;
728 }
729 /*
730 * If external processing and packet mode send ioctl packet.
731 */
732 if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) {
733 switch(cmd) {
734 case TIOCSETA:
735 case TIOCSETAW:
736 case TIOCSETAF:
737#ifdef COMPAT_43
738 case TIOCSETP:
739 case TIOCSETN:
740#endif
741#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
742 case TIOCSETC:
743 case TIOCSLTC:
744 case TIOCLBIS:
745 case TIOCLBIC:
746 case TIOCLSET:
747#endif
748 pti->pt_send |= TIOCPKT_IOCTL;
749 ptcwakeup(tp, FREAD);
750 break;
751 default:
752 break;
753 }
754 }
755 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
756 && CCEQ(cc[VSTART], CTRL('q'));
757 if (pti->pt_flags & PF_NOSTOP) {
758 if (stop) {
759 pti->pt_send &= ~TIOCPKT_NOSTOP;
760 pti->pt_send |= TIOCPKT_DOSTOP;
761 pti->pt_flags &= ~PF_NOSTOP;
762 ptcwakeup(tp, FREAD);
763 }
764 } else {
765 if (!stop) {
766 pti->pt_send &= ~TIOCPKT_DOSTOP;
767 pti->pt_send |= TIOCPKT_NOSTOP;
768 pti->pt_flags |= PF_NOSTOP;
769 ptcwakeup(tp, FREAD);
770 }
771 }
772 return (error);
773}
774
775static void
776pty_clone(void *arg, char *name, int namelen, dev_t *dev)
--- 40 unchanged lines hidden ---
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
--- 16 unchanged lines hidden (view full) ---
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * @(#)tty_pty.c 8.4 (Berkeley) 2/20/95
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD: head/sys/kern/tty_pty.c 130262 2004-06-09 10:16:14Z phk $");
34
35/*
36 * Pseudo-teletype Driver
37 * (Actually two drivers, requiring two entries in 'cdevsw')
38 */
39#include "opt_compat.h"
40#include "opt_tty.h"
41#include <sys/param.h>
--- 56 unchanged lines hidden (view full) ---
98 .d_poll = ptcpoll,
99 .d_name = "ptc",
100 .d_maj = CDEV_MAJOR_C,
101 .d_flags = D_TTY | D_NEEDGIANT,
102};
103
104#define BUFSIZ 100 /* Chunk size iomoved to/from user */
105
106struct pt_ioctl {
107 int pt_flags;
108 struct selinfo pt_selr, pt_selw;
109 u_char pt_send;
110 u_char pt_ucntl;
111 struct tty *pt_tty;
112 dev_t devs, devc;
113 struct prison *pt_prison;
114};
--- 17 unchanged lines hidden (view full) ---
132 *
133 * XXX: define and add mapping of upper minor bits to allow more
134 * than 256 ptys.
135 */
136static dev_t
137ptyinit(dev_t devc)
138{
139 dev_t devs;
140 struct pt_ioctl *pt;
141 int n;
142
143 n = minor(devc);
144 /* For now we only map the lower 8 bits of the minor */
145 if (n & ~0xff)
146 return (NODEV);
147
148 devc->si_flags &= ~SI_CHEAPCLONE;
--- 11 unchanged lines hidden (view full) ---
160}
161
162/*ARGSUSED*/
163static int
164ptsopen(dev_t dev, int flag, int devtype, struct thread *td)
165{
166 struct tty *tp;
167 int error;
168 struct pt_ioctl *pti;
169
170 if (!dev->si_drv1)
171 return(ENXIO);
172 pti = dev->si_drv1;
173 tp = dev->si_tty;
174 if ((tp->t_state & TS_ISOPEN) == 0) {
175 ttychars(tp); /* Set up default chars */
176 tp->t_iflag = TTYDEF_IFLAG;
177 tp->t_oflag = TTYDEF_OFLAG;
178 tp->t_lflag = TTYDEF_LFLAG;
179 tp->t_cflag = TTYDEF_CFLAG;
180 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
181 } else if (tp->t_state & TS_XCLUDE && suser(td))
182 return (EBUSY);
183 else if (pti->pt_prison != td->td_ucred->cr_prison)
184 return (EBUSY);
185 if (tp->t_oproc) /* Ctrlr still around. */
186 (void)ttyld_modem(tp, 1);
187 while ((tp->t_state & TS_CARR_ON) == 0) {
188 if (flag&FNONBLOCK)
189 break;
190 error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH,
191 "ptsopn", 0);
--- 19 unchanged lines hidden (view full) ---
211}
212
213static int
214ptsread(dev_t dev, struct uio *uio, int flag)
215{
216 struct thread *td = curthread;
217 struct proc *p = td->td_proc;
218 struct tty *tp = dev->si_tty;
219 struct pt_ioctl *pti = dev->si_drv1;
220 struct pgrp *pg;
221 int error = 0;
222
223again:
224 if (pti->pt_flags & PF_REMOTE) {
225 while (isbackground(p, tp)) {
226 sx_slock(&proctree_lock);
227 PROC_LOCK(p);
228 if (SIGISMEMBER(p->p_sigacts->ps_sigignore, SIGTTIN) ||
229 SIGISMEMBER(td->td_sigmask, SIGTTIN) ||
230 p->p_pgrp->pg_jobc == 0 || p->p_flag & P_PPWAIT) {
231 PROC_UNLOCK(p);
232 sx_sunlock(&proctree_lock);
--- 53 unchanged lines hidden (view full) ---
286
287/*
288 * Start output on pseudo-tty.
289 * Wake up process selecting or sleeping for input from controlling tty.
290 */
291static void
292ptsstart(struct tty *tp)
293{
294 struct pt_ioctl *pti = tp->t_dev->si_drv1;
295
296 if (tp->t_state & TS_TTSTOP)
297 return;
298 if (pti->pt_flags & PF_STOPPED) {
299 pti->pt_flags &= ~PF_STOPPED;
300 pti->pt_send = TIOCPKT_START;
301 }
302 ptcwakeup(tp, FREAD);
303}
304
305static void
306ptcwakeup(struct tty *tp, int flag)
307{
308 struct pt_ioctl *pti = tp->t_dev->si_drv1;
309
310 if (flag & FREAD) {
311 selwakeuppri(&pti->pt_selr, TTIPRI);
312 wakeup(TSA_PTC_READ(tp));
313 }
314 if (flag & FWRITE) {
315 selwakeuppri(&pti->pt_selw, TTOPRI);
316 wakeup(TSA_PTC_WRITE(tp));
317 }
318}
319
320static int
321ptcopen(dev_t dev, int flag, int devtype, struct thread *td)
322{
323 struct tty *tp;
324 struct pt_ioctl *pti;
325
326 if (!dev->si_drv1)
327 ptyinit(dev);
328 if (!dev->si_drv1)
329 return(ENXIO);
330 tp = dev->si_tty;
331 if (tp->t_oproc)
332 return (EIO);
333 tp->t_timeout = -1;
334 tp->t_oproc = ptsstart;
335 tp->t_stop = ptsstop;
336 (void)ttyld_modem(tp, 1);
337 tp->t_lflag &= ~EXTPROC;
338 pti = dev->si_drv1;
339 pti->pt_prison = td->td_ucred->cr_prison;
340 pti->pt_flags = 0;
341 pti->pt_send = 0;
342 pti->pt_ucntl = 0;
343 return (0);
344}
345
346static int
347ptcclose(dev_t dev, int flags, int fmt, struct thread *td)
348{
349 struct tty *tp;
350
--- 17 unchanged lines hidden (view full) ---
368 tp->t_oproc = 0; /* mark closed */
369 return (0);
370}
371
372static int
373ptcread(dev_t dev, struct uio *uio, int flag)
374{
375 struct tty *tp = dev->si_tty;
376 struct pt_ioctl *pti = dev->si_drv1;
377 char buf[BUFSIZ];
378 int error = 0, cc;
379
380 /*
381 * We want to block until the slave
382 * is open, and there's something to read;
383 * but if we lost the slave or we're NBIO,
384 * then return the appropriate error instead.
385 */
386 for (;;) {
387 if (tp->t_state&TS_ISOPEN) {
388 if (pti->pt_flags&PF_PKT && pti->pt_send) {
389 error = ureadc((int)pti->pt_send, uio);
390 if (error)
391 return (error);
392 if (pti->pt_send & TIOCPKT_IOCTL) {
393 cc = min(uio->uio_resid,
394 sizeof(tp->t_termios));
395 uiomove(&tp->t_termios, cc, uio);
396 }
397 pti->pt_send = 0;
398 return (0);
399 }
400 if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) {
401 error = ureadc((int)pti->pt_ucntl, uio);
402 if (error)
403 return (error);
404 pti->pt_ucntl = 0;
405 return (0);
406 }
407 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
408 break;
409 }
410 if ((tp->t_state & TS_CONNECTED) == 0)
411 return (0); /* EOF */
412 if (flag & IO_NDELAY)
413 return (EWOULDBLOCK);
414 error = tsleep(TSA_PTC_READ(tp), TTIPRI | PCATCH, "ptcin", 0);
415 if (error)
416 return (error);
417 }
418 if (pti->pt_flags & (PF_PKT|PF_UCNTL))
419 error = ureadc(0, uio);
420 while (uio->uio_resid > 0 && error == 0) {
421 cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ));
422 if (cc <= 0)
423 break;
424 error = uiomove(buf, cc, uio);
425 }
426 ttwwakeup(tp);
427 return (error);
428}
429
430static void
431ptsstop(struct tty *tp, int flush)
432{
433 struct pt_ioctl *pti = tp->t_dev->si_drv1;
434 int flag;
435
436 /* note: FLUSHREAD and FLUSHWRITE already ok */
437 if (flush == 0) {
438 flush = TIOCPKT_STOP;
439 pti->pt_flags |= PF_STOPPED;
440 } else
441 pti->pt_flags &= ~PF_STOPPED;
442 pti->pt_send |= flush;
443 /* change of perspective */
444 flag = 0;
445 if (flush & FREAD)
446 flag |= FWRITE;
447 if (flush & FWRITE)
448 flag |= FREAD;
449 ptcwakeup(tp, flag);
450}
451
452static int
453ptcpoll(dev_t dev, int events, struct thread *td)
454{
455 struct tty *tp = dev->si_tty;
456 struct pt_ioctl *pti = dev->si_drv1;
457 int revents = 0;
458 int s;
459
460 if ((tp->t_state & TS_CONNECTED) == 0)
461 return (events &
462 (POLLHUP | POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM));
463
464 /*
465 * Need to block timeouts (ttrstart).
466 */
467 s = spltty();
468
469 if (events & (POLLIN | POLLRDNORM))
470 if ((tp->t_state & TS_ISOPEN) &&
471 ((tp->t_outq.c_cc && (tp->t_state & TS_TTSTOP) == 0) ||
472 ((pti->pt_flags & PF_PKT) && pti->pt_send) ||
473 ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl)))
474 revents |= events & (POLLIN | POLLRDNORM);
475
476 if (events & (POLLOUT | POLLWRNORM))
477 if (tp->t_state & TS_ISOPEN &&
478 ((pti->pt_flags & PF_REMOTE) ?
479 (tp->t_canq.c_cc == 0) :
480 ((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG - 2) ||
481 (tp->t_canq.c_cc == 0 && (tp->t_lflag & ICANON)))))
482 revents |= events & (POLLOUT | POLLWRNORM);
483
484 if (events & POLLHUP)
485 if ((tp->t_state & TS_CARR_ON) == 0)
486 revents |= POLLHUP;
487
488 if (revents == 0) {
489 if (events & (POLLIN | POLLRDNORM))
490 selrecord(td, &pti->pt_selr);
491
492 if (events & (POLLOUT | POLLWRNORM))
493 selrecord(td, &pti->pt_selw);
494 }
495 splx(s);
496
497 return (revents);
498}
499
500static int
501ptcwrite(dev_t dev, struct uio *uio, int flag)
502{
503 struct tty *tp = dev->si_tty;
504 u_char *cp = 0;
505 int cc = 0;
506 u_char locbuf[BUFSIZ];
507 int cnt = 0;
508 struct pt_ioctl *pti = dev->si_drv1;
509 int error = 0;
510
511again:
512 if ((tp->t_state&TS_ISOPEN) == 0)
513 goto block;
514 if (pti->pt_flags & PF_REMOTE) {
515 if (tp->t_canq.c_cc)
516 goto block;
517 while ((uio->uio_resid > 0 || cc > 0) &&
518 tp->t_canq.c_cc < TTYHOG - 1) {
519 if (cc == 0) {
520 cc = min(uio->uio_resid, BUFSIZ);
521 cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc);
522 cp = locbuf;
--- 81 unchanged lines hidden (view full) ---
604 goto again;
605}
606
607/*ARGSUSED*/
608static int
609ptyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
610{
611 struct tty *tp = dev->si_tty;
612 struct pt_ioctl *pti = dev->si_drv1;
613 u_char *cc = tp->t_cc;
614 int stop, error;
615
616 if (devsw(dev)->d_open == ptcopen) {
617 switch (cmd) {
618
619 case TIOCGPGRP:
620 /*
621 * We avoid calling ttioctl on the controller since,
622 * in that case, tp must be the controlling terminal.
623 */
624 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
625 return (0);
626
627 case TIOCPKT:
628 if (*(int *)data) {
629 if (pti->pt_flags & PF_UCNTL)
630 return (EINVAL);
631 pti->pt_flags |= PF_PKT;
632 } else
633 pti->pt_flags &= ~PF_PKT;
634 return (0);
635
636 case TIOCUCNTL:
637 if (*(int *)data) {
638 if (pti->pt_flags & PF_PKT)
639 return (EINVAL);
640 pti->pt_flags |= PF_UCNTL;
641 } else
642 pti->pt_flags &= ~PF_UCNTL;
643 return (0);
644
645 case TIOCREMOTE:
646 if (*(int *)data)
647 pti->pt_flags |= PF_REMOTE;
648 else
649 pti->pt_flags &= ~PF_REMOTE;
650 ttyflush(tp, FREAD|FWRITE);
651 return (0);
652 }
653
654 /*
655 * The rest of the ioctls shouldn't be called until
656 * the slave is open.
657 */
--- 36 unchanged lines hidden (view full) ---
694 }
695 if (cmd == TIOCEXT) {
696 /*
697 * When the EXTPROC bit is being toggled, we need
698 * to send an TIOCPKT_IOCTL if the packet driver
699 * is turned on.
700 */
701 if (*(int *)data) {
702 if (pti->pt_flags & PF_PKT) {
703 pti->pt_send |= TIOCPKT_IOCTL;
704 ptcwakeup(tp, FREAD);
705 }
706 tp->t_lflag |= EXTPROC;
707 } else {
708 if ((tp->t_lflag & EXTPROC) &&
709 (pti->pt_flags & PF_PKT)) {
710 pti->pt_send |= TIOCPKT_IOCTL;
711 ptcwakeup(tp, FREAD);
712 }
713 tp->t_lflag &= ~EXTPROC;
714 }
715 return(0);
716 }
717 error = ttyioctl(dev, cmd, data, flag, td);
718 if (error == ENOTTY) {
719 if (pti->pt_flags & PF_UCNTL &&
720 (cmd & ~0xff) == UIOCCMD(0)) {
721 if (cmd & 0xff) {
722 pti->pt_ucntl = (u_char)cmd;
723 ptcwakeup(tp, FREAD);
724 }
725 return (0);
726 }
727 error = ENOTTY;
728 }
729 /*
730 * If external processing and packet mode send ioctl packet.
731 */
732 if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) {
733 switch(cmd) {
734 case TIOCSETA:
735 case TIOCSETAW:
736 case TIOCSETAF:
737#ifdef COMPAT_43
738 case TIOCSETP:
739 case TIOCSETN:
740#endif
741#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
742 case TIOCSETC:
743 case TIOCSLTC:
744 case TIOCLBIS:
745 case TIOCLBIC:
746 case TIOCLSET:
747#endif
748 pti->pt_send |= TIOCPKT_IOCTL;
749 ptcwakeup(tp, FREAD);
750 break;
751 default:
752 break;
753 }
754 }
755 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
756 && CCEQ(cc[VSTART], CTRL('q'));
757 if (pti->pt_flags & PF_NOSTOP) {
758 if (stop) {
759 pti->pt_send &= ~TIOCPKT_NOSTOP;
760 pti->pt_send |= TIOCPKT_DOSTOP;
761 pti->pt_flags &= ~PF_NOSTOP;
762 ptcwakeup(tp, FREAD);
763 }
764 } else {
765 if (!stop) {
766 pti->pt_send &= ~TIOCPKT_DOSTOP;
767 pti->pt_send |= TIOCPKT_NOSTOP;
768 pti->pt_flags |= PF_NOSTOP;
769 ptcwakeup(tp, FREAD);
770 }
771 }
772 return (error);
773}
774
775static void
776pty_clone(void *arg, char *name, int namelen, dev_t *dev)
--- 40 unchanged lines hidden ---