From 8045334f08798ea91e25875539efb3b430ed3e99 Mon Sep 17 00:00:00 2001 From: Leah Neukirchen Date: Thu, 5 Sep 2019 17:04:16 +0200 Subject: halt: add support for wtmp This implements -w and -d. Also add -B to create boot-time wtmp entries. --- halt.8 | 15 ++++++++++----- halt.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 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 -#include +#include +#include +#include +#include + #include +#include +#include #include -#include +#include +#include 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(); -- cgit 1.4.1