[REVIEW] move tty lock/initial up in the stack

Poul-Henning Kamp phk at phk.freebsd.dk
Sat Jun 19 08:16:06 GMT 2004


This patch moves the "lock/initial" facility known from sio(4) up
to the generic tty layer.

It adds two new flags to stty(1): -i and -l to manipulate the initial
and lock states and eliminates the tty[il]d# and cua[il]a# devices.

Subsequently I would like to move the tty/cua split up as well.

Poul-Henning


Index: bin/stty/stty.1
===================================================================
RCS file: /home/ncvs/src/bin/stty/stty.1,v
retrieving revision 1.28
diff -u -r1.28 stty.1
--- bin/stty/stty.1	6 Apr 2004 20:06:53 -0000	1.28
+++ bin/stty/stty.1	18 Jun 2004 11:43:40 -0000
@@ -41,6 +41,7 @@
 .Nm
 .Op Fl a | Fl e | Fl g
 .Op Fl f Ar file
+.Op Fl i | Fl l
 .Op operands
 .Sh DESCRIPTION
 The
@@ -83,6 +84,12 @@
 .Nm
 to restore the current terminal state as per
 .St -p1003.2 .
+.It Fl i
+Operate on the "initial" settings which apply on first open.
+.It Fl l
+Operate on the "lock" settings.
+Please note that the lock settings act as flags, the bits set here
+indicate which parts of the initial settings it is impossible to change.
 .El
 .Pp
 The following arguments are available to set the terminal
Index: bin/stty/stty.c
===================================================================
RCS file: /home/ncvs/src/bin/stty/stty.c,v
retrieving revision 1.22
diff -u -r1.22 stty.c
--- bin/stty/stty.c	6 Apr 2004 20:06:53 -0000	1.22
+++ bin/stty/stty.c	18 Jun 2004 11:36:57 -0000
@@ -60,15 +60,17 @@
 {
 	struct info i;
 	enum FMT fmt;
-	int ch;
+	int ch, iget, iset;
 
 	fmt = NOTSET;
 	i.fd = STDIN_FILENO;
 
 	opterr = 0;
+	iget = TIOCGETA;
+	iset = TIOCSETA;
 	while (optind < argc &&
 	    strspn(argv[optind], "-aefg") == strlen(argv[optind]) &&
-	    (ch = getopt(argc, argv, "aef:g")) != -1)
+	    (ch = getopt(argc, argv, "aef:gil")) != -1)
 		switch(ch) {
 		case 'a':		/* undocumented: POSIX compatibility */
 			fmt = POSIX;
@@ -83,6 +85,14 @@
 		case 'g':
 			fmt = GFLAG;
 			break;
+		case 'i':
+			iget = TIOCGETAI;
+			iset = TIOCSETAI;
+			break;
+		case 'l':
+			iget = TIOCGETAL;
+			iset = TIOCSETAL;
+			break;
 		case '?':
 		default:
 			goto args;
@@ -91,7 +101,7 @@
 args:	argc -= optind;
 	argv += optind;
 
-	if (tcgetattr(i.fd, &i.t) < 0)
+	if (ioctl(i.fd, iget, &i.t) < 0)
 		errx(1, "stdin isn't a terminal");
 	if (ioctl(i.fd, TIOCGETD, &i.ldisc) < 0)
 		err(1, "TIOCGETD");
@@ -144,7 +154,7 @@
 		usage();
 	}
 
-	if (i.set && tcsetattr(i.fd, 0, &i.t) < 0)
+	if (i.set && ioctl(i.fd, iset, &i.t) < 0)
 		err(1, "tcsetattr");
 	if (i.wset && ioctl(i.fd, TIOCSWINSZ, &i.win) < 0)
 		warn("TIOCSWINSZ");
Index: sys/dev/sio/sio.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/sio/sio.c,v
retrieving revision 1.438
diff -u -r1.438 sio.c
--- sys/dev/sio/sio.c	16 Jun 2004 09:46:56 -0000	1.438
+++ sys/dev/sio/sio.c	18 Jun 2004 13:06:42 -0000
@@ -89,9 +89,6 @@
 #define	LOTS_OF_EVENTS	64	/* helps separate urgent events from input */
 
 #define	CALLOUT_MASK		0x80
-#define	CONTROL_MASK		0x60
-#define	CONTROL_INIT_STATE	0x20
-#define	CONTROL_LOCK_STATE	0x40
 #define	DEV_TO_UNIT(dev)	(MINOR_TO_UNIT(minor(dev)))
 #define	MINOR_TO_UNIT(mynor)	((((mynor) & ~0xffffU) >> (8 + 3)) \
 				 | ((mynor) & 0x1f))
@@ -242,14 +239,6 @@
 
 	struct tty	*tp;	/* cross reference */
 
