Lines Matching +full:master +full:- +full:side

1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
71 * Our utmp(5) format is limited to 8-byte TTY line names. This means
72 * we can at most allocate 1000 pseudo-terminals ("pts/999"). Allow
81 * Per-PTS structure.
94 struct cv pts_inwait; /* (t) Blocking write() on master. */
96 struct cv pts_outwait; /* (t) Blocking read() on master. */
100 struct cdev *pts_cdev; /* (c) Master device node. */
107 * Controller-side file operations.
114 struct tty *tp = fp->f_data; in ptsdev_read()
119 if (uio->uio_resid == 0) in ptsdev_read()
130 if (psc->pts_flags & PTS_PKT && psc->pts_pkt) { in ptsdev_read()
131 pkt = psc->pts_pkt; in ptsdev_read()
132 psc->pts_pkt = 0; in ptsdev_read()
148 if (psc->pts_flags & PTS_PKT) { in ptsdev_read()
166 if (psc->pts_flags & PTS_FINISHED) in ptsdev_read()
170 if (fp->f_flag & O_NONBLOCK) { in ptsdev_read()
174 error = cv_wait_sig(&psc->pts_outwait, tp->t_mtx); in ptsdev_read()
188 struct tty *tp = fp->f_data; in ptsdev_write()
194 if (uio->uio_resid == 0) in ptsdev_write()
199 iblen = MIN(uio->uio_resid, sizeof ib); in ptsdev_write()
216 iblen -= rintlen; in ptsdev_write()
223 if (psc->pts_flags & PTS_FINISHED) { in ptsdev_write()
229 if (fp->f_flag & O_NONBLOCK) { in ptsdev_write()
234 /* Wake up users on the slave side. */ in ptsdev_write()
236 error = cv_wait_sig(&psc->pts_inwait, tp->t_mtx); in ptsdev_write()
241 if (uio->uio_resid == 0) in ptsdev_write()
253 uio->uio_resid += iblen; in ptsdev_write()
261 struct tty *tp = fp->f_data; in ptsdev_ioctl()
270 /* This device supports non-blocking operation. */ in ptsdev_ioctl()
290 if (i > fgn->len) in ptsdev_ioctl()
297 * called on the pseudo-terminal master, it should not check if in ptsdev_ioctl()
308 *(struct termios*)data = tp->t_termios; in ptsdev_ioctl()
317 * call TCSAFLUSH or TCSADRAIN on the master descriptor, it may in ptsdev_ioctl()
327 if (psc->pts_unit < 0) in ptsdev_ioctl()
329 *(unsigned int *)data = psc->pts_unit; in ptsdev_ioctl()
335 if (tp->t_pgrp != NULL) in ptsdev_ioctl()
336 *(int *)data = tp->t_pgrp->pg_id; in ptsdev_ioctl()
344 if (tp->t_session == NULL) in ptsdev_ioctl()
347 *(int *)data = tp->t_session->s_sid; in ptsdev_ioctl()
351 /* Yes, we are a pseudo-terminal master. */ in ptsdev_ioctl()
367 psc->pts_flags |= PTS_PKT; in ptsdev_ioctl()
369 psc->pts_flags &= ~PTS_PKT; in ptsdev_ioctl()
376 error = tty_ioctl(tp, cmd, data, fp->f_flag, td); in ptsdev_ioctl()
388 struct tty *tp = fp->f_data; in ptsdev_poll()
394 if (psc->pts_flags & PTS_FINISHED) { in ptsdev_poll()
403 (psc->pts_flags & PTS_PKT && psc->pts_pkt)) in ptsdev_poll()
415 * because the master is. in ptsdev_poll()
421 * poll events on this side is the opposite of the slave in ptsdev_poll()
425 selrecord(td, &psc->pts_outpoll); in ptsdev_poll()
427 selrecord(td, &psc->pts_inpoll); in ptsdev_poll()
442 struct file *fp = kn->kn_fp; in pts_kqops_read_detach()
443 struct tty *tp = fp->f_data; in pts_kqops_read_detach()
446 knlist_remove(&psc->pts_outpoll.si_note, kn, 0); in pts_kqops_read_detach()
452 struct file *fp = kn->kn_fp; in pts_kqops_read_event()
453 struct tty *tp = fp->f_data; in pts_kqops_read_event()
456 if (psc->pts_flags & PTS_FINISHED) { in pts_kqops_read_event()
457 kn->kn_flags |= EV_EOF; in pts_kqops_read_event()
460 kn->kn_data = ttydisc_getc_poll(tp); in pts_kqops_read_event()
461 return (kn->kn_data > 0); in pts_kqops_read_event()
468 struct file *fp = kn->kn_fp; in pts_kqops_write_detach()
469 struct tty *tp = fp->f_data; in pts_kqops_write_detach()
472 knlist_remove(&psc->pts_inpoll.si_note, kn, 0); in pts_kqops_write_detach()
478 struct file *fp = kn->kn_fp; in pts_kqops_write_event()
479 struct tty *tp = fp->f_data; in pts_kqops_write_event()
482 if (psc->pts_flags & PTS_FINISHED) { in pts_kqops_write_event()
483 kn->kn_flags |= EV_EOF; in pts_kqops_write_event()
486 kn->kn_data = ttydisc_rint_poll(tp); in pts_kqops_write_event()
487 return (kn->kn_data > 0); in pts_kqops_write_event()
505 struct tty *tp = fp->f_data; in ptsdev_kqfilter()
511 switch (kn->kn_filter) { in ptsdev_kqfilter()
513 kn->kn_fop = &pts_kqops_read; in ptsdev_kqfilter()
514 knlist_add(&psc->pts_outpoll.si_note, kn, 1); in ptsdev_kqfilter()
517 kn->kn_fop = &pts_kqops_write; in ptsdev_kqfilter()
518 knlist_add(&psc->pts_inpoll.si_note, kn, 1); in ptsdev_kqfilter()
532 struct tty *tp = fp->f_data; in ptsdev_stat()
536 struct cdev *dev = tp->t_dev; in ptsdev_stat()
541 * because Linux calls fstat() on the pseudo-terminal master to in ptsdev_stat()
549 if (psc->pts_cdev != NULL) in ptsdev_stat()
550 sb->st_ino = sb->st_rdev = dev2udev(psc->pts_cdev); in ptsdev_stat()
553 sb->st_ino = sb->st_rdev = tty_udev(tp); in ptsdev_stat()
555 sb->st_atim = dev->si_atime; in ptsdev_stat()
556 sb->st_ctim = dev->si_ctime; in ptsdev_stat()
557 sb->st_mtim = dev->si_mtime; in ptsdev_stat()
558 sb->st_uid = dev->si_uid; in ptsdev_stat()
559 sb->st_gid = dev->si_gid; in ptsdev_stat()
560 sb->st_mode = dev->si_mode | S_IFCHR; in ptsdev_stat()
568 struct tty *tp = fp->f_data; in ptsdev_close()
580 if (fp->f_vnode != NULL) in ptsdev_close()
591 kif->kf_type = KF_TYPE_PTS; in ptsdev_fill_kinfo()
592 tp = fp->f_data; in ptsdev_fill_kinfo()
593 kif->kf_un.kf_pts.kf_pts_dev = tty_udev(tp); in ptsdev_fill_kinfo()
594 kif->kf_un.kf_pts.kf_pts_dev_freebsd11 = in ptsdev_fill_kinfo()
595 kif->kf_un.kf_pts.kf_pts_dev; /* truncate */ in ptsdev_fill_kinfo()
596 strlcpy(kif->kf_path, tty_devname(tp), sizeof(kif->kf_path)); in ptsdev_fill_kinfo()
618 * Driver-side hooks.
626 cv_broadcast(&psc->pts_outwait); in ptsdrv_outwakeup()
627 selwakeup(&psc->pts_outpoll); in ptsdrv_outwakeup()
628 KNOTE_LOCKED(&psc->pts_outpoll.si_note, 0); in ptsdrv_outwakeup()
636 cv_broadcast(&psc->pts_inwait); in ptsdrv_inwakeup()
637 selwakeup(&psc->pts_inpoll); in ptsdrv_inwakeup()
638 KNOTE_LOCKED(&psc->pts_inpoll.si_note, 0); in ptsdrv_inwakeup()
646 psc->pts_flags &= ~PTS_FINISHED; in ptsdrv_open()
657 psc->pts_flags |= PTS_FINISHED; in ptsdrv_close()
673 psc->pts_pkt &= ~TIOCPKT_START; in ptsdrv_pktnotify()
676 psc->pts_pkt &= ~TIOCPKT_STOP; in ptsdrv_pktnotify()
679 psc->pts_pkt &= ~TIOCPKT_DOSTOP; in ptsdrv_pktnotify()
682 psc->pts_pkt &= ~TIOCPKT_NOSTOP; in ptsdrv_pktnotify()
686 psc->pts_pkt |= event; in ptsdrv_pktnotify()
696 if (psc->pts_unit >= 0) in ptsdrv_free()
697 free_unr(pts_pool, psc->pts_unit); in ptsdrv_free()
699 chgptscnt(psc->pts_cred->cr_ruidinfo, -1, 0); in ptsdrv_free()
700 racct_sub_cred(psc->pts_cred, RACCT_NPTS, 1); in ptsdrv_free()
701 crfree(psc->pts_cred); in ptsdrv_free()
703 seldrain(&psc->pts_inpoll); in ptsdrv_free()
704 seldrain(&psc->pts_outpoll); in ptsdrv_free()
705 knlist_destroy(&psc->pts_inpoll.si_note); in ptsdrv_free()
706 knlist_destroy(&psc->pts_outpoll.si_note); in ptsdrv_free()
709 /* Destroy master device as well. */ in ptsdrv_free()
710 if (psc->pts_cdev != NULL) in ptsdrv_free()
711 destroy_dev_sched(psc->pts_cdev); in ptsdrv_free()
736 struct proc *p = td->td_proc; in pts_alloc()
737 struct ucred *cred = td->td_ucred; in pts_alloc()
746 ok = chgptscnt(cred->cr_ruidinfo, 1, lim_cur(td, RLIMIT_NPTS)); in pts_alloc()
758 chgptscnt(cred->cr_ruidinfo, -1, 0); in pts_alloc()
764 cv_init(&psc->pts_inwait, "ptsin"); in pts_alloc()
765 cv_init(&psc->pts_outwait, "ptsout"); in pts_alloc()
767 psc->pts_unit = unit; in pts_alloc()
768 psc->pts_cred = crhold(cred); in pts_alloc()
771 knlist_init_mtx(&psc->pts_inpoll.si_note, tp->t_mtx); in pts_alloc()
772 knlist_init_mtx(&psc->pts_outpoll.si_note, tp->t_mtx); in pts_alloc()
775 tty_makedev(tp, td->td_ucred, "pts/%u", psc->pts_unit); in pts_alloc()
790 struct proc *p = td->td_proc; in pts_alloc_external()
791 struct ucred *cred = td->td_ucred; in pts_alloc_external()
800 ok = chgptscnt(cred->cr_ruidinfo, 1, lim_cur(td, RLIMIT_NPTS)); in pts_alloc_external()
810 cv_init(&psc->pts_inwait, "ptsin"); in pts_alloc_external()
811 cv_init(&psc->pts_outwait, "ptsout"); in pts_alloc_external()
813 psc->pts_unit = -1; in pts_alloc_external()
814 psc->pts_cdev = dev; in pts_alloc_external()
815 psc->pts_cred = crhold(cred); in pts_alloc_external()
818 knlist_init_mtx(&psc->pts_inpoll.si_note, tp->t_mtx); in pts_alloc_external()
819 knlist_init_mtx(&psc->pts_outpoll.si_note, tp->t_mtx); in pts_alloc_external()
822 tty_makedev(tp, td->td_ucred, "%s", name); in pts_alloc_external()
840 if (uap->flags & ~(O_RDWR|O_NOCTTY|O_CLOEXEC)) in sys_posix_openpt()
843 error = falloc(td, &fp, &fd, uap->flags); in sys_posix_openpt()
847 /* Allocate the actual pseudo-TTY. */ in sys_posix_openpt()
848 error = pts_alloc(FFLAGS(uap->flags & O_ACCMODE), td, fp); in sys_posix_openpt()
856 td->td_retval[0] = fd; in sys_posix_openpt()