Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 18 May 2018 14:57:59 +0000 (UTC)
From:      Glen Barber <gjb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r333796 - in stable/11: include lib/libc/gen libexec/getty sbin/init
Message-ID:  <201805181457.w4IEvxut012704@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: gjb
Date: Fri May 18 14:57:58 2018
New Revision: 333796
URL: https://svnweb.freebsd.org/changeset/base/333796

Log:
  MFC r315733, r315737, r315740, r330054:
  
   r315733 (imp):
    Impelemnt ttys onifexists in init.
  
    Implement a new init(8) option in /etc/ttys. If this option is present
    on the entry in /etc/ttys, the entry will be active if and only if it
    exists.  If the name starts with a '/', it will be considered an
    absolute path. If not, it will be a path relative to /dev.
  
    This allows one to turn off video console getty that aren't present
    (while running a getty on them even when they aren't the system
    console). Likewise with serial ports.
  
    It differs from onifconsole in only requiring the device exist rather
    than it be listed as one of the system consoles.
  
   r315737 (ngie):
    Unbreak world by adding sys/stat.h for stat(2)
  
   r315740 (imp):
    Simplify the code a little.
  
   r330054 (trasz):
    Improve missing tty handling in init(8).  This removes a check that did
    nothing - it was checking for ENXIO, which, with devfs, is no longer
    returned - and was badly placed anyway, and replaces it with similar
    one that works, and is done just before starting getty, instead of being
    done when rereading ttys(5).
  
    From the practical point of view, this makes init(8) handle disappearing
    terminals (eg /dev/ttyU*) gracefully, without unneccessary getty restarts
    and resulting error messages.
  
  Reported by:	Bart Ender, Andre Albsmeier
  PR:		228315
  Blocks:		11.2-BETA2
  Approved by:	re (marius)
  Sponsored by:	The FreeBSD Foundation

Modified:
  stable/11/include/ttyent.h
  stable/11/lib/libc/gen/getttyent.3
  stable/11/lib/libc/gen/getttyent.c
  stable/11/libexec/getty/ttys.5
  stable/11/sbin/init/init.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/include/ttyent.h
==============================================================================
--- stable/11/include/ttyent.h	Fri May 18 14:57:06 2018	(r333795)
+++ stable/11/include/ttyent.h	Fri May 18 14:57:58 2018	(r333796)
@@ -38,6 +38,7 @@
 #define	_TTYS_OFF	"off"
 #define	_TTYS_ON	"on"
 #define	_TTYS_ONIFCONSOLE "onifconsole"
+#define	_TTYS_ONIFEXISTS "onifexists"
 #define	_TTYS_SECURE	"secure"
 #define	_TTYS_INSECURE	"insecure"
 #define	_TTYS_WINDOW	"window"
