summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgjb <gjb@FreeBSD.org>2018-05-18 14:57:58 +0000
committergjb <gjb@FreeBSD.org>2018-05-18 14:57:58 +0000
commit630222de41b8cb3b18a61d59e8fa395d533e97fe (patch)
tree45e31405457becced671b631a52d4ff7e4166476
parentfcab6c1e9f9602099dc6b4b34d38da972a7059bd (diff)
downloadFreeBSD-src-630222de41b8cb3b18a61d59e8fa395d533e97fe.zip
FreeBSD-src-630222de41b8cb3b18a61d59e8fa395d533e97fe.tar.gz
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
-rw-r--r--include/ttyent.h3
-rw-r--r--lib/libc/gen/getttyent.36
-rw-r--r--lib/libc/gen/getttyent.c32
-rw-r--r--libexec/getty/ttys.58
-rw-r--r--sbin/init/init.c50
5 files changed, 80 insertions, 19 deletions
diff --git a/include/ttyent.h b/include/ttyent.h
index f2220ad..928da81 100644
--- a/include/ttyent.h
+++ b/include/ttyent.h
@@ -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 */
diff --git a/lib/libc/gen/getttyent.3 b/lib/libc/gen/getttyent.3
index 18c3f07..43b2ace 100644
--- a/lib/libc/gen/getttyent.3
+++ b/lib/libc/gen/getttyent.3
@@ -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.
diff --git a/lib/libc/gen/getttyent.c b/lib/libc/gen/getttyent.c
index 266f631..e0b2698 100644
--- a/lib/libc/gen/getttyent.c
+++ b/lib/libc/gen/getttyent.c
@@ -34,6 +34,7 @@ static char sccsid[] = "@(#)getttyent.c 8.1 (Berkeley) 6/4/93";
__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,14 +91,32 @@ 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 *
@@ -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))
diff --git a/libexec/getty/ttys.5 b/libexec/getty/ttys.5
index d4c7f1d..1150909 100644
--- a/libexec/getty/ttys.5
+++ b/libexec/getty/ttys.5
@@ -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 second field.
``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.
diff --git a/sbin/init/init.c b/sbin/init/init.c
index f4206c4..12cf9a7 100644
--- a/sbin/init/init.c
+++ b/sbin/init/init.c
@@ -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
@@ -1608,6 +1628,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 */
requested_transition = clean_ttys;
OpenPOWER on IntegriCloud