--- init.c.orig	Wed Jan  3 09:17:33 2007
+++ init.c	Wed Jan  3 10:08:38 2007
@@ -67,6 +67,7 @@
 #include <unistd.h>
 #include <sys/reboot.h>
 #include <err.h>
+#include <kenv.h>
 
 #include <stdarg.h>
 
@@ -115,6 +116,7 @@
 
 state_func_t single_user(void);
 state_func_t runcom(void);
+state_func_t runetcrc(int trychroot);
 state_func_t read_ttys(void);
 state_func_t multi_user(void);
 state_func_t clean_ttys(void);
@@ -175,12 +177,17 @@
 
 void clear_session_logs(session_t *);
 
+int shouldchroot(void);
+char init_chroot[PATH_MAX];
+int did_multiuser_chroot;
+
 int start_session_db(void);
 void add_session(session_t *);
 void del_session(session_t *);
 session_t *find_session(pid_t);
 DB *session_db;
 
+
 /*
  * The mother of all processes.
  */
@@ -718,6 +725,38 @@
 state_func_t
 runcom(void)
 {
+	state_func_t next_step;
+
+	/* Run /etc/rc and choose next state depending on the result. */
+	next_step = runetcrc(0);
+	if (next_step != (state_func_t) read_ttys)
+		return (state_func_t) next_step;
+
+	if (shouldchroot()) {
+		next_step = runetcrc(1);
+		if (next_step != (state_func_t) read_ttys)
+			return (state_func_t) next_step;
+
+		did_multiuser_chroot = 1;
+	} else {
+		did_multiuser_chroot = 0;
+	}
+
+	/*
+	 * Regardless of whether in chroot or not, we booted successfuly.
+	 * It's time to spawn gettys (ie. next_step's value at this point).
+	 */
+	runcom_mode = AUTOBOOT;		/* the default */
+	logwtmp("~", "reboot", "");
+	return (state_func_t) read_ttys;
+}
+
+/*
+ * Run the system startup script.
+ */
+state_func_t
+runetcrc(int trychroot)
+{
 	pid_t pid, wpid;
 	int status;
 	char *argv[4];
@@ -743,6 +782,12 @@
 
 		sigprocmask(SIG_SETMASK, &sa.sa_mask, (sigset_t *) 0);
 
+		if (trychroot)
+			if (chroot(init_chroot) != 0) {
+				warning("failed to chroot to `%s': %m",
+				    init_chroot);
+				_exit(1); 	/* force single user mode */
+			}
 #ifdef LOGIN_CAP
 		setprocresources(RESOURCE_RC);
 #endif
@@ -803,9 +848,6 @@
 	if (WEXITSTATUS(status))
 		return (state_func_t) single_user;
 
-	runcom_mode = AUTOBOOT;		/* the default */
-	/* NB: should send a message to the session logger to avoid blocking. */
-	logwtmp("~", "reboot", "");
 	return (state_func_t) read_ttys;
 }
 
@@ -1633,3 +1675,22 @@
 	}
 }
 #endif
+
+
+int shouldchroot(void) {
+	char icname[] = "init_chroot";
+	*init_chroot = '\0';
+
+	if(kenv(KENV_GET, icname, init_chroot, 
+           sizeof(init_chroot)) == -1) {
+		warning("Can't fetch init_chroot from kenv(): %m");
+		return 0;
+	}
+
+	if (chdir(init_chroot) != 0 || chroot(".") != 0) {
+		warning("Can't chroot to %s: %m", init_chroot);
+		return 0;
+	}
+
+	return 1;
+}
