From e069091227c58e0bb4f8bfb091f102f55f181f23 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Wed, 9 Aug 2023 22:52:22 +0200 Subject: [PATCH] readutmp: Return a boot time also on OpenBSD. * lib/readutmp.h (BOOT_TIME, USER_PROCESS): Provide fallback definitions. * lib/readutmp.c (read_utmp_from_file) [__OpenBSD__]: Fake a BOOT_TIME entry by looking at the time stamp of a specific file. --- ChangeLog | 6 ++++++ lib/readutmp.c | 36 ++++++++++++++++++++++++++++++++++++ lib/readutmp.h | 8 ++++++++ 3 files changed, 50 insertions(+) diff --git a/ChangeLog b/ChangeLog index c6e7001859..6fde91a679 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2023-08-09 Bruno Haible + readutmp: Return a boot time also on OpenBSD. + * lib/readutmp.h (BOOT_TIME, USER_PROCESS): Provide fallback + definitions. + * lib/readutmp.c (read_utmp_from_file) [__OpenBSD__]: Fake a BOOT_TIME + entry by looking at the time stamp of a specific file. + readutmp: Return a boot time also on Alpine Linux. * lib/readutmp.c: Include stat-time.h. (SIZEOF): New macro. diff --git a/lib/readutmp.c b/lib/readutmp.c index 2eb3395e0c..537846c144 100644 --- a/lib/readutmp.c +++ b/lib/readutmp.c @@ -496,6 +496,42 @@ read_utmp_from_file (char const *file, idx_t *n_entries, STRUCT_UTMP **utmp_buf, return -1; } +# if defined __OpenBSD__ + /* On OpenBSD, UTMP_FILE is not filled. It contains only dummy entries. + So, fake a BOOT_TIME entry, by getting the time stamp of a file that + gets touched only during the boot process. */ + if ((options & (READ_UTMP_USER_PROCESS | READ_UTMP_NO_BOOT_TIME)) == 0 + && strcmp (file, UTMP_FILE) == 0) + { + /* OpenBSD's 'struct utmp' does not have an ut_type field. */ + bool have_boot_time = false; + if (!have_boot_time) + { + const char * const boot_touched_files[] = + { + "/var/db/host.random", + "/var/run/utmp" + }; + for (idx_t i = 0; i < SIZEOF (boot_touched_files); i++) + { + const char *filename = boot_touched_files[i]; + struct stat statbuf; + if (stat (filename, &statbuf) >= 0) + { + struct timespec boot_time = get_stat_mtime (&statbuf); + a = add_utmp (a, options, + "reboot", strlen ("reboot"), + "", 0, + "", strlen (""), + "", 0, + 0, BOOT_TIME, boot_time, 0, 0, 0); + break; + } + } + } + } +# endif + # endif a = finish_utmp (a); diff --git a/lib/readutmp.h b/lib/readutmp.h index 88c0d94303..b74d37cde3 100644 --- a/lib/readutmp.h +++ b/lib/readutmp.h @@ -211,6 +211,14 @@ enum { UT_HOST_SIZE = -1 }; # define WTMP_FILE "/etc/wtmp" #endif +/* Some platforms, such as OpenBSD, don't have an ut_type field and don't have + the BOOT_TIME and USER_PROCESS macros. But we want to support them in + 'struct gl_utmp'. */ +#if !(HAVE_UTMPX_H ? HAVE_STRUCT_UTMPX_UT_TYPE : HAVE_STRUCT_UTMP_UT_TYPE) +# define BOOT_TIME 2 +# define USER_PROCESS 0 +#endif + /* Macros that test (UT)->ut_type. */ #ifdef BOOT_TIME # define UT_TYPE_BOOT_TIME(UT) UT_TYPE_EQ (UT, BOOT_TIME) -- 2.39.5