Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 14 Mar 2012 16:22:09 +0000 (UTC)
From:      Ed Schouten <ed@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r232977 - in head: etc sbin/init
Message-ID:  <201203141622.q2EGM9HR021407@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <paths.h>
 
+#define	_PATH_INITLOG	"/var/log/init.log"
 #define	_PATH_SLOGGER	"/sbin/session_logger"
 #define	_PATH_RUNCOM	"/etc/rc"
 #define _PATH_RUNDOWN   "/etc/rc.shutdown"



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201203141622.q2EGM9HR021407>