aboutsummaryrefslogtreecommitdiff
path: root/sbin/init/init.c
diff options
context:
space:
mode:
authorEdward Tomasz Napierala <trasz@FreeBSD.org>2018-02-27 10:54:15 +0000
committerEdward Tomasz Napierala <trasz@FreeBSD.org>2018-02-27 10:54:15 +0000
commit1cde387c8335360900b1955a9c69a620976b5d9a (patch)
tree9f7d40961dbd50e2fd62223eb6bdbbcc6378e3de /sbin/init/init.c
parent8d55975f921f88f0e411d2e0b81ff4cbd94fe72e (diff)
downloadsrc-1cde387c8335360900b1955a9c69a620976b5d9a.tar.gz
src-1cde387c8335360900b1955a9c69a620976b5d9a.zip
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. Reviewed by: imp@ MFC after: 2 weeks Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D14307
Notes
Notes: svn path=/head/; revision=330054
Diffstat (limited to 'sbin/init/init.c')
-rw-r--r--sbin/init/init.c50
1 files changed, 36 insertions, 14 deletions
diff --git a/sbin/init/init.c b/sbin/init/init.c
index e0ec7cd891ea..235c3f13ffd3 100644
--- a/sbin/init/init.c
+++ b/sbin/init/init.c
@@ -156,6 +156,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 */
@@ -1262,7 +1264,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 ||
@@ -1273,21 +1274,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);
@@ -1507,6 +1502,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.
*/
@@ -1524,7 +1543,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
@@ -1611,6 +1631,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;