changeset 34:c1f4f9101af7

Add oneit.
author Rob Landley <rob@landley.net>
date Sat, 25 Nov 2006 13:48:02 -0500
parents bc91b57308dc
children f2c7f0799ebe
files toys/Config.in toys/oneit.c toys/toylist.h
diffstat 3 files changed, 62 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/toys/Config.in	Sat Nov 25 13:45:39 2006 -0500
+++ b/toys/Config.in	Sat Nov 25 13:48:02 2006 -0500
@@ -34,6 +34,22 @@
 	help
 	  A hello world program.  You don't need this.
 
+config ONEIT
+	bool "oneit"
+	default n
+	help
+	  usage: oneit [-p] command [...]
+
+	  A simple init program that runs a single supplied command line with a
+	  controlling tty (so CTRL-C can kill it).
+
+	  -p	Power off instead of rebooting when command exits.
+
+	  The oneit command runs the supplied command line as a child process
+	  (because PID 1 has signals blocked), attached to /dev/tty0, in its
+	  own session.  Then oneit reaps zombies until the child exits, at
+	  which point it reboots (or with -p, powers off) the system.
+
 config PWD
 	bool "pwd"
 	default n
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/oneit.c	Sat Nov 25 13:48:02 2006 -0500
@@ -0,0 +1,45 @@
+/* oneit.c, tiny one-process init replacement.
+ *
+ * Copyright 2005 by Rob Landley <rob@landley.net>.
+ */
+
+#include "toys.h"
+#include <sys/reboot.h>
+
+// The minimum amount of work necessary to get ctrl-c and such to work is:
+//
+// - Fork a child (PID 1 is special: can't exit, has various signals blocked).
+// - Do a setsid() (so we have our own session).
+// - In the child, attach stdio to /dev/tty0 (/dev/console is special)
+// - Exec the rest of the command line.
+//
+// PID 1 then reaps zombies until the child process it spawned exits, at which
+// point it calls sync() and reboot().  I could stick a kill -1 in there.
+
+int oneit_main(void)
+{
+  int i;
+  pid_t pid;
+
+  // Create a new child process.
+  pid = vfork();
+  if (pid) {
+
+    // pid 1 just reaps zombies until it gets its child, then halts the system.
+    while (pid!=wait(&i));
+    sync();
+    reboot(toys.optflags ? RB_POWER_OFF : RB_AUTOBOOT);
+  }
+    
+  // Redirect stdio to /dev/tty0, with new session ID, so ctrl-c works.
+  setsid();
+  for (i=0; i<3; i++) {
+    close(i);
+    open("/dev/tty0",O_RDWR);
+  }
+
+  // Can't xexec() here because we vforked so we don't want to error_exit().
+  toy_exec(toys.optargs);
+  execvp(*toys.optargs, toys.optargs);
+  _exit(127);
+}
--- a/toys/toylist.h	Sat Nov 25 13:45:39 2006 -0500
+++ b/toys/toylist.h	Sat Nov 25 13:48:02 2006 -0500
@@ -57,6 +57,7 @@
 USE_DF(NEWTOY(df, "Pkt*a", TOYFLAG_USR|TOYFLAG_SBIN))
 USE_TOYSH(NEWTOY(exit, NULL, TOYFLAG_NOFORK))
 USE_HELLO(NEWTOY(hello, NULL, TOYFLAG_NOFORK|TOYFLAG_USR))
+USE_ONEIT(NEWTOY(oneit, "+p<1", TOYFLAG_SBIN))
 USE_PWD(NEWTOY(pwd, NULL, TOYFLAG_BIN))
 USE_TOYSH(OLDTOY(sh, toysh, "c:i", TOYFLAG_BIN))
 USE_TOYSH(NEWTOY(toysh, "c:i", TOYFLAG_BIN))