diff options
author | Edward Tomasz Napierala <trasz@FreeBSD.org> | 2018-02-27 10:54:15 +0000 |
---|---|---|
committer | Edward Tomasz Napierala <trasz@FreeBSD.org> | 2018-02-27 10:54:15 +0000 |
commit | 1cde387c8335360900b1955a9c69a620976b5d9a (patch) | |
tree | 9f7d40961dbd50e2fd62223eb6bdbbcc6378e3de /sbin/init/init.c | |
parent | 8d55975f921f88f0e411d2e0b81ff4cbd94fe72e (diff) | |
download | src-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.c | 50 |
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; |