From owner-svn-src-head@FreeBSD.ORG Wed Mar 14 16:22:09 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id EC56A1065672; Wed, 14 Mar 2012 16:22:09 +0000 (UTC) (envelope-from ed@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id D12508FC1A; Wed, 14 Mar 2012 16:22:09 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q2EGM9Ga021412; Wed, 14 Mar 2012 16:22:09 GMT (envelope-from ed@svn.freebsd.org) Received: (from ed@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q2EGM9HR021407; Wed, 14 Mar 2012 16:22:09 GMT (envelope-from ed@svn.freebsd.org) Message-Id: <201203141622.q2EGM9HR021407@svn.freebsd.org> From: Ed Schouten Date: Wed, 14 Mar 2012 16:22:09 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r232977 - in head: etc sbin/init X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 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: Wed, 14 Mar 2012 16:22:10 -0000 Author: ed Date: Wed Mar 14 16:22:09 2012 New Revision: 232977 URL: http://svn.freebsd.org/changeset/base/232977 Log: Make init(8) slightly more robust when /dev/console is missing. If the environment doesn't offer a working /dev/console, the existing version of init(8) will simply refuse running rc(8) scripts. This means you'll only have a system running init(8) and nothing else. Change the code to do the following: - Open /dev/console like we used to do, but make it more robust to use O_NONBLOCK to prevent blocking on a carrier. - If this fails, use /dev/null as stdin and /var/log/init.log as stdout and stderr. - If even this fails, use /dev/null as stdin, stdout and stderr. So why us this useful? Well, if you remove the `getpid() == 1' check in main(), you can now use init(8) inside jails to properly execute rc(8). It still requires some polishing, as existing tools assume init(8) has PID 1. Also it is now possible to use use init(8) on `headless' devices that don't even have a serial boot console. Modified: head/etc/newsyslog.conf head/sbin/init/init.8 head/sbin/init/init.c head/sbin/init/pathnames.h Modified: head/etc/newsyslog.conf ============================================================================== --- head/etc/newsyslog.conf Wed Mar 14 16:10:39 2012 (r232976) +++ head/etc/newsyslog.conf Wed Mar 14 16:22:09 2012 (r232977) @@ -24,6 +24,7 @@ /var/log/cron 600 3 100 * JC /var/log/daily.log 640 7 * @T00 JN /var/log/debug.log 600 7 100 * JC +/var/log/init.log 644 3 100 * J /var/log/kerberos.log 600 7 100 * J /var/log/lpd-errs 644 7 100 * JC /var/log/maillog 640 7 * @T00 JC Modified: head/sbin/init/init.8 ============================================================================== --- head/sbin/init/init.8 Wed Mar 14 16:10:39 2012 (r232976) +++ head/sbin/init/init.8 Wed Mar 14 16:22:09 2012 (r232977) @@ -31,7 +31,7 @@ .\" @(#)init.8 8.3 (Berkeley) 4/18/94 .\" $FreeBSD$ .\" -.Dd February 11, 2012 +.Dd March 14, 2012 .Dt INIT 8 .Os .Sh NAME @@ -293,22 +293,22 @@ as follows: file .El .Sh FILES -.Bl -tag -width /etc/rc.shutdown -compact +.Bl -tag -width /var/log/init.log -compact .It Pa /dev/console system console device .It Pa /dev/tty* terminal ports found in .Xr ttys 5 -.It Pa /var/run/utx.active -record of current users on the system -.It Pa /var/log/utx.log -record of all logins and logouts .It Pa /etc/ttys the terminal initialization information file .It Pa /etc/rc system startup commands .It Pa /etc/rc.shutdown system shutdown commands +.It Pa /var/log/init.log +log of +.Xr rc 8 +output if the system console device is not available .El .Sh DIAGNOSTICS .Bl -diag Modified: head/sbin/init/init.c ============================================================================== --- head/sbin/init/init.c Wed Mar 14 16:10:39 2012 (r232976) +++ head/sbin/init/init.c Wed Mar 14 16:22:09 2012 (r232977) @@ -138,7 +138,7 @@ static void transition(state_t); static state_t requested_transition; static state_t current_state = death_single; -static void setctty(const char *); +static void open_console(void); static const char *get_shell(void); static void write_stderr(const char *message); @@ -568,19 +568,35 @@ transition(state_t s) * Only called by children of init after forking. */ static void -setctty(const char *name) +open_console(void) { int fd; - revoke(name); - if ((fd = open(name, O_RDWR)) == -1) { - stall("can't open %s: %m", name); - _exit(1); + /* Try to open /dev/console. */ + revoke(_PATH_CONSOLE); + if ((fd = open(_PATH_CONSOLE, O_RDWR | O_NONBLOCK)) != -1) { + if (login_tty(fd) == 0) + return; + close(fd); } - if (login_tty(fd) == -1) { - stall("can't get %s for controlling terminal: %m", name); + + /* No luck. Log output to file if possible. */ + if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) { + stall("cannot open null device."); _exit(1); } + if (fd != STDIN_FILENO) { + dup2(fd, STDIN_FILENO); + close(fd); + } + fd = open(_PATH_INITLOG, O_WRONLY | O_APPEND | O_CREAT, 0644); + if (fd == -1) + dup2(STDIN_FILENO, STDOUT_FILENO); + else if (fd != STDOUT_FILENO) { + dup2(fd, STDOUT_FILENO); + close(fd); + } + dup2(STDOUT_FILENO, STDERR_FILENO); } static const char * @@ -638,7 +654,7 @@ single_user(void) /* * Start the single user session. */ - setctty(_PATH_CONSOLE); + open_console(); #ifdef SECURE /* @@ -798,7 +814,7 @@ run_script(const char *script) sigaction(SIGTSTP, &sa, (struct sigaction *)0); sigaction(SIGHUP, &sa, (struct sigaction *)0); - setctty(_PATH_CONSOLE); + open_console(); char _sh[] = "sh"; char _autoboot[] = "autoboot"; @@ -1572,7 +1588,7 @@ runshutdown(void) sigaction(SIGTSTP, &sa, (struct sigaction *)0); sigaction(SIGHUP, &sa, (struct sigaction *)0); - setctty(_PATH_CONSOLE); + open_console(); char _sh[] = "sh"; char _reboot[] = "reboot"; Modified: head/sbin/init/pathnames.h ============================================================================== --- head/sbin/init/pathnames.h Wed Mar 14 16:10:39 2012 (r232976) +++ head/sbin/init/pathnames.h Wed Mar 14 16:22:09 2012 (r232977) @@ -35,6 +35,7 @@ #include +#define _PATH_INITLOG "/var/log/init.log" #define _PATH_SLOGGER "/sbin/session_logger" #define _PATH_RUNCOM "/etc/rc" #define _PATH_RUNDOWN "/etc/rc.shutdown"