-	/* Initial state. */
-	struct termios	it_in;	/* should be in struct tty */
-	struct termios	it_out;
-
-	/* Lock state. */
-	struct termios	lt_in;	/* should be in struct tty */
-	struct termios	lt_out;
-
 	bool_t	do_timestamp;
 	bool_t	do_dcd_timestamp;
 	struct timeval	timestamp;
@@ -271,7 +260,7 @@
 	struct resource *ioportres;
 	int	ioportrid;
 	void	*cookie;
-	struct cdev *devs[6];
+	struct cdev *devs[2];
 
 	/*
 	 * Data area for output buffers.  Someday we should build the output
@@ -387,20 +376,18 @@
 	if (com == NULL)
 		return (ENXIO);
 
+	tp = com->tp;
 	/*
 	 * set the initial and lock rates for /dev/ttydXX and /dev/cuaXX
 	 * (note, the lock rates really are boolean -- if non-zero, disallow
 	 *  speed changes)
 	 */
-	com->it_in.c_ispeed  = com->it_in.c_ospeed =
-	com->lt_in.c_ispeed  = com->lt_in.c_ospeed =
-	com->it_out.c_ispeed = com->it_out.c_ospeed =
-	com->lt_out.c_ispeed = com->lt_out.c_ospeed = comdefaultrate;
+	tp->t_init.c_ispeed  = tp->t_init.c_ospeed =
+	tp->t_lock.c_ispeed  = tp->t_lock.c_ospeed = comdefaultrate;
 
 	/*
 	 * if we're open, change the running rate too
 	 */
-	tp = com->tp;
 	if (tp && (tp->t_state & TS_ISOPEN)) {
 		tp->t_termios.c_ispeed =
 		tp->t_termios.c_ospeed = comdefaultrate;
@@ -441,7 +428,7 @@
 		return (0);
 	}
 	com->gone = TRUE;
