1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
|
From: Andrew Bower <andrew@bower.uk>
Date: Fri, 24 Oct 2025 22:44:48 +0100
Subject: Fix rendering of last -x split entries
Show shutdown and reboot entries in the correct order and apply time
constraints independently.
Bug-Debian: https://bugs.debian.org/1102105
Forwarded: https://github.com/thkukuk/wtmpdb/pull/40
Forwarded: https://github.com/thkukuk/wtmpdb/pull/41
Applied-Upstream: commit:826d94555f85bf670971b99ed3d1aebf2d27c5ab
Applied-Upstream: commit:b15135a72e2a35c139702acf741b0dd29865f322
---
src/wtmpdb.c | 93 ++++++++++++++++++++++++++++++++++++++----------------------
1 file changed, 59 insertions(+), 34 deletions(-)
diff --git a/src/wtmpdb.c b/src/wtmpdb.c
index 5ed1b61..56583d8 100644
--- a/src/wtmpdb.c
+++ b/src/wtmpdb.c
@@ -65,7 +65,7 @@ static char *wtmpdb_path = NULL;
#define LOGROTATE_DAYS 60
-/* lenght of login string cannot become longer */
+/* length of login string cannot become longer */
#define LAST_TIMESTAMP_LEN 32
static uint64_t wtmp_start = UINT64_MAX;
@@ -131,6 +131,12 @@ isipaddr (const char *string, int *addr_type,
return is_ip;
}
+static inline time_t
+from_usec(uint64_t usecs)
+{
+ return (time_t) usecs / USEC_PER_SEC;
+}
+
static int
parse_time (const char *str, time_t *arg)
{
@@ -409,9 +415,11 @@ print_entry (void *unused __attribute__((__unused__)),
int argc, char **argv, char **azColName)
{
char host_buf[NI_MAXHOST];
- char logintime[32]; /* LAST_TIMESTAMP_LEN */
- char logouttime[32]; /* LAST_TIMESTAMP_LEN */
- char length[32]; /* LAST_TIMESTAMP_LEN */
+ struct times_buf {
+ char login[LAST_TIMESTAMP_LEN];
+ char logout[LAST_TIMESTAMP_LEN];
+ char length[LAST_TIMESTAMP_LEN];
+ } times;
char *endptr;
uint64_t logout_t = 0;
static uint64_t newer_boot = 0;
@@ -444,17 +452,28 @@ print_entry (void *unused __attribute__((__unused__)),
fprintf (stderr, "Invalid numeric time entry for 'login': '%s'\n",
argv[3]);
+ if (argv[4])
+ {
+ logout_t = strtoull(argv[4], &endptr, 10);
+ if ((errno == ERANGE && logout_t == ULLONG_MAX)
+ || (endptr == argv[4]) || (*endptr != '\0'))
+ fprintf (stderr, "Invalid numeric time entry for 'logout': '%s'\n",
+ argv[4]);
+ }
+
if (login_t < wtmp_start)
wtmp_start = login_t;
- if (since && (since > (time_t)(login_t/USEC_PER_SEC)))
- return 0;
-
- if (until && (until < (time_t)(login_t/USEC_PER_SEC)))
- return 0;
+ int swap = type == xflag && BOOT_TIME && logout_t != 0;
- if (present && (present < (time_t)(login_t/USEC_PER_SEC)))
- return 0;
+ if ((since && since > from_usec(swap ? logout_t : login_t)) ||
+ (until && until < from_usec(login_t)) ||
+ (present && present < from_usec(login_t)))
+ {
+ if (xflag && (type == BOOT_TIME))
+ newer_boot = login_t;
+ return 0;
+ }
if (match)
{
@@ -470,10 +489,10 @@ print_entry (void *unused __attribute__((__unused__)),
return 0;
}
- format_time (login_fmt, logintime, sizeof (logintime),
+ format_time (login_fmt, times.login, sizeof (times.login),
login_t/USEC_PER_SEC);
- if (argv[4])
+ if (logout_t != 0)
{
logout_t = strtoull(argv[4], &endptr, 10);
if ((errno == ERANGE && logout_t == ULLONG_MAX)
@@ -485,17 +504,17 @@ print_entry (void *unused __attribute__((__unused__)),
((time_t)(logout_t/USEC_PER_SEC) < present))
return 0;
- format_time (logout_fmt, logouttime, sizeof (logouttime),
+ format_time (logout_fmt, times.logout, sizeof (times.logout),
logout_t/USEC_PER_SEC);
- calc_time_length (length, sizeof(length), login_t, logout_t);
+ calc_time_length (times.length, sizeof(times.length), login_t, logout_t);
}
else /* login but no logout */
{
if (after_reboot)
{
- snprintf (logouttime, sizeof (logouttime), "crash");
- length[0] = '\0';
+ snprintf (times.logout, sizeof (times.logout), "crash");
+ times.length[0] = '\0';
}
else
{
@@ -504,30 +523,30 @@ print_entry (void *unused __attribute__((__unused__)),
case USER_PROCESS:
if (logout_fmt == TIMEFMT_HHMM)
{
- snprintf (logouttime, sizeof (logouttime), "still");
- snprintf(length, sizeof(length), "logged in");
+ snprintf (times.logout, sizeof (times.logout), "still");
+ snprintf(times.length, sizeof(times.length), "logged in");
}
else
{
- snprintf (logouttime, sizeof (logouttime), "still logged in");
- length[0] = '\0';
+ snprintf (times.logout, sizeof (times.logout), "still logged in");
+ times.length[0] = '\0';
}
break;
case BOOT_TIME:
if (logout_fmt == TIMEFMT_HHMM)
{
- snprintf (logouttime, sizeof (logouttime), "still");
- snprintf(length, sizeof(length), "running");
+ snprintf (times.logout, sizeof (times.logout), "still");
+ snprintf(times.length, sizeof(times.length), "running");
}
else
{
- snprintf (logouttime, sizeof (logouttime), "still running");
- length[0] = '\0';
+ snprintf (times.logout, sizeof (times.logout), "still running");
+ times.length[0] = '\0';
}
break;
default:
- snprintf (logouttime, sizeof (logouttime), "ERROR");
- snprintf(length, sizeof(length), "Unknown: %d", type);
+ snprintf (times.logout, sizeof (times.logout), "ERROR");
+ snprintf(times.length, sizeof(times.length), "Unknown: %d", type);
break;
}
}
@@ -595,22 +614,28 @@ print_entry (void *unused __attribute__((__unused__)),
}
}
- print_line (user, tty, host, print_service, logintime, logouttime, length);
-
if (xflag && (type == BOOT_TIME) && newer_boot != 0 && logout_t != 0)
{
- format_time (login_fmt, logintime, sizeof (logintime),
+ struct times_buf shutdown;
+
+ format_time (login_fmt, shutdown.login, sizeof (shutdown.login),
logout_t/USEC_PER_SEC);
- format_time (logout_fmt, logouttime, sizeof (logouttime),
+ format_time (logout_fmt, shutdown.logout, sizeof (shutdown.logout),
newer_boot/USEC_PER_SEC);
- calc_time_length (length, sizeof(length), logout_t, newer_boot);
+ calc_time_length (shutdown.length, sizeof(shutdown.length), logout_t, newer_boot);
- print_line ("shutdown", "system down", host, print_service,
- logintime, logouttime, length);
+ if ((!until || until >= from_usec(logout_t)) &&
+ (!since || since <= from_usec(logout_t)))
+ print_line ("shutdown", "system down", host, print_service,
+ shutdown.login, shutdown.logout, shutdown.length);
}
if (xflag && (type == BOOT_TIME))
newer_boot = login_t;
+ if ((!until || until >= from_usec(login_t)) &&
+ (!since || since <= from_usec(login_t)))
+ print_line (user, tty, host, print_service, times.login, times.logout, times.length);
+
free (print_service);
currentry++;
|