about summary refs log tree commit diff
path: root/halt.c
diff options
context:
space:
mode:
Diffstat (limited to 'halt.c')
-rw-r--r--halt.c55
1 files changed, 50 insertions, 5 deletions
diff --git a/halt.c b/halt.c
index 9ea75bc..7241d42 100644
--- a/halt.c
+++ b/halt.c
@@ -1,16 +1,53 @@
-#include <errno.h>
-#include <unistd.h>
+#include <sys/reboot.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+
 #include <err.h>
+#include <errno.h>
+#include <fcntl.h>
 #include <string.h>
-#include <sys/reboot.h>
+#include <unistd.h>
+#include <utmp.h>
 
 extern char *__progname;
 
 typedef enum {NOOP, HALT, REBOOT, POWEROFF} action_type;
 
+#ifndef OUR_WTMP
+#define OUR_WTMP "/var/log/wtmp"
+#endif
+
+void write_wtmp(int boot) {
+  int fd;
+
+  if ((fd = open(OUR_WTMP, O_WRONLY|O_APPEND)) < 0)
+    return;
+
+  struct utmp utmp = {0};
+  struct utsname uname_buf;
+  struct timeval tv;
+
+  gettimeofday(&tv, 0);
+  utmp.ut_tv.tv_sec = tv.tv_sec;
+  utmp.ut_tv.tv_usec = tv.tv_usec;
+
+  utmp.ut_type = boot ? BOOT_TIME : RUN_LVL;
+
+  strncpy(utmp.ut_name, boot ? "reboot" : "shutdown", sizeof(utmp.ut_name));
+  strncpy(utmp.ut_id , "~~", sizeof(utmp.ut_id));
+  strncpy(utmp.ut_line, boot ? "~" : "~~", sizeof(utmp.ut_line));
+  if (uname(&uname_buf) == 0)
+    strncpy(utmp.ut_host, uname_buf.release, sizeof(utmp.ut_host));
+
+  write(fd, (char *)&utmp, sizeof(utmp));
+  close(fd);
+}
+
 int main(int argc, char *argv[]) {
   int do_sync = 1;
   int do_force = 0;
+  int do_wtmp = 1;
   int opt;
   action_type action = NOOP;
 
@@ -23,7 +60,7 @@ int main(int argc, char *argv[]) {
   else
     warnx("no default behavior, needs to be called as halt/reboot/poweroff.");
 
-  while ((opt = getopt(argc, argv, "dfhinw")) != -1)
+  while ((opt = getopt(argc, argv, "dfhinwB")) != -1)
     switch (opt) {
     case 'n':
       do_sync = 0;
@@ -33,6 +70,8 @@ int main(int argc, char *argv[]) {
       do_sync = 0;
       break;
     case 'd':
+      do_wtmp = 0;
+      break;
     case 'h':
     case 'i':
       /* silently ignored.  */
@@ -40,10 +79,16 @@ int main(int argc, char *argv[]) {
     case 'f':
       do_force = 1;
       break;
+    case 'B':
+      write_wtmp(1);
+      return 0;
     default:
-      errx(1, "Usage: %s [-n] [-f]", __progname);
+      errx(1, "Usage: %s [-n] [-f] [-d] [-w] [-B]", __progname);
     }
 
+  if (do_wtmp)
+    write_wtmp(0);
+
   if (do_sync)
     sync();