summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--halt.815
-rw-r--r--halt.c55
2 files changed, 60 insertions, 10 deletions
diff --git a/halt.8 b/halt.8
index 8930ad3..47d9020 100644
--- a/halt.8
+++ b/halt.8
@@ -1,4 +1,4 @@
-.Dd July 29, 2014
+.Dd September 5, 2019
 .Dt HALT 8
 .Os Linux
 .Sh NAME
@@ -10,6 +10,9 @@
 .Nm halt
 .Op Fl n
 .Op Fl f
+.Op Fl d
+.Op Fl w
+.Op Fl B
 .Nm reboot
 .Op Fl n
 .Op Fl f
@@ -40,6 +43,12 @@ Force halt or reboot, don't call
 .Xr init 8 .
 This is
 .Sy dangerous !
+.It Fl d
+Do not write the wtmp record.
+.It Fl w
+Just write the wtmp record.
+.It Fl B
+Just write the wtmp record, but for a boot.
 .El
 .Sh UNSUPPORTED OPTIONS
 This version of
@@ -50,10 +59,6 @@ the following features are
 .Sy not
 supported and silently ignored:
 .Bl -tag -width indent
-.It Fl w
-to just write the wtmp record.
-.It Fl d
-to not write the wtmp record.
 .It Fl h
 to put hard drives in standby mode.
 .It Fl i
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();