summary refs log tree commit diff
path: root/halt.c
diff options
context:
space:
mode:
Diffstat (limited to 'halt.c')
-rw-r--r--halt.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/halt.c b/halt.c
new file mode 100644
index 0000000..d6c52e6
--- /dev/null
+++ b/halt.c
@@ -0,0 +1,76 @@
+#include <errno.h>
+#include <unistd.h>
+#include <err.h>
+#include <string.h>
+#include <sys/reboot.h>
+
+extern char *__progname;
+
+typedef enum {NOOP, HALT, REBOOT, POWEROFF} action_t;
+
+int main(int argc, char *argv[]) {
+  int do_sync = 1;
+  int do_force = 0;
+  int opt;
+  action_t action = NOOP;
+
+  if (strcmp(__progname, "halt") == 0)
+    action = HALT;
+  else if (strcmp(__progname, "reboot") == 0)
+    action = REBOOT;
+  else if (strcmp(__progname, "poweroff") == 0)
+    action = POWEROFF;
+  else
+    warnx("no default behavior, needs to be called as halt/reboot/poweroff.");
+
+  while ((opt = getopt(argc, argv, "dfhinw")) != -1)
+    switch (opt) {
+    case 'n':
+      do_sync = 0;
+      break;
+    case 'w':
+      action = NOOP;
+      break;
+    case 'd':
+    case 'h':
+    case 'i':
+      /* silently ignored.  */
+      break;
+    case 'f':
+      do_force = 1;
+      break;
+    default:
+      errx(1, "Usage: %s [-n] [-f]", __progname);
+    }
+  
+  if (do_sync)
+    sync();
+
+  switch (action) {
+  case HALT:
+    if (do_force)
+      reboot(RB_HALT_SYSTEM);
+    else
+      execl("/bin/init", "init", "0", (char*)0);
+    err(1, "halt failed");
+    break;
+  case POWEROFF:
+    if (do_force)
+      reboot(RB_POWER_OFF);
+    else
+      execl("/bin/init", "init", "0", (char*)0);
+    err(1, "poweroff failed");
+    break;
+  case REBOOT:
+    if (do_force)
+      reboot(RB_AUTOBOOT);
+    else
+      execl("/bin/init", "init", "6", (char*)0);
+    err(1, "reboot failed");
+    break;
+  case NOOP:
+    break;
+  }
+
+  return 0;
+}