- (void) thread_funnel_set(kernel_flock, funnel_state);
- return (err);
-}
-
-FREE_BSDSTATIC int
-ptsread(dev, uio, flag)
- dev_t dev;
- struct uio *uio;
- int flag;
-{
-#ifndef NeXT
- struct proc *p = curproc;
-#else
- struct proc *p = current_proc();
-#endif /* NeXT */
- register struct tty *tp = pt_tty[minor(dev)];
- register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
- int error = 0;
- struct uthread *ut;
- boolean_t funnel_state;
-
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
-
-
- ut = (struct uthread *)get_bsdthread_info(current_thread());
-again:
- if (pti->pt_flags & PF_REMOTE) {
- while (isbackground(p, tp)) {
- if ((p->p_sigignore & sigmask(SIGTTIN)) ||
- (ut->uu_sigmask & sigmask(SIGTTIN)) ||
- p->p_pgrp->pg_jobc == 0 ||
- p->p_flag & P_PPWAIT) {
- error = EIO;
- goto out;
- }
- pgsignal(p->p_pgrp, SIGTTIN, 1);
- error = ttysleep(tp, &lbolt, TTIPRI | PCATCH | PTTYBLOCK, "ptsbg",
- 0);
- if (error)
- goto out;
- }
- if (tp->t_canq.c_cc == 0) {
- if (flag & IO_NDELAY)
- return (EWOULDBLOCK);
- error = ttysleep(tp, TSA_PTS_READ(tp), TTIPRI | PCATCH,
- "ptsin", 0);
- if (error)
- goto out;
- goto again;
- }
- while (tp->t_canq.c_cc > 1 && uio_resid(uio) > 0) {
- int cc;
- char buf[BUFSIZ];
-
- cc = min(uio_resid(uio), BUFSIZ);
- // Don't copy the very last byte
- cc = min(cc, tp->t_canq.c_cc - 1);
- cc = q_to_b(&tp->t_canq, buf, cc);
- error = uiomove(buf, cc, uio);
- if (error)
- break;
- }
- if (tp->t_canq.c_cc == 1)
- (void) getc(&tp->t_canq);
- if (tp->t_canq.c_cc)
- goto out;
- } else
- if (tp->t_oproc)
- error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
- ptcwakeup(tp, FWRITE);
-out:
- (void) thread_funnel_set(kernel_flock, funnel_state);
- return (error);
-}
-
-/*
- * Write to pseudo-tty.
- * Wakeups of controlling tty will happen
- * indirectly, when tty driver calls ptsstart.
- */
-FREE_BSDSTATIC int
-ptswrite(dev, uio, flag)
- dev_t dev;
- struct uio *uio;
- int flag;
-{
- register struct tty *tp;
- int error;
- boolean_t funnel_state;
-
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
-
- tp = pt_tty[minor(dev)];
- if (tp->t_oproc == 0)
- error = EIO;
- else
- error = (*linesw[tp->t_line].l_write)(tp, uio, flag);
-
- (void) thread_funnel_set(kernel_flock, funnel_state);
- return (error);
-}
-
-/*
- * Start output on pseudo-tty.
- * Wake up process selecting or sleeping for input from controlling tty.
- */
-static void
-ptsstart(tp)
- struct tty *tp;
-{
- register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
- boolean_t funnel_state;
-
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
-
- if (tp->t_state & TS_TTSTOP)
- goto out;
- if (pti->pt_flags & PF_STOPPED) {
- pti->pt_flags &= ~PF_STOPPED;
- pti->pt_send = TIOCPKT_START;
- }
- ptcwakeup(tp, FREAD);
-out:
- (void) thread_funnel_set(kernel_flock, funnel_state);
- return;
-}
-
-static void
-ptcwakeup(tp, flag)
- struct tty *tp;
- int flag;
-{
- struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
- boolean_t funnel_state;
-
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
-
- if (flag & FREAD) {
- selwakeup(&pti->pt_selr);
- wakeup(TSA_PTC_READ(tp));
- }
- if (flag & FWRITE) {
- selwakeup(&pti->pt_selw);
- wakeup(TSA_PTC_WRITE(tp));
- }
- (void) thread_funnel_set(kernel_flock, funnel_state);
-}
-
-FREE_BSDSTATIC int
-ptcopen(dev_t dev, __unused int flag, __unused int devtype, __unused proc_t p)
-{
- register struct tty *tp;
- struct pt_ioctl *pti;
- int error = 0;
- boolean_t funnel_state;
-
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
-
- if (minor(dev) >= npty) {
- error = ENXIO;
- goto out;
- }
- if(!pt_tty[minor(dev)]) {
- tp = pt_tty[minor(dev)] = ttymalloc();
- } else
- tp = pt_tty[minor(dev)];
- if (tp->t_oproc) {
- error = EIO;
- goto out;
- }
- tp->t_oproc = ptsstart;
-#ifdef sun4c
- tp->t_stop = ptsstop;
-#endif
- (void)(*linesw[tp->t_line].l_modem)(tp, 1);
- tp->t_lflag &= ~EXTPROC;
- pti = &pt_ioctl[minor(dev)];
- pti->pt_flags = 0;
- pti->pt_send = 0;
- pti->pt_ucntl = 0;
-out:
- (void) thread_funnel_set(kernel_flock, funnel_state);
- return (error);
-}