From owner-svn-src-head@freebsd.org Tue Feb 27 10:54:16 2018 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 8888FF39DC6; Tue, 27 Feb 2018 10:54:16 +0000 (UTC) (envelope-from trasz@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 3C50F6EE0E; Tue, 27 Feb 2018 10:54:16 +0000 (UTC) (envelope-from trasz@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 362F0164F; Tue, 27 Feb 2018 10:54:16 +0000 (UTC) (envelope-from trasz@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w1RAsFi1098391; Tue, 27 Feb 2018 10:54:15 GMT (envelope-from trasz@FreeBSD.org) Received: (from trasz@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w1RAsF0r098387; Tue, 27 Feb 2018 10:54:15 GMT (envelope-from trasz@FreeBSD.org) Message-Id: <201802271054.w1RAsF0r098387@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: trasz set sender to trasz@FreeBSD.org using -f From: Edward Tomasz Napierala Date: Tue, 27 Feb 2018 10:54:15 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r330054 - in head: include lib/libc/gen sbin/init X-SVN-Group: head X-SVN-Commit-Author: trasz X-SVN-Commit-Paths: in head: include lib/libc/gen sbin/init X-SVN-Commit-Revision: 330054 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 27 Feb 2018 10:54:16 -0000 Author: trasz Date: Tue Feb 27 10:54:15 2018 New Revision: 330054 URL: https://svnweb.freebsd.org/changeset/base/330054 Log: 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 Modified: head/include/ttyent.h head/lib/libc/gen/getttyent.3 head/lib/libc/gen/getttyent.c head/sbin/init/init.c Modified: head/include/ttyent.h ============================================================================== --- head/include/ttyent.h Tue Feb 27 04:41:14 2018 (r330053) +++ head/include/ttyent.h Tue Feb 27 10:54:15 2018 (r330054) @@ -57,6 +57,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: head/lib/libc/gen/getttyent.3 ============================================================================== --- head/lib/libc/gen/getttyent.3 Tue Feb 27 04:41:14 2018 (r330053) +++ head/lib/libc/gen/getttyent.3 Tue Feb 27 10:54:15 2018 (r330054) @@ -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: head/lib/libc/gen/getttyent.c ============================================================================== --- head/lib/libc/gen/getttyent.c Tue Feb 27 04:41:14 2018 (r330053) +++ head/lib/libc/gen/getttyent.c Tue Feb 27 10:54:15 2018 (r330054) @@ -75,11 +75,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; @@ -90,14 +93,14 @@ 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 @@ -107,13 +110,13 @@ auto_exists_status(const char *ty_name) char *dev; int rv; - rv = 0; + 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; + rv |= TTY_ON; free(dev); return (rv); } Modified: head/sbin/init/init.c ============================================================================== --- head/sbin/init/init.c Tue Feb 27 04:41:14 2018 (r330053) +++ head/sbin/init/init.c Tue Feb 27 10:54:15 2018 (r330054) @@ -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 @@ -1610,6 +1630,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 */