@@ -54,6 +55,8 @@ struct ttyent {
 #define	TTY_SECURE	0x02	/* allow uid of 0 to login */
 #define	TTY_DIALUP	0x04	/* is a dialup tty */
 #define	TTY_NETWORK	0x08	/* is a network tty */
+#define	TTY_IFEXISTS	0x10	/* configured as "onifexists" */
+#define	TTY_IFCONSOLE	0x20	/* configured as "onifconsole" */
 	int	ty_status;	/* status flags */
 	char 	*ty_window;	/* command to start up window manager */
 	char	*ty_comment;	/* comment field */

Modified: stable/11/lib/libc/gen/getttyent.3
==============================================================================
--- stable/11/lib/libc/gen/getttyent.3	Fri May 18 14:57:06 2018	(r333795)
+++ stable/11/lib/libc/gen/getttyent.3	Fri May 18 14:57:58 2018	(r333796)
@@ -75,6 +75,8 @@ struct ttyent {
 #define	TTY_SECURE	0x02	/* allow uid of 0 to login */
 #define	TTY_DIALUP	0x04	/* is a dialup tty */
 #define	TTY_NETWORK	0x08	/* is a network tty */
+#define	TTY_IFEXISTS	0x10	/* configured as "onifexists" */
+#define	TTY_IFCONSOLE	0x20	/* configured as "onifconsole" */
 	int	ty_status;	/* status flags */
 	char	*ty_window;	/* command to start up window manager */
 	char	*ty_comment;	/* comment field */
@@ -115,6 +117,10 @@ Identifies a tty used for network connections.
 If this flag is set, then
 .Fn isnettty
 will return a non-zero value.
+.It Dv TTY_IFEXISTS
+Identifies a tty that does not neccessarily exist.
+.It Dv TTY_IFCONSOLE
+Identifies a tty that might be a system console.
 .El
 .It Fa ty_window
 The command to execute for a window system associated with the line.

Modified: stable/11/lib/libc/gen/getttyent.c
==============================================================================
--- stable/11/lib/libc/gen/getttyent.c	Fri May 18 14:57:06 2018	(r333795)
+++ stable/11/lib/libc/gen/getttyent.c	Fri May 18 14:57:58 2018	(r333796)
@@ -34,6 +34,7 @@ static char sccsid[] = "@(#)getttyent.c	8.1 (Berkeley)
 __FBSDID("$FreeBSD$");
 
 #include <sys/types.h>
+#include <sys/stat.h>
 #include <sys/sysctl.h>
 
 #include <ctype.h>
@@ -72,11 +73,14 @@ auto_tty_status(const char *ty_name)
 {
 	size_t len;
 	char *buf, *cons, *nextcons;
+	int rv;
 
+	rv = TTY_IFCONSOLE;
+
 	/* Check if this is an enabled kernel console line */
 	buf = NULL;
 	if (sysctlbyname("kern.console", NULL, &len, NULL, 0) == -1)
-		return (0); /* Errors mean don't enable */
+		return (rv); /* Errors mean don't enable */
 	buf = malloc(len);
 	if (sysctlbyname("kern.console", buf, &len, NULL, 0) == -1)
 		goto done;
@@ -87,16 +91,34 @@ auto_tty_status(const char *ty_name)
 	nextcons = buf;
 	while ((cons = strsep(&nextcons, ",")) != NULL && strlen(cons) != 0) {
 		if (strcmp(cons, ty_name) == 0) {
-			free(buf);
-			return (TTY_ON);
+			rv |= TTY_ON;
+			break;
 		}
 	}
 
 done:
 	free(buf);
-	return (0);
+	return (rv);
 }
 
+static int
+auto_exists_status(const char *ty_name)
+{
+	struct stat sb;
+	char *dev;
+	int rv;
+
+	rv = TTY_IFEXISTS;
+	if (*ty_name == '/')
+		asprintf(&dev, "%s", ty_name);
+	else
+		asprintf(&dev, "/dev/%s", ty_name);
+	if (dev != NULL && stat(dev, &sb) == 0)
+		rv |= TTY_ON;
+	free(dev);
+	return (rv);
+}
+
 struct ttyent *
 getttyent(void)
 {
@@ -161,6 +183,8 @@ getttyent(void)
 			tty.ty_status |= TTY_ON;
 		else if (scmp(_TTYS_ONIFCONSOLE))
 			tty.ty_status |= auto_tty_status(tty.ty_name);
+		else if (scmp(_TTYS_ONIFEXISTS))
+			tty.ty_status |= auto_exists_status(tty.ty_name);
 		else if (scmp(_TTYS_SECURE))
 			tty.ty_status |= TTY_SECURE;
 		else if (scmp(_TTYS_INSECURE))

Modified: stable/11/libexec/getty/ttys.5
==============================================================================
--- stable/11/libexec/getty/ttys.5	Fri May 18 14:57:06 2018	(r333795)
+++ stable/11/libexec/getty/ttys.5	Fri May 18 14:57:58 2018	(r333796)
@@ -28,7 +28,7 @@
 .\"     from: @(#)ttys.5	8.1 (Berkeley) 6/4/93
 .\" $FreeBSD$
 .\" "
-.Dd March 9, 2014
+.Dd March 16, 2017
 .Dt TTYS 5
 .Os
 .Sh NAME
@@ -105,6 +105,12 @@ should (should not) execute the command given in the s
 ``onifconsole'' will cause this line to be enabled if and only if it is
 an active kernel console device (it is equivalent to ``on'' in this
 case).
+The flag ``onifexists'' will cause this line to be enabled if and only
+if the name exists.
+If the name starts with a ``/'', it will be considered an absolute
+path.
+Otherwise, it is considered a path relative to
+.Pa /dev .
 The flag ``secure'' (if the console is enabled) allows users with a
 uid of 0 to login on
 this line.

Modified: stable/11/sbin/init/init.c
==============================================================================
--- stable/11/sbin/init/init.c	Fri May 18 14:57:06 2018	(r333795)
+++ stable/11/sbin/init/init.c	Fri May 18 14:57:58 2018	(r333796)
@@ -154,6 +154,8 @@ typedef struct init_session {
 	int	se_flags;		/* status of session */
 #define	SE_SHUTDOWN	0x1		/* session won't be restarted */
 #define	SE_PRESENT	0x2		/* session is in /etc/ttys */
+#define	SE_IFEXISTS	0x4		/* session defined as "onifexists" */
+#define	SE_IFCONSOLE	0x8		/* session defined as "onifconsole" */
 	int	se_nspace;		/* spacing count */
 	char	*se_device;		/* filename of port */
 	char	*se_getty;		/* what to run on that port */
@@ -1260,7 +1262,6 @@ static session_t *
 new_session(session_t *sprev, struct ttyent *typ)
 {
 	session_t *sp;
-	int fd;
 
 	if ((typ->ty_status & TTY_ON) == 0 ||
 	    typ->ty_name == 0 ||
@@ -1271,21 +1272,15 @@ new_session(session_t *sprev, struct ttyent *typ)
 
 	sp->se_flags |= SE_PRESENT;
 
+	if ((typ->ty_status & TTY_IFEXISTS) != 0)
+		sp->se_flags |= SE_IFEXISTS;
+
+	if ((typ->ty_status & TTY_IFCONSOLE) != 0)
+		sp->se_flags |= SE_IFCONSOLE;
+
 	if (asprintf(&sp->se_device, "%s%s", _PATH_DEV, typ->ty_name) < 0)
 		err(1, "asprintf");
 
-	/*
-	 * Attempt to open the device, if we get "device not configured"
-	 * then don't add the device to the session list.
-	 */
-	if ((fd = open(sp->se_device, O_RDONLY | O_NONBLOCK, 0)) < 0) {
-		if (errno == ENXIO) {
-			free_session(sp);
-			return (0);
-		}
-	} else
-		close(fd);
-
 	if (setupargv(sp, typ) == 0) {
 		free_session(sp);
 		return (0);
@@ -1505,6 +1500,30 @@ start_getty(session_t *sp)
 }
 
 /*
+ * Return 1 if the session is defined as "onifexists"
+ * or "onifconsole" and the device node does not exist.
+ */
+static int
+session_has_no_tty(session_t *sp)
+{
+	int fd;
+
+	if ((sp->se_flags & SE_IFEXISTS) == 0 &&
+	    (sp->se_flags & SE_IFCONSOLE) == 0)
+		return (0);
+
+	fd = open(sp->se_device, O_RDONLY | O_NONBLOCK, 0);
+	if (fd < 0) {
+		if (errno == ENOENT)
+			return (1);
+		return (0);
+	}
+
+	close(fd);
+	return (0);
+}
+
+/*
  * Collect exit status for a child.
  * If an exiting login, start a new login running.
  */
@@ -1522,7 +1541,8 @@ collect_child(pid_t pid)
 	del_session(sp);
 	sp->se_process = 0;
 
-	if (sp->se_flags & SE_SHUTDOWN) {
+	if (sp->se_flags & SE_SHUTDOWN ||
+	    session_has_no_tty(sp)) {
 		if ((sprev = sp->se_prev) != NULL)
 			sprev->se_next = sp->se_next;
 		else
@@ -1607,6 +1627,8 @@ multi_user(void)
 
 	for (sp = sessions; sp; sp = sp->se_next) {
 		if (sp->se_process)
+			continue;
+		if (session_has_no_tty(sp))
 			continue;
 		if ((pid = start_getty(sp)) == -1) {
 			/* serious trouble */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201805181457.w4IEvxut012704>