-	for (i = 0 ; i < 6; i++)
+	for (i = 0 ; i < 2; i++)
 		destroy_dev(com->devs[i]);
 	if (com->irqres) {
 		bus_teardown_intr(dev, com->irqres, com->cookie);
@@ -912,6 +899,7 @@
 	int		rid;
 	struct resource *port;
 	int		ret;
+	struct tty	*tp;
 
 	rid = xrid;
 	port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
@@ -964,28 +952,28 @@
 		rclk = DEFAULT_RCLK;
 	com->rclk = rclk;
 
+	tp = com->tp = ttymalloc(NULL);
 	/*
 	 * We don't use all the flags from <sys/ttydefaults.h> since they
 	 * are only relevant for logins.  It's important to have echo off
 	 * initially so that the line doesn't start blathering before the
 	 * echo flag can be turned off.
 	 */
-	com->it_in.c_iflag = 0;
-	com->it_in.c_oflag = 0;
-	com->it_in.c_cflag = TTYDEF_CFLAG;
-	com->it_in.c_lflag = 0;
+	tp->t_init.c_iflag = 0;
+	tp->t_init.c_oflag = 0;
+	tp->t_init.c_cflag = TTYDEF_CFLAG;
+	tp->t_init.c_lflag = 0;
 	if (unit == comconsole) {
-		com->it_in.c_iflag = TTYDEF_IFLAG;
-		com->it_in.c_oflag = TTYDEF_OFLAG;
-		com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL;
-		com->it_in.c_lflag = TTYDEF_LFLAG;
-		com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL;
-		com->lt_out.c_ispeed = com->lt_out.c_ospeed =
-		com->lt_in.c_ispeed = com->lt_in.c_ospeed =
-		com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate;
+		tp->t_init.c_iflag = TTYDEF_IFLAG;
+		tp->t_init.c_oflag = TTYDEF_OFLAG;
+		tp->t_init.c_cflag = TTYDEF_CFLAG | CLOCAL;
+		tp->t_init.c_lflag = TTYDEF_LFLAG;
+		tp->t_lock.c_cflag = CLOCAL;
+		tp->t_lock.c_ispeed = tp->t_lock.c_ospeed =
+		tp->t_init.c_ispeed = tp->t_init.c_ospeed = comdefaultrate;
 	} else
-		com->it_in.c_ispeed = com->it_in.c_ospeed = TTYDEF_SPEED;
-	if (siosetwater(com, com->it_in.c_ispeed) != 0) {
+		tp->t_init.c_ispeed = tp->t_init.c_ospeed = TTYDEF_SPEED;
+	if (siosetwater(com, tp->t_init.c_ispeed) != 0) {
 		mtx_unlock_spin(&sio_lock);
 		/*
 		 * Leave i/o resources allocated if this is a `cn'-level
@@ -996,8 +984,7 @@
 		return (ENOMEM);
 	}
 	mtx_unlock_spin(&sio_lock);
-	termioschars(&com->it_in);
-	com->it_out = com->it_in;
+	termioschars(&tp->t_init);
 
 	/* attempt to determine UART type */
 	printf("sio%d: type", unit);
@@ -1125,20 +1112,12 @@
 	minorbase = UNIT_TO_MINOR(unit);
 	com->devs[0] = make_dev(&sio_cdevsw, minorbase,
 	    UID_ROOT, GID_WHEEL, 0600, "ttyd%r", unit);
-	com->devs[1] = make_dev(&sio_cdevsw, minorbase | CONTROL_INIT_STATE,
-	    UID_ROOT, GID_WHEEL, 0600, "ttyid%r", unit);
-	com->devs[2] = make_dev(&sio_cdevsw, minorbase | CONTROL_LOCK_STATE,
-	    UID_ROOT, GID_WHEEL, 0600, "ttyld%r", unit);
-	com->devs[3] = make_dev(&sio_cdevsw, minorbase | CALLOUT_MASK,
+	com->devs[1] = make_dev(&sio_cdevsw, minorbase | CALLOUT_MASK,
 	    UID_UUCP, GID_DIALER, 0660, "cuaa%r", unit);
-	com->devs[4] = make_dev(&sio_cdevsw,
-	    minorbase | CALLOUT_MASK | CONTROL_INIT_STATE,
-	    UID_UUCP, GID_DIALER, 0660, "cuaia%r", unit);
-	com->devs[5] = make_dev(&sio_cdevsw,
-	    minorbase | CALLOUT_MASK | CONTROL_LOCK_STATE,
-	    UID_UUCP, GID_DIALER, 0660, "cuala%r", unit);
-	for (rid = 0; rid < 6; rid++)
+	for (rid = 0; rid < 2; rid++) {
 		com->devs[rid]->si_drv1 = com;
+		com->devs[rid]->si_tty = tp;
+	}
 	com->flags = flags;
 	com->pps.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR;
 
@@ -1199,9 +1178,7 @@
 		return (ENXIO);
 	if (com->gone)
 		return (ENXIO);
-	if (mynor & CONTROL_MASK)
-		return (0);
-	tp = dev->si_tty = com->tp = ttymalloc(com->tp);
+	tp = dev->si_tty;
 	s = spltty();
 	/*
 	 * We jump to this label after all non-interrupted sleeps to pick
@@ -1256,8 +1233,7 @@
 		tp->t_param = comparam;
 		tp->t_stop = comstop;
 		tp->t_dev = dev;
-		tp->t_termios = mynor & CALLOUT_MASK
-				? com->it_out : com->it_in;
+		tp->t_termios = tp->t_init;
 		(void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET);
 		com->poll = com->no_irq;
 		com->poll_output = com->loses_outints;
@@ -1374,8 +1350,6 @@
 	struct tty	*tp;
 
 	mynor = minor(dev);
-	if (mynor & CONTROL_MASK)
-		return (0);
 	com = com_addr(MINOR_TO_UNIT(mynor));
 	if (com == NULL)
 		return (ENODEV);
@@ -1435,7 +1409,7 @@
 		     */
 		    || (!com->active_out
 		        && !(com->prev_modem_status & MSR_DCD)
-		        && !(com->it_in.c_cflag & CLOCAL))
+		        && !(tp->t_init.c_cflag & CLOCAL))
 		    || !(tp->t_state & TS_ISOPEN)) {
 			(void)commctl(com, TIOCM_DTR, DMBIC);
 			if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) {
@@ -1468,8 +1442,6 @@
 	struct com_s	*com;
 
 	mynor = minor(dev);
-	if (mynor & CONTROL_MASK)
-		return (ENODEV);
 	com = com_addr(MINOR_TO_UNIT(mynor));
 	if (com == NULL || com->gone)
 		return (ENODEV);
@@ -1487,8 +1459,6 @@
 	int		unit;
 
 	mynor = minor(dev);
-	if (mynor & CONTROL_MASK)
-		return (ENODEV);
 
 	unit = MINOR_TO_UNIT(mynor);
 	com = com_addr(unit);
@@ -1981,39 +1951,6 @@
 	com = com_addr(MINOR_TO_UNIT(mynor));
 	if (com == NULL || com->gone)
 		return (ENODEV);
-	if (mynor & CONTROL_MASK) {
-		struct termios	*ct;
-
-		switch (mynor & CONTROL_MASK) {
-		case CONTROL_INIT_STATE:
-			ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in;
-			break;
-		case CONTROL_LOCK_STATE:
-			ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in;
-			break;
-		default:
-			return (ENODEV);	/* /dev/nodev */
-		}
-		switch (cmd) {
-		case TIOCSETA:
-			error = suser(td);
-			if (error != 0)
-				return (error);
-			*ct = *(struct termios *)data;
-			return (0);
-		case TIOCGETA:
-			*(struct termios *)data = *ct;
-			return (0);
-		case TIOCGETD:
-			*(int *)data = TTYDISC;
-			return (0);
-		case TIOCGWINSZ:
-			bzero(data, sizeof(struct winsize));
-			return (0);
-		default:
-			return (ENOTTY);
-		}
-	}
 	tp = com->tp;
 #if defined(COMPAT_43)
 	term = tp->t_termios;
@@ -2027,8 +1964,7 @@
 	if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) {
 		int	cc;
 		struct termios *dt = (struct termios *)data;
-		struct termios *lt = mynor & CALLOUT_MASK
-				     ? &com->lt_out : &com->lt_in;
+		struct termios *lt = &tp->t_lock;
 
 		dt->c_iflag = (tp->t_iflag & lt->c_iflag)
 			      | (dt->c_iflag & ~lt->c_iflag);
Index: sys/kern/tty.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/tty.c,v
retrieving revision 1.219
diff -u -r1.219 tty.c
--- sys/kern/tty.c	16 Jun 2004 09:47:12 -0000	1.219
+++ sys/kern/tty.c	18 Jun 2004 11:48:41 -0000
@@ -769,6 +769,8 @@
 	case  TIOCSTI:
 	case  TIOCSTOP:
 	case  TIOCSWINSZ:
+	case  TIOCSETAI:
+	case  TIOCSETAL:
 #if defined(COMPAT_43)
 	case  TIOCLBIC:
 	case  TIOCLBIS:
@@ -1129,6 +1131,24 @@
 	case TIOCGDRAINWAIT:
 		*(int *)data = tp->t_timeout / hz;
 		break;
+	case TIOCSETAI:
+		error = suser(td);
+		if (error)
+			return (error);
+		tp->t_init = *(struct termios *)data;
+		break;
+	case TIOCGETAI:
+		*(struct termios *)data = tp->t_init;
+		break;
+	case TIOCSETAL:
+		error = suser(td);
+		if (error)
+			return (error);
+		tp->t_lock = *(struct termios *)data;
+		break;
+	case TIOCGETAL:
+		*(struct termios *)data = tp->t_lock;
+		break;
 	default:
 #if defined(COMPAT_43)
 		return (ttcompat(tp, cmd, data, flag));
Index: sys/sys/tty.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/tty.h,v
retrieving revision 1.81
diff -u -r1.81 tty.h
--- sys/sys/tty.h	17 Jun 2004 17:16:53 -0000	1.81
+++ sys/sys/tty.h	18 Jun 2004 11:42:43 -0000
@@ -94,6 +94,8 @@
 	struct	selinfo t_rsel;		/* Tty read/oob select. */
 	struct	selinfo t_wsel;		/* Tty write select. */
 	struct	termios t_termios;	/* Termios state. */
+	struct	termios t_init;		/* Initial termios state. */
+	struct	termios t_lock;		/* Locked termios state. */
 	struct	winsize t_winsize;	/* Window size. */
 					/* Start output. */
 	void	(*t_oproc)(struct tty *);
Index: sys/sys/ttycom.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/ttycom.h,v
retrieving revision 1.20
diff -u -r1.20 ttycom.h
--- sys/sys/ttycom.h	10 May 2004 02:24:56 -0000	1.20
+++ sys/sys/ttycom.h	18 Jun 2004 11:51:35 -0000
@@ -73,7 +73,11 @@
 						/* 23-25 obsolete or unused */
 #define	TIOCGETD	_IOR('t', 26, int)	/* get line discipline */
 #define	TIOCSETD	_IOW('t', 27, int)	/* set line discipline */
-						/* 28-69 free */
+#define	TIOCGETAI	_IOR('t', 28, struct termios) /* get init params */
+#define	TIOCSETAI	_IOW('t', 29, struct termios) /* set init params */
+#define	TIOCGETAL	_IOR('t', 30, struct termios) /* get lock params */
+#define	TIOCSETAL	_IOW('t', 31, struct termios) /* set lock params */
+						/* 32-69 free */
 						/* 127-124 compat */
 #define	TIOCSBRK	 _IO('t', 123)		/* set break bit */
 #define	TIOCCBRK	 _IO('t', 122)		/* clear break bit */
-- 
Poul-Henning Kamp       | UNIX since Zilog Zeus 3.20
phk at FreeBSD.ORG         | TCP/IP since RFC 956
FreeBSD committer       | BSD since 4.3-tahoe
Never attribute to malice what can adequately be explained by incompetence.


More information about the freebsd-current mailing list