⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tty_pty.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1982, 1986, 1989, 1993 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *	@(#)tty_pty.c	8.2 (Berkeley) 9/23/93 *//* * Pseudo-teletype Driver * (Actually two drivers, requiring two entries in 'cdevsw') */#include "pty.h"		/* XXX */#include <sys/param.h>#include <sys/systm.h>#include <sys/ioctl.h>#include <sys/proc.h>#include <sys/tty.h>#include <sys/conf.h>#include <sys/file.h>#include <sys/uio.h>#include <sys/kernel.h>#include <sys/vnode.h>#if NPTY == 1#undef NPTY#define	NPTY	32		/* crude XXX */#endif#define BUFSIZ 100		/* Chunk size iomoved to/from user *//* * pts == /dev/tty[pqrs]? * ptc == /dev/pty[pqrs]? */struct	tty pt_tty[NPTY];	/* XXX */struct	pt_ioctl {	int	pt_flags;	struct	selinfo pt_selr, pt_selw;	u_char	pt_send;	u_char	pt_ucntl;} pt_ioctl[NPTY];		/* XXX */int	npty = NPTY;		/* for pstat -t */#define	PF_PKT		0x08		/* packet mode */#define	PF_STOPPED	0x10		/* user told stopped */#define	PF_REMOTE	0x20		/* remote and flow controlled input */#define	PF_NOSTOP	0x40#define PF_UCNTL	0x80		/* user control mode */void	ptsstop __P((struct tty *, int));/* * Establish n (or default if n is 1) ptys in the system. * * XXX cdevsw & pstat require the array `pty[]' to be an array */voidptyattach(n)	int n;{#ifdef notyet	char *mem;	register u_long ntb;#define	DEFAULT_NPTY	32	/* maybe should allow 0 => none? */	if (n <= 1)		n = DEFAULT_NPTY;	ntb = n * sizeof(struct tty);	mem = malloc(ntb + ALIGNBYTES + n * sizeof(struct pt_ioctl),	    M_DEVBUF, M_WAITOK);	pt_tty = (struct tty *)mem;	mem = (char *)ALIGN(mem + ntb);	pt_ioctl = (struct pt_ioctl *)mem;	npty = n;#endif}/*ARGSUSED*/ptsopen(dev, flag, devtype, p)	dev_t dev;	int flag, devtype;	struct proc *p;{	register struct tty *tp;	int error;	if (minor(dev) >= npty)		return (ENXIO);	tp = &pt_tty[minor(dev)];	if ((tp->t_state & TS_ISOPEN) == 0) {		tp->t_state |= TS_WOPEN;		ttychars(tp);		/* Set up default chars */		tp->t_iflag = TTYDEF_IFLAG;		tp->t_oflag = TTYDEF_OFLAG;		tp->t_lflag = TTYDEF_LFLAG;		tp->t_cflag = TTYDEF_CFLAG;		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;		ttsetwater(tp);		/* would be done in xxparam() */	} else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)		return (EBUSY);	if (tp->t_oproc)			/* Ctrlr still around. */		tp->t_state |= TS_CARR_ON;	while ((tp->t_state & TS_CARR_ON) == 0) {		tp->t_state |= TS_WOPEN;		if (flag&FNONBLOCK)			break;		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,		    ttopen, 0))			return (error);	}	error = (*linesw[tp->t_line].l_open)(dev, tp);	ptcwakeup(tp, FREAD|FWRITE);	return (error);}ptsclose(dev, flag, mode, p)	dev_t dev;	int flag, mode;	struct proc *p;{	register struct tty *tp;	int err;	tp = &pt_tty[minor(dev)];	err = (*linesw[tp->t_line].l_close)(tp, flag);	err |= ttyclose(tp);	ptcwakeup(tp, FREAD|FWRITE);	return (err);}ptsread(dev, uio, flag)	dev_t dev;	struct uio *uio;	int flag;{	struct proc *p = curproc;	register struct tty *tp = &pt_tty[minor(dev)];	register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];	int error = 0;again:	if (pti->pt_flags & PF_REMOTE) {		while (isbackground(p, tp)) {			if ((p->p_sigignore & sigmask(SIGTTIN)) ||			    (p->p_sigmask & sigmask(SIGTTIN)) ||			    p->p_pgrp->pg_jobc == 0 ||			    p->p_flag & P_PPWAIT)				return (EIO);			pgsignal(p->p_pgrp, SIGTTIN, 1);			if (error = ttysleep(tp, (caddr_t)&lbolt, 			    TTIPRI | PCATCH, ttybg, 0))				return (error);		}		if (tp->t_canq.c_cc == 0) {			if (flag & IO_NDELAY)				return (EWOULDBLOCK);			if (error = ttysleep(tp, (caddr_t)&tp->t_canq,			    TTIPRI | PCATCH, ttyin, 0))				return (error);			goto again;		}		while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0)			if (ureadc(getc(&tp->t_canq), uio) < 0) {				error = EFAULT;				break;			}		if (tp->t_canq.c_cc == 1)			(void) getc(&tp->t_canq);		if (tp->t_canq.c_cc)			return (error);	} else		if (tp->t_oproc)			error = (*linesw[tp->t_line].l_read)(tp, uio, flag);	ptcwakeup(tp, FWRITE);	return (error);}/* * Write to pseudo-tty. * Wakeups of controlling tty will happen * indirectly, when tty driver calls ptsstart. */ptswrite(dev, uio, flag)	dev_t dev;	struct uio *uio;	int flag;{	register struct tty *tp;	tp = &pt_tty[minor(dev)];	if (tp->t_oproc == 0)		return (EIO);	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));}/* * Start output on pseudo-tty. * Wake up process selecting or sleeping for input from controlling tty. */voidptsstart(tp)	struct tty *tp;{	register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];	if (tp->t_state & TS_TTSTOP)		return;	if (pti->pt_flags & PF_STOPPED) {		pti->pt_flags &= ~PF_STOPPED;		pti->pt_send = TIOCPKT_START;	}	ptcwakeup(tp, FREAD);}ptcwakeup(tp, flag)	struct tty *tp;	int flag;{	struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];	if (flag & FREAD) {		selwakeup(&pti->pt_selr);		wakeup((caddr_t)&tp->t_outq.c_cf);	}	if (flag & FWRITE) {		selwakeup(&pti->pt_selw);		wakeup((caddr_t)&tp->t_rawq.c_cf);	}}/*ARGSUSED*/#ifdef __STDC__ptcopen(dev_t dev, int flag, int devtype, struct proc *p)#elseptcopen(dev, flag, devtype, p)	dev_t dev;	int flag, devtype;	struct proc *p;#endif{	register struct tty *tp;	struct pt_ioctl *pti;	if (minor(dev) >= npty)		return (ENXIO);	tp = &pt_tty[minor(dev)];	if (tp->t_oproc)		return (EIO);	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;	return (0);}ptcclose(dev)	dev_t dev;{	register struct tty *tp;	tp = &pt_tty[minor(dev)];	(void)(*linesw[tp->t_line].l_modem)(tp, 0);	tp->t_state &= ~TS_CARR_ON;	tp->t_oproc = 0;		/* mark closed */	tp->t_session = 0;	return (0);}ptcread(dev, uio, flag)	dev_t dev;	struct uio *uio;	int flag;{	register struct tty *tp = &pt_tty[minor(dev)];	struct pt_ioctl *pti = &pt_ioctl[minor(dev)];	char buf[BUFSIZ];	int error = 0, cc;	/*	 * We want to block until the slave	 * is open, and there's something to read;	 * but if we lost the slave or we're NBIO,	 * then return the appropriate error instead.	 */	for (;;) {		if (tp->t_state&TS_ISOPEN) {			if (pti->pt_flags&PF_PKT && pti->pt_send) {				error = ureadc((int)pti->pt_send, uio);				if (error)					return (error);				if (pti->pt_send & TIOCPKT_IOCTL) {					cc = min(uio->uio_resid,						sizeof(tp->t_termios));					uiomove(&tp->t_termios, cc, uio);				}				pti->pt_send = 0;				return (0);			}			if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) {				error = ureadc((int)pti->pt_ucntl, uio);				if (error)					return (error);				pti->pt_ucntl = 0;				return (0);			}			if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)				break;		}		if ((tp->t_state&TS_CARR_ON) == 0)			return (0);	/* EOF */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -