Thanks for doing all that work. I looked into it, and found a problem: a
command like "who /var/log/wtmp" stops working because the systemd
emulation of read_utmp only supports plain "who" (rougnly equivalent to
"who /var/run/utmp" on Fedora). So I installed it into coreutils, but
the default is systemd is disabled. This should give people time to
experiment with it.
Thorsten, is there some way to get the equivalent of /var/log/wtmp with
systemd?
Also, I simplified the use of the new readutmp interface a bit, by going
back to the old way where you simply call 'free' once to free the
storage. Although I toyed with the idea of simplifying readutmp.h
further, by moving most of it into readutmp.c and having just struct
gl_utmp public (this would simplify coreutils quite a bit), I ran out of
time and patience and decided to ship what I had. So I nstalled the
first ten attached patches into Gnulib, and the last patch into coreutils.
I haven't tested this with the latest systemd so there could well be
typos in that part of the code.From 39a4cb0afdf4f2a1e6c2f3176b84e5b4cfe8996d Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Thu, 3 Aug 2023 15:31:48 -0700
Subject: [PATCH 1/9] readutmp: simplify extract_trimmed_name via ximemdup0
* lib/readutmp.c (extract_trimmed_name): Simplify.
* modules/readutmp (Depends-on):
Add strnlen, which was a missing dependency.
* lib/readutmp.c: Include xmemdup0.
(extract_trimmed_name): Simplify.
* modules/readutmp (Depends-on): Add xmemdup0.
Add strnlen, which was a missing dependency already.
---
ChangeLog | 7 +++++++
lib/readutmp.c | 28 +++++++++++-----------------
modules/readutmp | 1 +
3 files changed, 19 insertions(+), 17 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index b84cece6ff..7fa4e7b64a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2023-08-03 Paul Eggert <egg...@cs.ucla.edu>
+
+ readutmp: simplify extract_trimmed_name via ximemdup0
+ * lib/readutmp.c (extract_trimmed_name): Simplify.
+ * modules/readutmp (Depends-on):
+ Add strnlen, which was a missing dependency.
+
2023-08-03 Bruno Haible <br...@clisp.org>
alignasof, stdalign: Avoid some -Wundef warnings from config.h.
diff --git a/lib/readutmp.c b/lib/readutmp.c
index 11dd1655c5..9057a36494 100644
--- a/lib/readutmp.c
+++ b/lib/readutmp.c
@@ -47,29 +47,23 @@
# pragma GCC diagnostic ignored "-Wsizeof-pointer-memaccess"
#endif
+/* Work around <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109614>. */
+#if 11 <= __GNUC__
+# pragma GCC diagnostic ignored "-Wstringop-overread"
+#endif
+
/* Copy UT_USER (UT) into storage obtained from malloc. Then remove any
trailing spaces from the copy, NUL terminate it, and return the copy. */
char *
extract_trimmed_name (const STRUCT_UTMP *ut)
{
- char *p, *trimmed_name;
-
-#if READUTMP_USE_SYSTEMD
- trimmed_name = xstrdup (UT_USER (ut));
-#else
- trimmed_name = xmalloc (UT_USER_SIZE + 1);
- strncpy (trimmed_name, UT_USER (ut), UT_USER_SIZE);
- /* Append a trailing NUL. Some systems pad names shorter than the
- maximum with spaces, others pad with NULs. */
- trimmed_name[UT_USER_SIZE] = '\0';
-#endif
- /* Remove any trailing spaces. */
- for (p = trimmed_name + strlen (trimmed_name);
- trimmed_name < p && p[-1] == ' ';
- *--p = '\0')
- ;
- return trimmed_name;
+ char const *name = UT_USER (ut);
+ idx_t len = strnlen (name, UT_USER_SIZE);
+ char const *p;
+ for (p = name + len; name < p && p[-1] == ' '; p--)
+ continue;
+ return ximemdup0 (name, p - name);
}
#if READ_UTMP_SUPPORTED
diff --git a/modules/readutmp b/modules/readutmp
index 04893a4487..484edd1842 100644
--- a/modules/readutmp
+++ b/modules/readutmp
@@ -12,6 +12,7 @@ extensions
xalloc
stdbool
stdint
+strnlen
sys_time
fopen-gnu
unlocked-io-internal
--
2.39.2
From 1ccde926759e8638d4b86de3dabbd948ad921edc Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Thu, 3 Aug 2023 15:53:27 -0700
Subject: [PATCH 2/9] =?UTF-8?q?readutmp:=20go=20back=20to=20simple=20?=
=?UTF-8?q?=E2=80=98free=E2=80=99?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Omit the new free_utmp function. Instead, allocate storage
in one block, so that using code can still just call ‘free’.
* lib/readutmp.c (struct utmp_alloc) [READUTMP_USE_SYSTEMD]: New type.
(add_utmp) [READUTMP_USE_SYSTEMD]: New function.
(read_utmp) [READUTMP_USE_SYSTEMD]: Use it.
Also, use malloc a bit less heavily.
(free_utmp): Remove.
* tests/test-readutmp.c (main): Call free, not free_utmp.
---
ChangeLog | 10 ++
NEWS | 4 +-
lib/readutmp.c | 285 +++++++++++++++++++++++-------------------
lib/readutmp.h | 4 -
tests/test-readutmp.c | 4 +-
5 files changed, 167 insertions(+), 140 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 7fa4e7b64a..56b27d129f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
2023-08-03 Paul Eggert <egg...@cs.ucla.edu>
+ readutmp: go back to simple ‘free’
+ Omit the new free_utmp function. Instead, allocate storage
+ in one block, so that using code can still just call ‘free’.
+ * lib/readutmp.c (struct utmp_alloc) [READUTMP_USE_SYSTEMD]: New type.
+ (add_utmp) [READUTMP_USE_SYSTEMD]: New function.
+ (read_utmp) [READUTMP_USE_SYSTEMD]: Use it.
+ Also, use malloc a bit less heavily.
+ (free_utmp): Remove.
+ * tests/test-readutmp.c (main): Call free, not free_utmp.
+
readutmp: simplify extract_trimmed_name via ximemdup0
* lib/readutmp.c (extract_trimmed_name): Simplify.
* modules/readutmp (Depends-on):
diff --git a/NEWS b/NEWS
index 87d49ffbe2..24139d4660 100644
--- a/NEWS
+++ b/NEWS
@@ -74,8 +74,8 @@ User visible incompatible changes
Date Modules Changes
-2023-08-01 readutmp After processing the read_utmp() results, call
- free_utmp() in order to avoid a memory leak.
+2023-08-01 readutmp Some STRUCT_UTMP members can be char *,
+ rather than fixed-length char arrays.
Link additionally with $(READUTMP_LIB).
2023-07-10 dfa The signature of the function
diff --git a/lib/readutmp.c b/lib/readutmp.c
index 9057a36494..508978ba79 100644
--- a/lib/readutmp.c
+++ b/lib/readutmp.c
@@ -223,34 +223,92 @@ guess_pty_name (uid_t uid, const struct timespec at)
return NULL;
}
+/* A memory allocation for an in-progress read_utmp. */
+
+struct utmp_alloc
+{
+ /* A pointer to a possibly-empty array of utmp entries,
+ followed by a possibly-empty sequence of unused bytes,
+ followed by a possibly-empty sequence of string bytes.
+ UTMP is either null or allocated by malloc. */
+ STRUCT_UTMP *utmp;
+
+ /* The number of utmp entries. */
+ idx_t filled;
+
+ /* The string byte sequence length. Strings are null-terminated. */
+ idx_t string_bytes;
+
+ /* The total number of bytes allocated. This equals
+ FILLED * sizeof *UTMP + [size of free area] + STRING_BYTES. */
+ idx_t alloc_bytes;
+};
+
+/* Use the memory allocation A, and if the read_utmp options OPTIONS
+ permit it, add a new entry with the given USER, etc. Grow A as
+ needed, reporting an error and exit on memory allocation failure.
+ Return the resulting memory allocation. */
+
+static struct utmp_alloc
+add_utmp (struct utmp_alloc a, int options,
+ char const *user, char const *id, char const *line, pid_t pid,
+ short type, struct timeval t, char const *host, long session)
+{
+ if (!user) user = "";
+ if (!host) host = "";
+ int entry_bytes = sizeof (STRUCT_UTMP);
+ idx_t usersize = strlen (user) + 1, idsize = strlen (id) + 1,
+ linesize = strlen (line) + 1, hostsize = strlen (host) + 1;
+ idx_t avail = a.alloc_bytes - (entry_bytes * a.filled + a.string_bytes);
+ idx_t needed_string_bytes = usersize + idsize + linesize + hostsize;
+ idx_t needed = entry_bytes + needed_string_bytes;
+ if (avail < needed)
+ {
+ idx_t old_string_offset = a.alloc_bytes - a.string_bytes;
+ void *new = xpalloc (a.utmp, &a.alloc_bytes, needed - avail, -1, 1);
+ idx_t new_string_offset = a.alloc_bytes - a.string_bytes;
+ a.utmp = new;
+ char *q = new;
+ memmove (q + new_string_offset, q + old_string_offset, a.string_bytes);
+ }
+ STRUCT_UTMP *ut = &a.utmp[a.filled];
+ char *stringlim = (char *) a.utmp + a.alloc_bytes;
+ char *p = stringlim - a.string_bytes;
+ ut->ut_user = p = memcpy (p - usersize, user, usersize);
+ ut->ut_id = p = memcpy (p - idsize, id, idsize);
+ ut->ut_line = p = memcpy (p - linesize, line, linesize);
+ ut->ut_pid = pid;
+ ut->ut_type = type;
+ ut->ut_tv = t;
+ ut->ut_host = memcpy (p - hostsize, line, hostsize);
+ ut->ut_session = session;
+ if (desirable_utmp_entry (ut, options))
+ {
+ /* Now that UT has been checked, relocate its string slots to be
+ relative to the end of the allocated storage, so that these
+ slots survive realloc. The slots will be relocated back just
+ before read_utmp returns. */
+ ut->ut_user = (char *) (intptr_t) (ut->ut_user - stringlim);
+ ut->ut_id = (char *) (intptr_t) (ut->ut_id - stringlim);
+ ut->ut_line = (char *) (intptr_t) (ut->ut_line - stringlim);
+ ut->ut_host = (char *) (intptr_t) (ut->ut_host - stringlim);
+ a.filled++;
+ a.string_bytes += needed_string_bytes;
+ }
+ return a;
+}
+
int
read_utmp (char const *file, size_t *n_entries, STRUCT_UTMP **utmp_buf,
int options)
{
- /* Fill entries, simulating what an utmp file would contain. */
- idx_t n_filled = 0;
- idx_t n_alloc = 0;
- STRUCT_UTMP *utmp = NULL;
+ /* Fill entries, simulating what a utmp file would contain. */
+ struct utmp_alloc a = {0};
/* Synthesize a BOOT_TIME entry. */
if (!(options & READ_UTMP_USER_PROCESS))
- {
- if (n_filled == n_alloc)
- utmp = xpalloc (utmp, &n_alloc, 1, -1, sizeof (STRUCT_UTMP));
- STRUCT_UTMP *ut = &utmp[n_filled];
- ut->ut_user = xstrdup ("reboot");
- ut->ut_id = xstrdup ("");
- ut->ut_line = xstrdup ("~");
- ut->ut_pid = 0;
- ut->ut_type = BOOT_TIME;
- ut->ut_tv = get_boot_time ();
- ut->ut_host = xstrdup ("");
- ut->ut_session = 0;
- if (desirable_utmp_entry (ut, options))
- n_filled++;
- else
- free_utmp (1, ut);
- }
+ a = add_utmp (a, options, "reboot", "", "~", 0,
+ BOOT_TIME, get_boot_time (), "", 0);
/* Synthesize USER_PROCESS entries. */
char **sessions;
@@ -273,48 +331,46 @@ read_utmp (char const *file, size_t *n_entries, STRUCT_UTMP **utmp_buf,
if (sd_session_get_seat (session, &seat) < 0)
seat = NULL;
+ char missing_type[] = "";
+ char *type = NULL;
char *tty;
if (sd_session_get_tty (session, &tty) < 0)
{
tty = NULL;
/* Try harder to get a sensible value for the tty. */
- char *type;
- if (sd_session_get_type (session, &type) >= 0)
+ if (sd_session_get_type (session, &type) < 0)
+ type = missing_type;
+ if (strcmp (type, "tty") == 0)
{
- if (strcmp (type, "tty") == 0)
- {
- char *service;
- if (sd_session_get_service (session, &service) < 0)
- service = NULL;
+ char *service;
+ if (sd_session_get_service (session, &service) < 0)
+ service = NULL;
- char *pty;
- uid_t uid;
- if (sd_session_get_uid (session, &uid) >= 0)
- {
- struct timespec start_ts =
- {
- .tv_sec = start_tv.tv_sec,
- .tv_nsec = start_tv.tv_usec * 1000
- };
- pty = guess_pty_name (uid, start_ts);
- }
- else
- pty = NULL;
-
- if (service != NULL && pty != NULL)
+ char *pty;
+ uid_t uid;
+ if (sd_session_get_uid (session, &uid) >= 0)
+ {
+ struct timespec start_ts =
{
- tty = xmalloc (strlen (service) + 1 + strlen (pty) + 1);
- stpcpy (stpcpy (stpcpy (tty, service), " "), pty);
- }
- else if (service != NULL)
- tty = xstrdup (service);
- else if (pty != NULL)
- tty = xstrdup (pty);
+ .tv_sec = start_tv.tv_sec,
+ .tv_nsec = start_tv.tv_usec * 1000
+ };
+ pty = guess_pty_name (uid, start_ts);
+ }
+ else
+ pty = NULL;
+ if (service != NULL && pty != NULL)
+ {
+ tty = xmalloc (strlen (service) + 1 + strlen (pty) + 1);
+ stpcpy (stpcpy (stpcpy (tty, service), " "), pty);
free (pty);
free (service);
}
- free (type);
+ else if (service != NULL)
+ tty = service;
+ else if (pty != NULL)
+ tty = pty;
}
}
@@ -324,92 +380,60 @@ read_utmp (char const *file, size_t *n_entries, STRUCT_UTMP **utmp_buf,
{
char *user;
if (sd_session_get_username (session, &user) < 0)
- user = xstrdup ("");
+ user = NULL;
pid_t leader_pid;
if (sd_session_get_leader (session, &leader_pid) < 0)
leader_pid = 0;
+ char *host;
char *remote_host;
if (sd_session_get_remote_host (session, &remote_host) < 0)
- remote_host = NULL;
- char *remote_user;
- if (sd_session_get_remote_user (session, &remote_user) < 0)
- remote_user = NULL;
- char *host;
- if (remote_host != NULL)
{
- if (remote_user != NULL)
+ host = NULL;
+ /* For backward compatibility, put the X11 display into the
+ host field. */
+ if (!type && sd_session_get_type (session, &type) < 0)
+ type = missing_type;
+ if (strcmp (type, "x11") == 0)
{
- host = xmalloc (strlen (remote_user) + 1 + strlen (remote_host) + 1);
- stpcpy (stpcpy (stpcpy (host, remote_user), "@"), remote_host);
+ char *display;
+ if (sd_session_get_display (session, &display) < 0)
+ display = NULL;
+ host = display;
}
- else
- host = xstrdup (remote_host);
}
else
{
- host = NULL;
- /* For backward compatibility, put the X11 display into the
- host field. */
- char *type;
- if (sd_session_get_type (session, &type) >= 0)
+ char *remote_user;
+ if (sd_session_get_remote_user (session, &remote_user) < 0)
+ host = remote_host;
+ else
{
- if (strcmp (type, "x11") == 0)
- {
- char *display;
- if (sd_session_get_display (session, &display) < 0)
- display = NULL;
- host = display;
- }
- free (type);
+ host = xmalloc (strlen (remote_user) + 1
+ + strlen (remote_host) + 1);
+ stpcpy (stpcpy (stpcpy (host, remote_user), "@"),
+ remote_host);
+ free (remote_user);
+ free (remote_host);
}
- if (host == NULL)
- host = xstrdup ("");
}
- size_t n_filled_after = n_filled + (seat != NULL) + (tty != NULL);
- if (n_filled_after > n_alloc)
- utmp = xpalloc (utmp, &n_alloc, n_filled_after - n_alloc, -1,
- sizeof (STRUCT_UTMP));
if (seat != NULL)
- {
- STRUCT_UTMP *ut = &utmp[n_filled];
- ut->ut_user = xstrdup (user);
- ut->ut_id = xstrdup (session);
- ut->ut_line = xstrdup (seat);
- ut->ut_pid = leader_pid; /* this is the best we have */
- ut->ut_type = USER_PROCESS;
- ut->ut_tv = start_tv;
- ut->ut_host = xstrdup (host);
- ut->ut_session = leader_pid;
- if (desirable_utmp_entry (ut, options))
- n_filled++;
- else
- free_utmp (1, ut);
- }
+ a = add_utmp (a, options, user, session, seat,
+ leader_pid /* the best we have */,
+ USER_PROCESS, start_tv, host, leader_pid);
if (tty != NULL)
- {
- STRUCT_UTMP *ut = &utmp[n_filled];
- ut->ut_user = xstrdup (user);
- ut->ut_id = xstrdup (session);
- ut->ut_line = xstrdup (tty);
- ut->ut_pid = leader_pid; /* this is the best we have */
- ut->ut_type = USER_PROCESS;
- ut->ut_tv = start_tv;
- ut->ut_host = xstrdup (host);
- ut->ut_session = leader_pid;
- if (desirable_utmp_entry (ut, options))
- n_filled++;
- else
- free_utmp (1, ut);
- }
+ a = add_utmp (a, options, user, session, tty,
+ leader_pid /* the best we have */,
+ USER_PROCESS, start_tv, host, leader_pid);
free (host);
- free (remote_user);
- free (remote_host);
free (user);
}
+
+ if (type != missing_type)
+ free (type);
free (tty);
free (seat);
free (session);
@@ -417,8 +441,21 @@ read_utmp (char const *file, size_t *n_entries, STRUCT_UTMP **utmp_buf,
free (sessions);
}
- *n_entries = n_filled;
- *utmp_buf = utmp;
+ /* Relocate the string pointers back to their natural position. */
+ {
+ char *stringlim = (char *) a.utmp + a.alloc_bytes;
+
+ for (idx_t i = 0; i < a.filled; i++)
+ {
+ a.utmp[i].ut_user = (intptr_t) a.utmp[i].ut_user + stringlim;
+ a.utmp[i].ut_id = (intptr_t) a.utmp[i].ut_id + stringlim;
+ a.utmp[i].ut_line = (intptr_t) a.utmp[i].ut_line + stringlim;
+ a.utmp[i].ut_host = (intptr_t) a.utmp[i].ut_host + stringlim;
+ }
+ }
+
+ *n_entries = a.filled;
+ *utmp_buf = a.utmp;
return 0;
}
@@ -557,19 +594,3 @@ read_utmp (char const *file, size_t *n_entries, STRUCT_UTMP **utmp_buf,
}
#endif
-
-void
-free_utmp (size_t n_entries, STRUCT_UTMP *entries)
-{
-#if READUTMP_USE_SYSTEMD
- size_t i;
- for (i = 0; i < n_entries; i++)
- {
- STRUCT_UTMP *ut = &entries[i];
- free (ut->ut_user);
- free (ut->ut_id);
- free (ut->ut_line);
- free (ut->ut_host);
- }
-#endif
-}
diff --git a/lib/readutmp.h b/lib/readutmp.h
index d7db9f3a67..956a8cafd9 100644
--- a/lib/readutmp.h
+++ b/lib/readutmp.h
@@ -389,8 +389,4 @@ char *extract_trimmed_name (const STRUCT_UTMP *ut)
int read_utmp (char const *file, size_t *n_entries, STRUCT_UTMP **utmp_buf,
int options);
-/* Free the memory allocated by the N_ENTRIES utmp entries, starting
- at ENTRIES. */
-void free_utmp (size_t n_entries, STRUCT_UTMP *entries);
-
#endif /* __READUTMP_H__ */
diff --git a/tests/test-readutmp.c b/tests/test-readutmp.c
index ae17087a81..b03c5f9e47 100644
--- a/tests/test-readutmp.c
+++ b/tests/test-readutmp.c
@@ -138,9 +138,9 @@ main (int argc, char *argv[])
time_t now = time (NULL);
ASSERT (first >= now - 157680000);
ASSERT (last <= now + 604800);
-
- free_utmp (num_entries, entries);
}
+ free (entries);
+
return 0;
}
--
2.39.2
From db1645dd8b4874600d12a42324d2c153ea05d9ee Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Thu, 3 Aug 2023 15:53:30 -0700
Subject: [PATCH 3/9] readutmp: fix idx_t FIXME in API
* lib/readutmp.c (read_utmp): 2nd arg is now idx_t *, not
size_t *.
* lib/readutmp.h: Include idx.h, for idx_t.
* modules/readutmp (Depends-on): Add idx.
---
ChangeLog | 6 ++++++
NEWS | 5 +++--
lib/readutmp.c | 8 ++++----
lib/readutmp.h | 5 +++--
modules/readutmp | 1 +
5 files changed, 17 insertions(+), 8 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 56b27d129f..a87e6537b1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
2023-08-03 Paul Eggert <egg...@cs.ucla.edu>
+ readutmp: fix idx_t FIXME in API
+ * lib/readutmp.c (read_utmp): 2nd arg is now idx_t *, not
+ size_t *.
+ * lib/readutmp.h: Include idx.h, for idx_t.
+ * modules/readutmp (Depends-on): Add idx.
+
readutmp: go back to simple ‘free’
Omit the new free_utmp function. Instead, allocate storage
in one block, so that using code can still just call ‘free’.
diff --git a/NEWS b/NEWS
index 24139d4660..f1c9b72aa9 100644
--- a/NEWS
+++ b/NEWS
@@ -74,8 +74,9 @@ User visible incompatible changes
Date Modules Changes
-2023-08-01 readutmp Some STRUCT_UTMP members can be char *,
- rather than fixed-length char arrays.
+2023-08-02 readutmp Some STRUCT_UTMP members can be char *,
+2023-08-01 rather than fixed-length char arrays.
+ read_utmp's 2nd arg is now idx_t * not size_t *.
Link additionally with $(READUTMP_LIB).
2023-07-10 dfa The signature of the function
diff --git a/lib/readutmp.c b/lib/readutmp.c
index 508978ba79..66314ec1db 100644
--- a/lib/readutmp.c
+++ b/lib/readutmp.c
@@ -299,7 +299,7 @@ add_utmp (struct utmp_alloc a, int options,
}
int
-read_utmp (char const *file, size_t *n_entries, STRUCT_UTMP **utmp_buf,
+read_utmp (char const *file, idx_t *n_entries, STRUCT_UTMP **utmp_buf,
int options)
{
/* Fill entries, simulating what a utmp file would contain. */
@@ -508,7 +508,7 @@ copy_utmp_entry (STRUCT_UTMP *dst, STRUCT_UTMP *src)
}
int
-read_utmp (char const *file, size_t *n_entries, STRUCT_UTMP **utmp_buf,
+read_utmp (char const *file, idx_t *n_entries, STRUCT_UTMP **utmp_buf,
int options)
{
idx_t n_read = 0;
@@ -544,7 +544,7 @@ read_utmp (char const *file, size_t *n_entries, STRUCT_UTMP **utmp_buf,
# else
int
-read_utmp (char const *file, size_t *n_entries, STRUCT_UTMP **utmp_buf,
+read_utmp (char const *file, idx_t *n_entries, STRUCT_UTMP **utmp_buf,
int options)
{
idx_t n_read = 0;
@@ -586,7 +586,7 @@ read_utmp (char const *file, size_t *n_entries, STRUCT_UTMP **utmp_buf,
#else /* dummy fallback */
int
-read_utmp (char const *file, size_t *n_entries, STRUCT_UTMP **utmp_buf,
+read_utmp (char const *file, idx_t *n_entries, STRUCT_UTMP **utmp_buf,
int options)
{
errno = ENOSYS;
diff --git a/lib/readutmp.h b/lib/readutmp.h
index 956a8cafd9..4897b102d2 100644
--- a/lib/readutmp.h
+++ b/lib/readutmp.h
@@ -27,6 +27,8 @@
# error "Please include config.h first."
# endif
+# include "idx.h"
+
# include <stdlib.h>
# include <sys/types.h>
@@ -385,8 +387,7 @@ char *extract_trimmed_name (const STRUCT_UTMP *ut)
process-IDs do not currently exist.
If OPTIONS & READ_UTMP_USER_PROCESS is nonzero, omit entries which
do not correspond to a user process. */
-/* FIXME: This header should use idx_t, not size_t. */
-int read_utmp (char const *file, size_t *n_entries, STRUCT_UTMP **utmp_buf,
+int read_utmp (char const *file, idx_t *n_entries, STRUCT_UTMP **utmp_buf,
int options);
#endif /* __READUTMP_H__ */
diff --git a/modules/readutmp b/modules/readutmp
index 484edd1842..534ce4fa19 100644
--- a/modules/readutmp
+++ b/modules/readutmp
@@ -9,6 +9,7 @@ m4/systemd.m4
Depends-on:
extensions
+idx
xalloc
stdbool
stdint
--
2.39.2
From e16e74a11015259f02f5cfe26af6ea8e2ce1a270 Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Thu, 3 Aug 2023 15:54:12 -0700
Subject: [PATCH 4/9] readutmp: pacify -Wstrict-prototypes
* lib/readutmp.c (get_boot_time_uncached, get_boot_time):
Pacify gcc 13 -Wstrict-prototypes.
---
ChangeLog | 4 ++++
lib/readutmp.c | 4 ++--
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index a87e6537b1..1a75ea0c33 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
2023-08-03 Paul Eggert <egg...@cs.ucla.edu>
+ readutmp: pacify -Wstrict-prototypes
+ * lib/readutmp.c (get_boot_time_uncached, get_boot_time):
+ Pacify gcc 13 -Wstrict-prototypes.
+
readutmp: fix idx_t FIXME in API
* lib/readutmp.c (read_utmp): 2nd arg is now idx_t *, not
size_t *.
diff --git a/lib/readutmp.c b/lib/readutmp.c
index 66314ec1db..97e92e69af 100644
--- a/lib/readutmp.c
+++ b/lib/readutmp.c
@@ -94,7 +94,7 @@ desirable_utmp_entry (STRUCT_UTMP const *ut, int options)
/* Use systemd and Linux /proc and kernel APIs. */
static struct timeval
-get_boot_time_uncached ()
+get_boot_time_uncached (void)
{
/* /proc/uptime contains the uptime with a resolution of 0.01 sec. */
FILE *fp = fopen ("/proc/uptime", "re");
@@ -147,7 +147,7 @@ get_boot_time_uncached ()
}
static struct timeval
-get_boot_time ()
+get_boot_time (void)
{
static int cached;
static struct timeval boot_time;
--
2.39.2
From 2ab324f6789713e55e05ad7c50691995db2b0f85 Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Thu, 3 Aug 2023 15:54:14 -0700
Subject: [PATCH 5/9] readutmp: fix # indentation
* lib/readutmp.h: Change # indentation to standard Gnulib style.
---
ChangeLog | 3 +
lib/readutmp.h | 380 ++++++++++++++++++++++++-------------------------
2 files changed, 191 insertions(+), 192 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 1a75ea0c33..44b80d8c61 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
2023-08-03 Paul Eggert <egg...@cs.ucla.edu>
+ readutmp: fix # indentation
+ * lib/readutmp.h: Change # indentation to standard Gnulib style.
+
readutmp: pacify -Wstrict-prototypes
* lib/readutmp.c (get_boot_time_uncached, get_boot_time):
Pacify gcc 13 -Wstrict-prototypes.
diff --git a/lib/readutmp.h b/lib/readutmp.h
index 4897b102d2..da7225152c 100644
--- a/lib/readutmp.h
+++ b/lib/readutmp.h
@@ -18,31 +18,31 @@
/* Written by jla; revised by djm */
#ifndef __READUTMP_H__
-# define __READUTMP_H__
+#define __READUTMP_H__
/* This file uses _GL_ATTRIBUTE_MALLOC, _GL_ATTRIBUTE_RETURNS_NONNULL,
HAVE_UTMP_H, HAVE_UTMPX_H, HAVE_STRUCT_UTMP_*, HAVE_STRUCT_UTMPX_*,
HAVE_UTMPNAME, HAVE_UTMPXNAME, HAVE_DECL_GETUTENT. */
-# if !_GL_CONFIG_H_INCLUDED
-# error "Please include config.h first."
-# endif
+#if !_GL_CONFIG_H_INCLUDED
+# error "Please include config.h first."
+#endif
-# include "idx.h"
+#include "idx.h"
-# include <stdlib.h>
-# include <sys/types.h>
+#include <stdlib.h>
+#include <sys/types.h>
/* AIX 4.3.3 has both utmp.h and utmpx.h, but only struct utmp
has the ut_exit member. */
-# if (HAVE_UTMPX_H && HAVE_UTMP_H && HAVE_STRUCT_UTMP_UT_EXIT \
- && ! HAVE_STRUCT_UTMPX_UT_EXIT)
-# undef HAVE_UTMPX_H
-# endif
+#if (HAVE_UTMPX_H && HAVE_UTMP_H && HAVE_STRUCT_UTMP_UT_EXIT \
+ && ! HAVE_STRUCT_UTMPX_UT_EXIT)
+# undef HAVE_UTMPX_H
+#endif
-# if READUTMP_USE_SYSTEMD
+#if READUTMP_USE_SYSTEMD
/* Get 'struct timeval'. */
-# include <sys/time.h>
+# include <sys/time.h>
/* Type for the entries returned by read_utmp. */
struct gl_utmp
@@ -59,14 +59,14 @@ struct gl_utmp
};
/* Get values for ut_type: BOOT_TIME, USER_PROCESS. */
-# include <utmpx.h>
+# include <utmpx.h>
-# define UTMP_STRUCT_NAME gl_utmp
-# define UT_TIME_MEMBER(UT) ((UT)->ut_tv.tv_sec)
-# define UT_EXIT_E_TERMINATION(UT) 0
-# define UT_EXIT_E_EXIT(UT) 0
+# define UTMP_STRUCT_NAME gl_utmp
+# define UT_TIME_MEMBER(UT) ((UT)->ut_tv.tv_sec)
+# define UT_EXIT_E_TERMINATION(UT) 0
+# define UT_EXIT_E_EXIT(UT) 0
-# elif HAVE_UTMPX_H
+#elif HAVE_UTMPX_H
/* <utmpx.h> defines 'struct utmpx' with the following fields:
@@ -90,48 +90,44 @@ struct gl_utmp
⎣ ut_ss struct sockaddr_storage NetBSD, Minix
*/
-# if HAVE_UTMP_H
+# if HAVE_UTMP_H
/* HPUX 10.20 needs utmp.h, for the definition of e.g., UTMP_FILE. */
-# include <utmp.h>
-# endif
-# if defined _THREAD_SAFE && defined UTMP_DATA_INIT
+# include <utmp.h>
+# endif
+# if defined _THREAD_SAFE && defined UTMP_DATA_INIT
/* When including both utmp.h and utmpx.h on AIX 4.3, with _THREAD_SAFE
defined, work around the duplicate struct utmp_data declaration. */
-# define utmp_data gl_aix_4_3_workaround_utmp_data
-# endif
-# include <utmpx.h>
-# define UTMP_STRUCT_NAME utmpx
-# define UT_TIME_MEMBER(UT) ((UT)->ut_tv.tv_sec)
-# define SET_UTMP_ENT setutxent
-# define GET_UTMP_ENT getutxent
-# define END_UTMP_ENT endutxent
-# ifdef HAVE_UTMPXNAME
-# define UTMP_NAME_FUNCTION utmpxname
-# elif defined UTXDB_ACTIVE
-# define UTMP_NAME_FUNCTION(x) setutxdb (UTXDB_ACTIVE, x)
-# endif
-
-# if HAVE_STRUCT_UTMPX_UT_EXIT_E_TERMINATION
-# define UT_EXIT_E_TERMINATION(UT) ((UT)->ut_exit.e_termination)
-# else
-# if HAVE_STRUCT_UTMPX_UT_EXIT_UT_TERMINATION /* OSF/1 */
-# define UT_EXIT_E_TERMINATION(UT) ((UT)->ut_exit.ut_termination)
-# else
-# define UT_EXIT_E_TERMINATION(UT) 0
-# endif
-# endif
-
-# if HAVE_STRUCT_UTMPX_UT_EXIT_E_EXIT
-# define UT_EXIT_E_EXIT(UT) ((UT)->ut_exit.e_exit)
-# else
-# if HAVE_STRUCT_UTMPX_UT_EXIT_UT_EXIT /* OSF/1 */
-# define UT_EXIT_E_EXIT(UT) ((UT)->ut_exit.ut_exit)
-# else
-# define UT_EXIT_E_EXIT(UT) 0
-# endif
-# endif
-
-# elif HAVE_UTMP_H
+# define utmp_data gl_aix_4_3_workaround_utmp_data
+# endif
+# include <utmpx.h>
+# define UTMP_STRUCT_NAME utmpx
+# define UT_TIME_MEMBER(UT) ((UT)->ut_tv.tv_sec)
+# define SET_UTMP_ENT setutxent
+# define GET_UTMP_ENT getutxent
+# define END_UTMP_ENT endutxent
+# ifdef HAVE_UTMPXNAME
+# define UTMP_NAME_FUNCTION utmpxname
+# elif defined UTXDB_ACTIVE
+# define UTMP_NAME_FUNCTION(x) setutxdb (UTXDB_ACTIVE, x)
+# endif
+
+# if HAVE_STRUCT_UTMPX_UT_EXIT_E_TERMINATION
+# define UT_EXIT_E_TERMINATION(UT) ((UT)->ut_exit.e_termination)
+# elif HAVE_STRUCT_UTMPX_UT_EXIT_UT_TERMINATION /* OSF/1 */
+# define UT_EXIT_E_TERMINATION(UT) ((UT)->ut_exit.ut_termination)
+# else
+# define UT_EXIT_E_TERMINATION(UT) 0
+# endif
+
+# if HAVE_STRUCT_UTMPX_UT_EXIT_E_EXIT
+# define UT_EXIT_E_EXIT(UT) ((UT)->ut_exit.e_exit)
+# elif HAVE_STRUCT_UTMPX_UT_EXIT_UT_EXIT /* OSF/1 */
+# define UT_EXIT_E_EXIT(UT) ((UT)->ut_exit.ut_exit)
+# else
+# define UT_EXIT_E_EXIT(UT) 0
+# endif
+
+#elif HAVE_UTMP_H
/* <utmp.h> defines 'struct utmp' with the following fields:
@@ -154,37 +150,37 @@ struct gl_utmp
⎣ ut_addr_v6 [u]int[4] glibc, musl, Android
*/
-# include <utmp.h>
-# if !HAVE_DECL_GETUTENT
+# include <utmp.h>
+# if !HAVE_DECL_GETUTENT
struct utmp *getutent (void);
-# endif
-# define UTMP_STRUCT_NAME utmp
-# define UT_TIME_MEMBER(UT) ((UT)->ut_time)
-# define SET_UTMP_ENT setutent
-# define GET_UTMP_ENT getutent
-# define END_UTMP_ENT endutent
-# ifdef HAVE_UTMPNAME
-# define UTMP_NAME_FUNCTION utmpname
-# endif
-
-# if HAVE_STRUCT_UTMP_UT_EXIT_E_TERMINATION
-# define UT_EXIT_E_TERMINATION(UT) ((UT)->ut_exit.e_termination)
-# else
-# define UT_EXIT_E_TERMINATION(UT) 0
-# endif
-
-# if HAVE_STRUCT_UTMP_UT_EXIT_E_EXIT
-# define UT_EXIT_E_EXIT(UT) ((UT)->ut_exit.e_exit)
-# else
-# define UT_EXIT_E_EXIT(UT) 0
-# endif
+# endif
+# define UTMP_STRUCT_NAME utmp
+# define UT_TIME_MEMBER(UT) ((UT)->ut_time)
+# define SET_UTMP_ENT setutent
+# define GET_UTMP_ENT getutent
+# define END_UTMP_ENT endutent
+# ifdef HAVE_UTMPNAME
+# define UTMP_NAME_FUNCTION utmpname
+# endif
+# if HAVE_STRUCT_UTMP_UT_EXIT_E_TERMINATION
+# define UT_EXIT_E_TERMINATION(UT) ((UT)->ut_exit.e_termination)
# else
+# define UT_EXIT_E_TERMINATION(UT) 0
+# endif
+
+# if HAVE_STRUCT_UTMP_UT_EXIT_E_EXIT
+# define UT_EXIT_E_EXIT(UT) ((UT)->ut_exit.e_exit)
+# else
+# define UT_EXIT_E_EXIT(UT) 0
+# endif
+
+#else
/* Provide a dummy fallback. */
/* Get 'struct timeval'. */
-# include <sys/time.h>
+# include <sys/time.h>
struct gl_utmp
{
@@ -192,178 +188,178 @@ struct gl_utmp
char ut_line[1];
struct timeval ut_tv;
};
-# define UTMP_STRUCT_NAME gl_utmp
-# define UT_TIME_MEMBER(UT) ((UT)->ut_tv.tv_sec)
-# define UT_EXIT_E_TERMINATION(UT) 0
-# define UT_EXIT_E_EXIT(UT) 0
+# define UTMP_STRUCT_NAME gl_utmp
+# define UT_TIME_MEMBER(UT) ((UT)->ut_tv.tv_sec)
+# define UT_EXIT_E_TERMINATION(UT) 0
+# define UT_EXIT_E_EXIT(UT) 0
-# endif
+#endif
/* Accessor macro for the member named ut_user or ut_name. */
-# if READUTMP_USE_SYSTEMD
+#if READUTMP_USE_SYSTEMD
-# define UT_USER(UT) ((UT)->ut_user)
+# define UT_USER(UT) ((UT)->ut_user)
-# elif HAVE_UTMPX_H
+#elif HAVE_UTMPX_H
-# if HAVE_STRUCT_UTMPX_UT_USER
-# define UT_USER(UT) ((UT)->ut_user)
-# endif
-# if HAVE_STRUCT_UTMPX_UT_NAME
-# undef UT_USER
-# define UT_USER(UT) ((UT)->ut_name)
-# endif
+# if HAVE_STRUCT_UTMPX_UT_USER
+# define UT_USER(UT) ((UT)->ut_user)
+# endif
+# if HAVE_STRUCT_UTMPX_UT_NAME
+# undef UT_USER
+# define UT_USER(UT) ((UT)->ut_name)
+# endif
-# elif HAVE_UTMP_H
+#elif HAVE_UTMP_H
-# if HAVE_STRUCT_UTMP_UT_USER
-# define UT_USER(UT) ((UT)->ut_user)
-# endif
-# if HAVE_STRUCT_UTMP_UT_NAME
-# undef UT_USER
-# define UT_USER(UT) ((UT)->ut_name)
-# endif
+# if HAVE_STRUCT_UTMP_UT_USER
+# define UT_USER(UT) ((UT)->ut_user)
+# endif
+# if HAVE_STRUCT_UTMP_UT_NAME
+# undef UT_USER
+# define UT_USER(UT) ((UT)->ut_name)
+# endif
-# else /* dummy fallback */
+#else /* dummy fallback */
-# define UT_USER(UT) ((UT)->ut_user)
+# define UT_USER(UT) ((UT)->ut_user)
-# endif
+#endif
-# if READUTMP_USE_SYSTEMD
-# define HAVE_STRUCT_XTMP_UT_EXIT 0
-# else
-# define HAVE_STRUCT_XTMP_UT_EXIT \
+#if READUTMP_USE_SYSTEMD
+# define HAVE_STRUCT_XTMP_UT_EXIT 0
+#else
+# define HAVE_STRUCT_XTMP_UT_EXIT \
(HAVE_STRUCT_UTMP_UT_EXIT \
|| HAVE_STRUCT_UTMPX_UT_EXIT)
-# endif
+#endif
-# if READUTMP_USE_SYSTEMD
-# define HAVE_STRUCT_XTMP_UT_ID 1
-# else
-# define HAVE_STRUCT_XTMP_UT_ID \
+#if READUTMP_USE_SYSTEMD
+# define HAVE_STRUCT_XTMP_UT_ID 1
+#else
+# define HAVE_STRUCT_XTMP_UT_ID \
(HAVE_STRUCT_UTMP_UT_ID \
|| HAVE_STRUCT_UTMPX_UT_ID)
-# endif
+#endif
-# if READUTMP_USE_SYSTEMD
-# define HAVE_STRUCT_XTMP_UT_PID 1
-# else
-# define HAVE_STRUCT_XTMP_UT_PID \
+#if READUTMP_USE_SYSTEMD
+# define HAVE_STRUCT_XTMP_UT_PID 1
+#else
+# define HAVE_STRUCT_XTMP_UT_PID \
(HAVE_STRUCT_UTMP_UT_PID \
|| HAVE_STRUCT_UTMPX_UT_PID)
-# endif
+#endif
-# if READUTMP_USE_SYSTEMD
-# define HAVE_STRUCT_XTMP_UT_HOST 1
-# else
-# define HAVE_STRUCT_XTMP_UT_HOST \
+#if READUTMP_USE_SYSTEMD
+# define HAVE_STRUCT_XTMP_UT_HOST 1
+#else
+# define HAVE_STRUCT_XTMP_UT_HOST \
(HAVE_STRUCT_UTMP_UT_HOST \
|| HAVE_STRUCT_UTMPX_UT_HOST)
-# endif
+#endif
/* Type of entry returned by read_utmp(). */
typedef struct UTMP_STRUCT_NAME STRUCT_UTMP;
/* Size of the UT_USER (ut) member, or -1 if unbounded. */
-# if READUTMP_USE_SYSTEMD
+#if READUTMP_USE_SYSTEMD
enum { UT_USER_SIZE = -1 };
-# else
+#else
enum { UT_USER_SIZE = sizeof UT_USER ((STRUCT_UTMP *) 0) };
-# define UT_USER_SIZE UT_USER_SIZE
-# endif
+# define UT_USER_SIZE UT_USER_SIZE
+#endif
/* Size of the ut->ut_id member, or -1 if unbounded. */
-# if READUTMP_USE_SYSTEMD
+#if READUTMP_USE_SYSTEMD
enum { UT_ID_SIZE = -1 };
-# else
+#else
enum { UT_ID_SIZE = sizeof (((STRUCT_UTMP *) 0)->ut_id) };
-# define UT_ID_SIZE UT_ID_SIZE
-# endif
+# define UT_ID_SIZE UT_ID_SIZE
+#endif
/* Size of the ut->ut_line member, or -1 if unbounded. */
-# if READUTMP_USE_SYSTEMD
+#if READUTMP_USE_SYSTEMD
enum { UT_LINE_SIZE = -1 };
-# else
+#else
enum { UT_LINE_SIZE = sizeof (((STRUCT_UTMP *) 0)->ut_line) };
-# define UT_LINE_SIZE UT_LINE_SIZE
-# endif
+# define UT_LINE_SIZE UT_LINE_SIZE
+#endif
/* Size of the ut->ut_host member, or -1 if unbounded. */
-# if READUTMP_USE_SYSTEMD
+#if READUTMP_USE_SYSTEMD
enum { UT_HOST_SIZE = -1 };
-# else
+#else
enum { UT_HOST_SIZE = sizeof (((STRUCT_UTMP *) 0)->ut_host) };
-# define UT_HOST_SIZE UT_HOST_SIZE
-# endif
+# define UT_HOST_SIZE UT_HOST_SIZE
+#endif
/* Definition of UTMP_FILE and WTMP_FILE. */
-# if !defined UTMP_FILE && defined _PATH_UTMP
-# define UTMP_FILE _PATH_UTMP
-# endif
+#if !defined UTMP_FILE && defined _PATH_UTMP
+# define UTMP_FILE _PATH_UTMP
+#endif
-# if !defined WTMP_FILE && defined _PATH_WTMP
-# define WTMP_FILE _PATH_WTMP
-# endif
+#if !defined WTMP_FILE && defined _PATH_WTMP
+# define WTMP_FILE _PATH_WTMP
+#endif
-# ifdef UTMPX_FILE /* Solaris, SysVr4 */
-# undef UTMP_FILE
-# define UTMP_FILE UTMPX_FILE
-# endif
+#ifdef UTMPX_FILE /* Solaris, SysVr4 */
+# undef UTMP_FILE
+# define UTMP_FILE UTMPX_FILE
+#endif
-# ifdef WTMPX_FILE /* Solaris, SysVr4 */
-# undef WTMP_FILE
-# define WTMP_FILE WTMPX_FILE
-# endif
+#ifdef WTMPX_FILE /* Solaris, SysVr4 */
+# undef WTMP_FILE
+# define WTMP_FILE WTMPX_FILE
+#endif
-# ifndef UTMP_FILE
-# define UTMP_FILE "/etc/utmp"
-# endif
+#ifndef UTMP_FILE
+# define UTMP_FILE "/etc/utmp"
+#endif
-# ifndef WTMP_FILE
-# define WTMP_FILE "/etc/wtmp"
-# endif
+#ifndef WTMP_FILE
+# define WTMP_FILE "/etc/wtmp"
+#endif
/* Accessor macro for the member named ut_pid. */
-# if HAVE_STRUCT_XTMP_UT_PID
-# define UT_PID(UT) ((UT)->ut_pid)
-# else
-# define UT_PID(UT) 0
-# endif
+#if HAVE_STRUCT_XTMP_UT_PID
+# define UT_PID(UT) ((UT)->ut_pid)
+#else
+# define UT_PID(UT) 0
+#endif
/* Accessor macros for the member named ut_type. */
-# if READUTMP_USE_SYSTEMD || HAVE_STRUCT_UTMP_UT_TYPE || HAVE_STRUCT_UTMPX_UT_TYPE
-# define UT_TYPE_EQ(UT, V) ((UT)->ut_type == (V))
-# define UT_TYPE_NOT_DEFINED 0
-# else
-# define UT_TYPE_EQ(UT, V) 0
-# define UT_TYPE_NOT_DEFINED 1
-# endif
-
-# ifdef BOOT_TIME
-# define UT_TYPE_BOOT_TIME(UT) UT_TYPE_EQ (UT, BOOT_TIME)
-# else
-# define UT_TYPE_BOOT_TIME(UT) 0
-# endif
-
-# ifdef USER_PROCESS
-# define UT_TYPE_USER_PROCESS(UT) UT_TYPE_EQ (UT, USER_PROCESS)
-# else
-# define UT_TYPE_USER_PROCESS(UT) 0
-# endif
+#if READUTMP_USE_SYSTEMD || HAVE_STRUCT_UTMP_UT_TYPE || HAVE_STRUCT_UTMPX_UT_TYPE
+# define UT_TYPE_EQ(UT, V) ((UT)->ut_type == (V))
+# define UT_TYPE_NOT_DEFINED 0
+#else
+# define UT_TYPE_EQ(UT, V) 0
+# define UT_TYPE_NOT_DEFINED 1
+#endif
+
+#ifdef BOOT_TIME
+# define UT_TYPE_BOOT_TIME(UT) UT_TYPE_EQ (UT, BOOT_TIME)
+#else
+# define UT_TYPE_BOOT_TIME(UT) 0
+#endif
+
+#ifdef USER_PROCESS
+# define UT_TYPE_USER_PROCESS(UT) UT_TYPE_EQ (UT, USER_PROCESS)
+#else
+# define UT_TYPE_USER_PROCESS(UT) 0
+#endif
/* Determines whether an entry *UT corresponds to a user process. */
-# define IS_USER_PROCESS(UT) \
+#define IS_USER_PROCESS(UT) \
(UT_USER (UT)[0] \
&& (UT_TYPE_USER_PROCESS (UT) \
|| (UT_TYPE_NOT_DEFINED && UT_TIME_MEMBER (UT) != 0)))
/* Define if read_utmp is not just a dummy. */
-# if READUTMP_USE_SYSTEMD || HAVE_UTMPX_H || HAVE_UTMP_H
-# define READ_UTMP_SUPPORTED 1
-# endif
+#if READUTMP_USE_SYSTEMD || HAVE_UTMPX_H || HAVE_UTMP_H
+# define READ_UTMP_SUPPORTED 1
+#endif
/* Options for read_utmp. */
enum
--
2.39.2
From c0a858b24839d69858a5418f30971fd355b42fc4 Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Thu, 3 Aug 2023 16:01:50 -0700
Subject: [PATCH 6/9] readutmp: switch new struct to struct timespec
* lib/readutmp.c (get_boot_time_uncached, get_boot_time)
(add_utmp, read_utmp):
Use struct timespec, not struct timeval.
* lib/readutmp.h: Always include <time.h>, for struct timespec.
Simplify when utmp.h and utmpx.h are included.
(struct gl_utmp): Use the same struct for both the
systemd and the dummy version. Reorder members, and
use proper pid_t type for ut_session. Rename ut_tv to ut_ts
and make it a struct timespec. All uses changed.
(HAVE_GL_UTMP): New macro. Use it where appropriate, instead
of READUTMP_USE_SYSTEMD.
(UT_USER, HAVE_STRUCT_XTMP_UT_EXIT, HAVE_STRUCT_XTMP_UT_ID)
(HAVE_STRUCT_XTMP_UT_PID, HAVE_STRUCT_XTMP_UT_HOST):
Simplify.
* modules/readutmp (Depends-on): Add time-h, timespec_get.
Remove sys_type. Sort.
---
ChangeLog | 18 ++++++
lib/readutmp.c | 69 +++++++++++------------
lib/readutmp.h | 141 ++++++++++++++---------------------------------
modules/readutmp | 7 ++-
4 files changed, 93 insertions(+), 142 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 44b80d8c61..133f49df97 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,23 @@
2023-08-03 Paul Eggert <egg...@cs.ucla.edu>
+ readutmp: switch new struct to struct timespec
+ * lib/readutmp.c (get_boot_time_uncached, get_boot_time)
+ (add_utmp, read_utmp):
+ Use struct timespec, not struct timeval.
+ * lib/readutmp.h: Always include <time.h>, for struct timespec.
+ Simplify when utmp.h and utmpx.h are included.
+ (struct gl_utmp): Use the same struct for both the
+ systemd and the dummy version. Reorder members, and
+ use proper pid_t type for ut_session. Rename ut_tv to ut_ts
+ and make it a struct timespec. All uses changed.
+ (HAVE_GL_UTMP): New macro. Use it where appropriate, instead
+ of READUTMP_USE_SYSTEMD.
+ (UT_USER, HAVE_STRUCT_XTMP_UT_EXIT, HAVE_STRUCT_XTMP_UT_ID)
+ (HAVE_STRUCT_XTMP_UT_PID, HAVE_STRUCT_XTMP_UT_HOST):
+ Simplify.
+ * modules/readutmp (Depends-on): Add time-h, timespec_get.
+ Remove sys_type. Sort.
+
readutmp: fix # indentation
* lib/readutmp.h: Change # indentation to standard Gnulib style.
diff --git a/lib/readutmp.c b/lib/readutmp.c
index 97e92e69af..113382c636 100644
--- a/lib/readutmp.c
+++ b/lib/readutmp.c
@@ -93,7 +93,7 @@ desirable_utmp_entry (STRUCT_UTMP const *ut, int options)
# if READUTMP_USE_SYSTEMD
/* Use systemd and Linux /proc and kernel APIs. */
-static struct timeval
+static struct timespec
get_boot_time_uncached (void)
{
/* /proc/uptime contains the uptime with a resolution of 0.01 sec. */
@@ -111,19 +111,22 @@ get_boot_time_uncached (void)
double uptime = strtod (buf, &endptr);
if (endptr > buf)
{
- struct timeval result;
- if (gettimeofday (&result, NULL) >= 0)
+ struct timespec result;
+ if (0 <= timespec_get (&result, TIME_UTC))
{
- long uptime_sec = (long) uptime;
- int uptime_usec =
- (int) ((uptime - (double) uptime_sec) * 1000000.0 + 0.5);
- if (result.tv_usec < uptime_usec)
+ time_t uptime_sec = uptime;
+ struct timespec up =
{
- result.tv_usec += 1000000;
+ .tv_sec = uptime_sec,
+ .tv_nsec = (uptime - uptime_sec) * 1e9 + 0.5
+ };
+ if (result.tv_nsec < up.tv_nsec)
+ {
+ result.tv_nsec += 1000000000;
result.tv_sec -= 1;
}
- result.tv_sec -= uptime_sec;
- result.tv_usec -= uptime_usec;
+ result.tv_sec -= up.tv_sec;
+ result.tv_nsec -= up.tv_nsec;
return result;
}
}
@@ -134,8 +137,8 @@ get_boot_time_uncached (void)
struct sysinfo info;
if (sysinfo (&info) >= 0)
{
- struct timeval result;
- if (gettimeofday (&result, NULL) >= 0)
+ struct timespec result;
+ if (0 <= timespec_get (&result, TIME_UTC))
{
result.tv_sec -= info.uptime;
return result;
@@ -143,19 +146,19 @@ get_boot_time_uncached (void)
}
/* We shouldn't get here. */
- return (struct timeval) { .tv_sec = 0, .tv_usec = 0 };
+ return (struct timespec) {0};
}
-static struct timeval
+static struct timespec
get_boot_time (void)
{
- static int cached;
- static struct timeval boot_time;
+ static bool cached;
+ static struct timespec boot_time;
if (!cached)
{
+ cached = true;
boot_time = get_boot_time_uncached ();
- cached = 1;
}
return boot_time;
}
@@ -252,7 +255,7 @@ struct utmp_alloc
static struct utmp_alloc
add_utmp (struct utmp_alloc a, int options,
char const *user, char const *id, char const *line, pid_t pid,
- short type, struct timeval t, char const *host, long session)
+ short type, struct timespec ts, char const *host, long session)
{
if (!user) user = "";
if (!host) host = "";
@@ -277,11 +280,11 @@ add_utmp (struct utmp_alloc a, int options,
ut->ut_user = p = memcpy (p - usersize, user, usersize);
ut->ut_id = p = memcpy (p - idsize, id, idsize);
ut->ut_line = p = memcpy (p - linesize, line, linesize);
- ut->ut_pid = pid;
- ut->ut_type = type;
- ut->ut_tv = t;
ut->ut_host = memcpy (p - hostsize, line, hostsize);
+ ut->ut_ts = ts;
+ ut->ut_pid = pid;
ut->ut_session = session;
+ ut->ut_type = type;
if (desirable_utmp_entry (ut, options))
{
/* Now that UT has been checked, relocate its string slots to be
@@ -323,9 +326,9 @@ read_utmp (char const *file, idx_t *n_entries, STRUCT_UTMP **utmp_buf,
uint64_t start_usec;
if (sd_session_get_start_time (session, &start_usec) < 0)
start_usec = 0;
- struct timeval start_tv;
- start_tv.tv_sec = start_usec / 1000000;
- start_tv.tv_usec = start_usec % 1000000;
+ struct timespec start_ts;
+ start_ts.tv_sec = start_usec / 1000000;
+ start_ts.tv_nsec = start_usec % 1000000 * 1000;
char *seat;
if (sd_session_get_seat (session, &seat) < 0)
@@ -346,19 +349,9 @@ read_utmp (char const *file, idx_t *n_entries, STRUCT_UTMP **utmp_buf,
if (sd_session_get_service (session, &service) < 0)
service = NULL;
- char *pty;
uid_t uid;
- if (sd_session_get_uid (session, &uid) >= 0)
- {
- struct timespec start_ts =
- {
- .tv_sec = start_tv.tv_sec,
- .tv_nsec = start_tv.tv_usec * 1000
- };
- pty = guess_pty_name (uid, start_ts);
- }
- else
- pty = NULL;
+ char *pty = (sd_session_get_uid (session, &uid) < 0 ? NULL
+ : guess_pty_name (uid, start_ts));
if (service != NULL && pty != NULL)
{
@@ -422,11 +415,11 @@ read_utmp (char const *file, idx_t *n_entries, STRUCT_UTMP **utmp_buf,
if (seat != NULL)
a = add_utmp (a, options, user, session, seat,
leader_pid /* the best we have */,
- USER_PROCESS, start_tv, host, leader_pid);
+ USER_PROCESS, start_ts, host, leader_pid);
if (tty != NULL)
a = add_utmp (a, options, user, session, tty,
leader_pid /* the best we have */,
- USER_PROCESS, start_tv, host, leader_pid);
+ USER_PROCESS, start_ts, host, leader_pid);
free (host);
free (user);
diff --git a/lib/readutmp.h b/lib/readutmp.h
index da7225152c..b3cfaeb67c 100644
--- a/lib/readutmp.h
+++ b/lib/readutmp.h
@@ -31,6 +31,7 @@
#include <stdlib.h>
#include <sys/types.h>
+#include <time.h>
/* AIX 4.3.3 has both utmp.h and utmpx.h, but only struct utmp
has the ut_exit member. */
@@ -39,30 +40,39 @@
# undef HAVE_UTMPX_H
#endif
-#if READUTMP_USE_SYSTEMD
+/* HPUX 10.20 needs utmp.h, for the definition of e.g., UTMP_FILE. */
+#if HAVE_UTMP_H
+# include <utmp.h>
+#endif
-/* Get 'struct timeval'. */
-# include <sys/time.h>
+/* Needed for BOOT_TIME and USER_PROCESS. */
+#if HAVE_UTMPX_H
+# if defined _THREAD_SAFE && defined UTMP_DATA_INIT
+ /* When including both utmp.h and utmpx.h on AIX 4.3, with _THREAD_SAFE
+ defined, work around the duplicate struct utmp_data declaration. */
+# define utmp_data gl_aix_4_3_workaround_utmp_data
+# endif
+# include <utmpx.h>
+#endif
+
+#if READUTMP_USE_SYSTEMD || ! (HAVE_UTMPX_H || HAVE_UTMP_H)
-/* Type for the entries returned by read_utmp. */
struct gl_utmp
{
/* All 'char *' here are of arbitrary length and malloc-allocated. */
char *ut_user; /* User name */
char *ut_id; /* Session ID */
char *ut_line; /* seat / device */
+ char *ut_host; /* for remote sessions: user@host or host */
+ struct timespec ut_ts; /* time */
pid_t ut_pid; /* process ID of ? */
+ pid_t ut_session; /* process ID of session leader */
short ut_type; /* BOOT_TIME or USER_PROCESS */
- struct timeval ut_tv; /* time */
- char *ut_host; /* for remote sessions: user@host or host */
- long ut_session; /* process ID of session leader */
};
-/* Get values for ut_type: BOOT_TIME, USER_PROCESS. */
-# include <utmpx.h>
-
+# define HAVE_GL_UTMP 1
# define UTMP_STRUCT_NAME gl_utmp
-# define UT_TIME_MEMBER(UT) ((UT)->ut_tv.tv_sec)
+# define UT_TIME_MEMBER(UT) ((UT)->ut_ts.tv_sec)
# define UT_EXIT_E_TERMINATION(UT) 0
# define UT_EXIT_E_EXIT(UT) 0
@@ -90,16 +100,6 @@ struct gl_utmp
⎣ ut_ss struct sockaddr_storage NetBSD, Minix
*/
-# if HAVE_UTMP_H
- /* HPUX 10.20 needs utmp.h, for the definition of e.g., UTMP_FILE. */
-# include <utmp.h>
-# endif
-# if defined _THREAD_SAFE && defined UTMP_DATA_INIT
- /* When including both utmp.h and utmpx.h on AIX 4.3, with _THREAD_SAFE
- defined, work around the duplicate struct utmp_data declaration. */
-# define utmp_data gl_aix_4_3_workaround_utmp_data
-# endif
-# include <utmpx.h>
# define UTMP_STRUCT_NAME utmpx
# define UT_TIME_MEMBER(UT) ((UT)->ut_tv.tv_sec)
# define SET_UTMP_ENT setutxent
@@ -150,12 +150,11 @@ struct gl_utmp
⎣ ut_addr_v6 [u]int[4] glibc, musl, Android
*/
-# include <utmp.h>
# if !HAVE_DECL_GETUTENT
struct utmp *getutent (void);
# endif
# define UTMP_STRUCT_NAME utmp
-# define UT_TIME_MEMBER(UT) ((UT)->ut_time)
+# define UT_TIME_MEMBER(UT) ((UT)->ut_ts.tv_sec)
# define SET_UTMP_ENT setutent
# define GET_UTMP_ENT getutent
# define END_UTMP_ENT endutent
@@ -175,94 +174,34 @@ struct gl_utmp
# define UT_EXIT_E_EXIT(UT) 0
# endif
-#else
-
-/* Provide a dummy fallback. */
-
-/* Get 'struct timeval'. */
-# include <sys/time.h>
-
-struct gl_utmp
-{
- char ut_user[1];
- char ut_line[1];
- struct timeval ut_tv;
-};
-# define UTMP_STRUCT_NAME gl_utmp
-# define UT_TIME_MEMBER(UT) ((UT)->ut_tv.tv_sec)
-# define UT_EXIT_E_TERMINATION(UT) 0
-# define UT_EXIT_E_EXIT(UT) 0
-
#endif
/* Accessor macro for the member named ut_user or ut_name. */
-#if READUTMP_USE_SYSTEMD
-
-# define UT_USER(UT) ((UT)->ut_user)
-
-#elif HAVE_UTMPX_H
-
-# if HAVE_STRUCT_UTMPX_UT_USER
-# define UT_USER(UT) ((UT)->ut_user)
-# endif
-# if HAVE_STRUCT_UTMPX_UT_NAME
-# undef UT_USER
-# define UT_USER(UT) ((UT)->ut_name)
-# endif
-
-#elif HAVE_UTMP_H
-
-# if HAVE_STRUCT_UTMP_UT_USER
-# define UT_USER(UT) ((UT)->ut_user)
-# endif
-# if HAVE_STRUCT_UTMP_UT_NAME
-# undef UT_USER
-# define UT_USER(UT) ((UT)->ut_name)
-# endif
-
-#else /* dummy fallback */
-
+#if (!HAVE_GL_UTMP \
+ && (HAVE_UTMPX_H ? HAVE_STRUCT_UTMPX_UT_NAME \
+ : HAVE_UTMP_H && HAVE_STRUCT_UTMP_UT_NAME))
+# define UT_USER(UT) ((UT)->ut_name)
+#else
# define UT_USER(UT) ((UT)->ut_user)
-
#endif
-#if READUTMP_USE_SYSTEMD
-# define HAVE_STRUCT_XTMP_UT_EXIT 0
-#else
-# define HAVE_STRUCT_XTMP_UT_EXIT \
- (HAVE_STRUCT_UTMP_UT_EXIT \
- || HAVE_STRUCT_UTMPX_UT_EXIT)
-#endif
+#define HAVE_STRUCT_XTMP_UT_EXIT \
+ (!HAVE_GL_UTMP && (HAVE_STRUCT_UTMP_UT_EXIT || HAVE_STRUCT_UTMPX_UT_EXIT)
-#if READUTMP_USE_SYSTEMD
-# define HAVE_STRUCT_XTMP_UT_ID 1
-#else
-# define HAVE_STRUCT_XTMP_UT_ID \
- (HAVE_STRUCT_UTMP_UT_ID \
- || HAVE_STRUCT_UTMPX_UT_ID)
-#endif
+#define HAVE_STRUCT_XTMP_UT_ID \
+ (HAVE_GL_UTMP || HAVE_STRUCT_UTMP_UT_ID || HAVE_STRUCT_UTMPX_UT_ID)
-#if READUTMP_USE_SYSTEMD
-# define HAVE_STRUCT_XTMP_UT_PID 1
-#else
-# define HAVE_STRUCT_XTMP_UT_PID \
- (HAVE_STRUCT_UTMP_UT_PID \
- || HAVE_STRUCT_UTMPX_UT_PID)
-#endif
+#define HAVE_STRUCT_XTMP_UT_PID \
+ (HAVE_GL_UTMP || HAVE_STRUCT_UTMP_UT_PID || HAVE_STRUCT_UTMPX_UT_PID)
-#if READUTMP_USE_SYSTEMD
-# define HAVE_STRUCT_XTMP_UT_HOST 1
-#else
-# define HAVE_STRUCT_XTMP_UT_HOST \
- (HAVE_STRUCT_UTMP_UT_HOST \
- || HAVE_STRUCT_UTMPX_UT_HOST)
-#endif
+#define HAVE_STRUCT_XTMP_UT_HOST \
+ (HAVE_GL_UTMP || HAVE_STRUCT_UTMP_UT_HOST || HAVE_STRUCT_UTMPX_UT_HOST)
/* Type of entry returned by read_utmp(). */
typedef struct UTMP_STRUCT_NAME STRUCT_UTMP;
/* Size of the UT_USER (ut) member, or -1 if unbounded. */
-#if READUTMP_USE_SYSTEMD
+#if HAVE_GL_UTMP
enum { UT_USER_SIZE = -1 };
#else
enum { UT_USER_SIZE = sizeof UT_USER ((STRUCT_UTMP *) 0) };
@@ -270,7 +209,7 @@ enum { UT_USER_SIZE = sizeof UT_USER ((STRUCT_UTMP *) 0) };
#endif
/* Size of the ut->ut_id member, or -1 if unbounded. */
-#if READUTMP_USE_SYSTEMD
+#if HAVE_GL_UTMP
enum { UT_ID_SIZE = -1 };
#else
enum { UT_ID_SIZE = sizeof (((STRUCT_UTMP *) 0)->ut_id) };
@@ -278,7 +217,7 @@ enum { UT_ID_SIZE = sizeof (((STRUCT_UTMP *) 0)->ut_id) };
#endif
/* Size of the ut->ut_line member, or -1 if unbounded. */
-#if READUTMP_USE_SYSTEMD
+#if HAVE_GL_UTMP
enum { UT_LINE_SIZE = -1 };
#else
enum { UT_LINE_SIZE = sizeof (((STRUCT_UTMP *) 0)->ut_line) };
@@ -286,7 +225,7 @@ enum { UT_LINE_SIZE = sizeof (((STRUCT_UTMP *) 0)->ut_line) };
#endif
/* Size of the ut->ut_host member, or -1 if unbounded. */
-#if READUTMP_USE_SYSTEMD
+#if HAVE_GL_UTMP
enum { UT_HOST_SIZE = -1 };
#else
enum { UT_HOST_SIZE = sizeof (((STRUCT_UTMP *) 0)->ut_host) };
@@ -330,7 +269,7 @@ enum { UT_HOST_SIZE = sizeof (((STRUCT_UTMP *) 0)->ut_host) };
/* Accessor macros for the member named ut_type. */
-#if READUTMP_USE_SYSTEMD || HAVE_STRUCT_UTMP_UT_TYPE || HAVE_STRUCT_UTMPX_UT_TYPE
+#if HAVE_GL_UTMP || HAVE_STRUCT_UTMP_UT_TYPE || HAVE_STRUCT_UTMPX_UT_TYPE
# define UT_TYPE_EQ(UT, V) ((UT)->ut_type == (V))
# define UT_TYPE_NOT_DEFINED 0
#else
diff --git a/modules/readutmp b/modules/readutmp
index 534ce4fa19..15c63a3d5e 100644
--- a/modules/readutmp
+++ b/modules/readutmp
@@ -9,14 +9,15 @@ m4/systemd.m4
Depends-on:
extensions
+fopen-gnu
idx
-xalloc
stdbool
stdint
strnlen
-sys_time
-fopen-gnu
+time-h
+timespec_get
unlocked-io-internal
+xalloc
configure.ac:
gl_READUTMP
--
2.39.2
From 9765d190a95f379c1b690ccbf6f3cb1a62f1c803 Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Thu, 3 Aug 2023 16:01:52 -0700
Subject: [PATCH 7/9] readutmp: systemd supports only UTMP_FILE
* lib/readutmp.c (read_utmp): Fail if not UTMP_FILE.
* m4/systemd.m4 (gl_SYSTEMD_CHOICE): Default to no for now,
since yes means "who /var/log/wtmp" stops working.
---
ChangeLog | 5 +++++
lib/readutmp.c | 7 +++++++
m4/systemd.m4 | 6 +++---
3 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 133f49df97..8730fd9bc8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
2023-08-03 Paul Eggert <egg...@cs.ucla.edu>
+ readutmp: systemd supports only UTMP_FILE
+ * lib/readutmp.c (read_utmp): Fail if not UTMP_FILE.
+ * m4/systemd.m4 (gl_SYSTEMD_CHOICE): Default to no for now,
+ since yes means "who /var/log/wtmp" stops working.
+
readutmp: switch new struct to struct timespec
* lib/readutmp.c (get_boot_time_uncached, get_boot_time)
(add_utmp, read_utmp):
diff --git a/lib/readutmp.c b/lib/readutmp.c
index 113382c636..c692b3854d 100644
--- a/lib/readutmp.c
+++ b/lib/readutmp.c
@@ -305,6 +305,13 @@ int
read_utmp (char const *file, idx_t *n_entries, STRUCT_UTMP **utmp_buf,
int options)
{
+ /* The current implementation can imitate only UTMP_FILE. */
+ if (strcmp (file, UTMP_FILE) != 0)
+ {
+ errno = ENOTSUP;
+ return -1;
+ }
+
/* Fill entries, simulating what a utmp file would contain. */
struct utmp_alloc a = {0};
diff --git a/m4/systemd.m4 b/m4/systemd.m4
index 0c919385b2..c54e2fb47f 100644
--- a/m4/systemd.m4
+++ b/m4/systemd.m4
@@ -1,4 +1,4 @@
-# systemd.m4 serial 1
+# systemd.m4 serial 2
dnl Copyright (C) 2023 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -10,9 +10,9 @@ AC_DEFUN([gl_SYSTEMD_CHOICE],
[
AC_MSG_CHECKING([whether to use systemd APIs])
AC_ARG_ENABLE([systemd],
- [ --disable-systemd do not use systemd APIs],
+ [ --enable-systemd use systemd APIs],
[SYSTEMD_CHOICE="$enableval"],
- [SYSTEMD_CHOICE=yes])
+ [SYSTEMD_CHOICE=no])
AC_MSG_RESULT([$SYSTEMD_CHOICE])
AC_SUBST([SYSTEMD_CHOICE])
])
--
2.39.2
From 8edf2ae3fcf7a20c28142dfada145f4a89808a05 Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Thu, 3 Aug 2023 18:27:35 -0700
Subject: [PATCH 8/9] readutmp: fix comments
---
NEWS | 5 ++++-
lib/readutmp.h | 3 ++-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/NEWS b/NEWS
index f1c9b72aa9..265f9788bc 100644
--- a/NEWS
+++ b/NEWS
@@ -74,8 +74,11 @@ User visible incompatible changes
Date Modules Changes
-2023-08-02 readutmp Some STRUCT_UTMP members can be char *,
+2023-08-03 readutmp Some STRUCT_UTMP members can be char *,
2023-08-01 rather than fixed-length char arrays.
+ On some platforms, the timestamp is ut_ts of type
+ struct timespec, not ut_tv of type struct timeval,
+ and ut_session is pid_t not long.
read_utmp's 2nd arg is now idx_t * not size_t *.
Link additionally with $(READUTMP_LIB).
diff --git a/lib/readutmp.h b/lib/readutmp.h
index b3cfaeb67c..01964d2622 100644
--- a/lib/readutmp.h
+++ b/lib/readutmp.h
@@ -59,7 +59,8 @@
struct gl_utmp
{
- /* All 'char *' here are of arbitrary length and malloc-allocated. */
+ /* All 'char *' here are of arbitrary length and point to storage
+ with lifetime equal to that of this struct. */
char *ut_user; /* User name */
char *ut_id; /* Session ID */
char *ut_line; /* seat / device */
--
2.39.2
From f6aa86ea62cd60141e918142bf3ba9fda8ee2463 Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Thu, 3 Aug 2023 18:41:52 -0700
Subject: [PATCH 9/9] * m4/systemd.m4: Fix --help lineup.
---
m4/systemd.m4 | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/m4/systemd.m4 b/m4/systemd.m4
index c54e2fb47f..4a0931f0f2 100644
--- a/m4/systemd.m4
+++ b/m4/systemd.m4
@@ -1,4 +1,4 @@
-# systemd.m4 serial 2
+# systemd.m4 serial 3
dnl Copyright (C) 2023 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -10,7 +10,7 @@ AC_DEFUN([gl_SYSTEMD_CHOICE],
[
AC_MSG_CHECKING([whether to use systemd APIs])
AC_ARG_ENABLE([systemd],
- [ --enable-systemd use systemd APIs],
+ [ --enable-systemd use systemd APIs],
[SYSTEMD_CHOICE="$enableval"],
[SYSTEMD_CHOICE=no])
AC_MSG_RESULT([$SYSTEMD_CHOICE])
--
2.39.2
From 0e58c95000114f246db1e44507f0b1dd17d22a1a Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Thu, 3 Aug 2023 18:35:29 -0700
Subject: [PATCH] maint: Update after gnulib module 'readutmp' changed
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
(This patch is coauthored with Bruno Haible,
with original version at <https://bugs.gnu.org/64937#>.)
This updates the gnulib submodule to latest.
For year-2038 safety on Linux/{x86,arm},
this adds an --enable-systemd option to ‘configure’.
The idea is that this sort of thing will become the default
after it has been tested more.
* configure.ac: Don't test whether struct utmp and struct utmpx
have the ut_host field; this is now done in gnulib's readutmp module.
* src/local.mk: Link the programs 'pinky', 'uptime', 'users',
'who' with $(READUTMP_LIB).
* src/pinky.c, src/who.c:
Test HAVE_STRUCT_XTMP_UT_HOST instead of HAVE_UT_HOST.
* src/pinky.c (print_entry):
* src/who.c (print_user, print_deadprocs, print_login)
(print_initspawn, scan_entries):
Support the situation where ut_line is a 'char *' rather than a
'char[]' of fixed size. Likewise for ut_user and ut_host.
(make_id_equals_comment): Likewise for ut_id.
* src/pinky.c (print_entry):
* src/who.c (print_user):
Open /dev to simplify looking up its entries.
Don’t use printf if the output might in theory be longer than INT_MAX.
* src/pinky.c (scan_entries, short_pinky):
* src/uptime.c (print_uptime, uptime):
* src/users.c (list_entries_users, users):
* src/who.c (who):
Use idx_t where new read_utmp needs it.
* src/system.h (STREQ_LEN): Add comment that last arg can be -1.
---
NEWS | 4 ++
configure.ac | 30 ------------
gnulib | 2 +-
src/local.mk | 6 +++
src/pinky.c | 95 +++++++++++++++++++++++++-------------
src/system.h | 2 +-
src/uptime.c | 4 +-
src/users.c | 10 ++--
src/who.c | 127 ++++++++++++++++++++++++++++++---------------------
9 files changed, 159 insertions(+), 121 deletions(-)
diff --git a/NEWS b/NEWS
index 2b8f984ba..53a342a5e 100644
--- a/NEWS
+++ b/NEWS
@@ -41,6 +41,10 @@ GNU coreutils NEWS -*- outline -*-
pinky, uptime, users, and who no longer misbehave on 32-bit GNU/Linux
platforms like x86 and ARM where time_t was historically 32 bits.
+ A new configure-time option --enable-systemd enables experimental
+ support for using systemd, to let these programs continue to work on
+ these old platforms even after the year 2038, so long as systemd
+ is also installed.
[bug introduced in coreutils-9.0]
'pr --length=1 --double-space' no longer enters an infinite loop.
diff --git a/configure.ac b/configure.ac
index 33441a82f..afc1098f7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -406,36 +406,6 @@ AC_DEFUN([coreutils_DUMMY_1],
])
coreutils_DUMMY_1
-AC_MSG_CHECKING([ut_host in struct utmp])
-AC_CACHE_VAL([su_cv_func_ut_host_in_utmp],
-[AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
- #include <utmp.h>
- struct utmp ut;
- int s = sizeof ut.ut_host;]])],
- [su_cv_func_ut_host_in_utmp=yes],
- [su_cv_func_ut_host_in_utmp=no])])
-AC_MSG_RESULT([$su_cv_func_ut_host_in_utmp])
-if test $su_cv_func_ut_host_in_utmp = yes; then
- have_ut_host=1
- AC_DEFINE([HAVE_UT_HOST], [1], [FIXME])
-fi
-
-if test -z "$have_ut_host"; then
- AC_MSG_CHECKING([ut_host in struct utmpx])
- AC_CACHE_VAL([su_cv_func_ut_host_in_utmpx],
- [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
- #include <utmpx.h>
- struct utmpx ut;
- int s = sizeof ut.ut_host;]])],
- [su_cv_func_ut_host_in_utmpx=yes],
- [su_cv_func_ut_host_in_utmpx=no])])
- AC_MSG_RESULT([$su_cv_func_ut_host_in_utmpx])
- if test $su_cv_func_ut_host_in_utmpx = yes; then
- AC_DEFINE([HAVE_UTMPX_H], [1], [FIXME])
- AC_DEFINE([HAVE_UT_HOST], [1], [FIXME])
- fi
-fi
-
GNULIB_BOOT_TIME([gl_ADD_PROG([optional_bin_progs], [uptime])])
AC_SYS_POSIX_TERMIOS()
diff --git a/gnulib b/gnulib
index 0e7af0cff..f6aa86ea6 160000
--- a/gnulib
+++ b/gnulib
@@ -1 +1 @@
-Subproject commit 0e7af0cff0011f25f5f842af5216325923017b34
+Subproject commit f6aa86ea62cd60141e918142bf3ba9fda8ee2463
diff --git a/src/local.mk b/src/local.mk
index cb9b39274..4d7df2789 100644
--- a/src/local.mk
+++ b/src/local.mk
@@ -317,6 +317,12 @@ src_who_LDADD += $(GETADDRINFO_LIB)
src_hostname_LDADD += $(GETHOSTNAME_LIB)
src_uname_LDADD += $(GETHOSTNAME_LIB)
+# for read_utmp
+src_pinky_LDADD += $(READUTMP_LIB)
+src_uptime_LDADD += $(READUTMP_LIB)
+src_users_LDADD += $(READUTMP_LIB)
+src_who_LDADD += $(READUTMP_LIB)
+
# for strsignal
src_kill_LDADD += $(LIBTHREAD)
diff --git a/src/pinky.c b/src/pinky.c
index b6d411c85..38ceccbea 100644
--- a/src/pinky.c
+++ b/src/pinky.c
@@ -62,7 +62,7 @@ static bool include_home_and_shell = true;
static bool do_short_format = true;
/* if true, display the ut_host field. */
-#ifdef HAVE_UT_HOST
+#if HAVE_STRUCT_XTMP_UT_HOST
static bool include_where = true;
#endif
@@ -203,20 +203,32 @@ print_entry (const STRUCT_UTMP *utmp_ent)
time_t last_change;
char mesg;
-#define DEV_DIR_WITH_TRAILING_SLASH "/dev/"
-#define DEV_DIR_LEN (sizeof (DEV_DIR_WITH_TRAILING_SLASH) - 1)
-
- char line[sizeof (utmp_ent->ut_line) + DEV_DIR_LEN + 1];
- char *p = line;
+#ifdef UT_LINE_SIZE
+ char line[UT_LINE_SIZE + 1];
+ stzncpy (line, utmp_ent->ut_line, UT_LINE_SIZE);
+#else
+ /* If ut_line contains a space, the device name starts after the space. */
+ char *line = utmp_ent->ut_line;
+ char *space = strchr (line, ' ');
+ line = space ? space + 1 : line;
+#endif
- /* Copy ut_line into LINE, prepending '/dev/' if ut_line is not
- already an absolute file name. Some system may put the full,
- absolute file name in ut_line. */
- if ( ! IS_ABSOLUTE_FILE_NAME (utmp_ent->ut_line))
- p = stpcpy (p, DEV_DIR_WITH_TRAILING_SLASH);
- stzncpy (p, utmp_ent->ut_line, sizeof (utmp_ent->ut_line));
+ int dirfd;
+ if (IS_ABSOLUTE_FILE_NAME (line))
+ dirfd = AT_FDCWD;
+ else
+ {
+ static int dev_dirfd;
+ if (!dev_dirfd)
+ {
+ dev_dirfd = open ("/dev", O_PATHSEARCH | O_DIRECTORY);
+ if (dev_dirfd < 0)
+ dev_dirfd = AT_FDCWD - 1;
+ }
+ dirfd = dev_dirfd;
+ }
- if (stat (line, &stats) == 0)
+ if (AT_FDCWD <= dirfd && fstatat (dirfd, line, &stats, 0) == 0)
{
mesg = (stats.st_mode & S_IWGRP) ? ' ' : '*';
last_change = stats.st_atime;
@@ -227,15 +239,20 @@ print_entry (const STRUCT_UTMP *utmp_ent)
last_change = 0;
}
- printf ("%-8.*s", UT_USER_SIZE, UT_USER (utmp_ent));
+ if (0 <= UT_USER_SIZE || strnlen (UT_USER (utmp_ent), 8) < 8)
+ printf ("%-8.*s", UT_USER_SIZE, UT_USER (utmp_ent));
+ else
+ fputs (UT_USER (utmp_ent), stdout);
if (include_fullname)
{
- struct passwd *pw;
+#ifdef UT_USER_SIZE
char name[UT_USER_SIZE + 1];
-
stzncpy (name, UT_USER (utmp_ent), UT_USER_SIZE);
- pw = getpwnam (name);
+#else
+ char *name = UT_USER (utmp_ent);
+#endif
+ struct passwd *pw = getpwnam (name);
if (pw == nullptr)
/* TRANSLATORS: Real name is unknown; at most 19 characters. */
printf (" %19s", _(" ???"));
@@ -253,8 +270,12 @@ print_entry (const STRUCT_UTMP *utmp_ent)
}
}
- printf (" %c%-8.*s",
- mesg, (int) sizeof (utmp_ent->ut_line), utmp_ent->ut_line);
+ fputc (' ', stdout);
+ fputc (mesg, stdout);
+ if (0 <= UT_LINE_SIZE || strnlen (utmp_ent->ut_line, 8) < 8)
+ printf ("%-8.*s", UT_LINE_SIZE, utmp_ent->ut_line);
+ else
+ fputs (utmp_ent->ut_line, stdout);
if (include_idle)
{
@@ -267,15 +288,18 @@ print_entry (const STRUCT_UTMP *utmp_ent)
printf (" %s", time_string (utmp_ent));
-#ifdef HAVE_UT_HOST
+#ifdef HAVE_STRUCT_XTMP_UT_HOST
if (include_where && utmp_ent->ut_host[0])
{
- char ut_host[sizeof (utmp_ent->ut_host) + 1];
char *host = nullptr;
char *display = nullptr;
- /* Copy the host name into UT_HOST, and ensure it's nul terminated. */
- stzncpy (ut_host, utmp_ent->ut_host, sizeof (utmp_ent->ut_host));
+# ifdef UT_HOST_SIZE
+ char ut_host[UT_HOST_SIZE + 1];
+ stzncpy (ut_host, utmp_ent->ut_host, UT_HOST_SIZE);
+# else
+ char *ut_host = utmp_ent->ut_host;
+# endif
/* Look for an X display. */
display = strchr (ut_host, ':');
@@ -288,10 +312,13 @@ print_entry (const STRUCT_UTMP *utmp_ent)
if ( ! host)
host = ut_host;
+ fputc (' ', stdout);
+ fputs (host, stdout);
if (display)
- printf (" %s:%s", host, display);
- else
- printf (" %s", host);
+ {
+ fputc (':', stdout);
+ fputs (display, stdout);
+ }
if (host != ut_host)
free (host);
@@ -408,17 +435,23 @@ print_heading (void)
if (include_idle)
printf (" %-6s", _("Idle"));
printf (" %-*s", time_format_width, _("When"));
-#ifdef HAVE_UT_HOST
+#ifdef HAVE_STRUCT_XTMP_UT_HOST
if (include_where)
printf (" %s", _("Where"));
#endif
putchar ('\n');
}
+/* Work around <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109614>,
+ triggered by STREQ_LEN with a negative length. */
+#if 11 <= __GNUC__
+# pragma GCC diagnostic ignored "-Wstringop-overread"
+#endif
+
/* Display UTMP_BUF, which should have N entries. */
static void
-scan_entries (size_t n, const STRUCT_UTMP *utmp_buf,
+scan_entries (idx_t n, const STRUCT_UTMP *utmp_buf,
const int argc_names, char *const argv_names[])
{
if (hard_locale (LC_TIME))
@@ -461,7 +494,7 @@ static void
short_pinky (char const *filename,
const int argc_names, char *const argv_names[])
{
- size_t n_users;
+ idx_t n_users;
STRUCT_UTMP *utmp_buf = nullptr;
if (read_utmp (filename, &n_users, &utmp_buf, 0) != 0)
@@ -550,14 +583,14 @@ main (int argc, char **argv)
case 'i':
include_fullname = false;
-#ifdef HAVE_UT_HOST
+#ifdef HAVE_STRUCT_XTMP_UT_HOST
include_where = false;
#endif
break;
case 'q':
include_fullname = false;
-#ifdef HAVE_UT_HOST
+#ifdef HAVE_STRUCT_XTMP_UT_HOST
include_where = false;
#endif
include_idle = false;
diff --git a/src/system.h b/src/system.h
index b5ec074e7..7b736604b 100644
--- a/src/system.h
+++ b/src/system.h
@@ -192,7 +192,7 @@ select_plural (uintmax_t n)
}
#define STREQ(a, b) (strcmp (a, b) == 0)
-#define STREQ_LEN(a, b, n) (strncmp (a, b, n) == 0)
+#define STREQ_LEN(a, b, n) (strncmp (a, b, n) == 0) /* n==-1 means unbounded */
#define STRPREFIX(a, b) (strncmp (a, b, strlen (b)) == 0)
/* Just like strncmp, but the second argument must be a literal string
diff --git a/src/uptime.c b/src/uptime.c
index bdbf1451a..ad1bbb9a1 100644
--- a/src/uptime.c
+++ b/src/uptime.c
@@ -45,7 +45,7 @@
proper_name ("Kaveh Ghazi")
static void
-print_uptime (size_t n, const STRUCT_UTMP *this)
+print_uptime (idx_t n, const STRUCT_UTMP *this)
{
idx_t entries = 0;
time_t boot_time = 0;
@@ -169,7 +169,7 @@ print_uptime (size_t n, const STRUCT_UTMP *this)
static _Noreturn void
uptime (char const *filename, int options)
{
- size_t n_users;
+ idx_t n_users;
STRUCT_UTMP *utmp_buf = nullptr;
if (read_utmp (filename, &n_users, &utmp_buf, options) != 0)
diff --git a/src/users.c b/src/users.c
index e14f3fc3e..353c1765d 100644
--- a/src/users.c
+++ b/src/users.c
@@ -42,11 +42,11 @@ userid_compare (const void *v_a, const void *v_b)
}
static void
-list_entries_users (size_t n, const STRUCT_UTMP *this)
+list_entries_users (idx_t n, const STRUCT_UTMP *this)
{
- char **u = xnmalloc (n, sizeof *u);
- size_t i;
- size_t n_entries = 0;
+ char **u = xinmalloc (n, sizeof *u);
+ idx_t i;
+ idx_t n_entries = 0;
while (n--)
{
@@ -82,7 +82,7 @@ list_entries_users (size_t n, const STRUCT_UTMP *this)
static void
users (char const *filename, int options)
{
- size_t n_users;
+ idx_t n_users;
STRUCT_UTMP *utmp_buf;
if (read_utmp (filename, &n_users, &utmp_buf, options) != 0)
diff --git a/src/who.c b/src/who.c
index ec0dff792..0e94d3c83 100644
--- a/src/who.c
+++ b/src/who.c
@@ -333,26 +333,38 @@ print_user (const STRUCT_UTMP *utmp_ent, time_t boottime)
time_t last_change;
char mesg;
char idlestr[IDLESTR_LEN + 1];
+ PIDSTR_DECL_AND_INIT (pidstr, utmp_ent);
static char *hoststr;
-#if HAVE_UT_HOST
- static size_t hostlen;
+#if HAVE_STRUCT_XTMP_UT_HOST
+ static idx_t hostlen;
#endif
-#define DEV_DIR_WITH_TRAILING_SLASH "/dev/"
-#define DEV_DIR_LEN (sizeof (DEV_DIR_WITH_TRAILING_SLASH) - 1)
-
- char line[sizeof (utmp_ent->ut_line) + DEV_DIR_LEN + 1];
- char *p = line;
- PIDSTR_DECL_AND_INIT (pidstr, utmp_ent);
+#ifdef UT_LINE_SIZE
+ char line[UT_LINE_SIZE + 1];
+ stzncpy (line, utmp_ent->ut_line, UT_LINE_SIZE);
+#else
+ /* If ut_line contains a space, the device name starts after the space. */
+ char *line = utmp_ent->ut_line;
+ char *space = strchr (line, ' ');
+ line = space ? space + 1 : line;
+#endif
- /* Copy ut_line into LINE, prepending '/dev/' if ut_line is not
- already an absolute file name. Some systems may put the full,
- absolute file name in ut_line. */
- if ( ! IS_ABSOLUTE_FILE_NAME (utmp_ent->ut_line))
- p = stpcpy (p, DEV_DIR_WITH_TRAILING_SLASH);
- stzncpy (p, utmp_ent->ut_line, sizeof (utmp_ent->ut_line));
+ int dirfd;
+ if (IS_ABSOLUTE_FILE_NAME (line))
+ dirfd = AT_FDCWD;
+ else
+ {
+ static int dev_dirfd;
+ if (!dev_dirfd)
+ {
+ dev_dirfd = open ("/dev", O_PATHSEARCH | O_DIRECTORY);
+ if (dev_dirfd < 0)
+ dev_dirfd = AT_FDCWD - 1;
+ }
+ dirfd = dev_dirfd;
+ }
- if (stat (line, &stats) == 0)
+ if (AT_FDCWD <= dirfd && fstatat (dirfd, line, &stats, 0) == 0)
{
mesg = is_tty_writable (&stats) ? '+' : '-';
last_change = stats.st_atime;
@@ -368,15 +380,18 @@ print_user (const STRUCT_UTMP *utmp_ent, time_t boottime)
else
sprintf (idlestr, " ?");
-#if HAVE_UT_HOST
+#if HAVE_STRUCT_XTMP_UT_HOST
if (utmp_ent->ut_host[0])
{
- char ut_host[sizeof (utmp_ent->ut_host) + 1];
char *host = nullptr;
char *display = nullptr;
- /* Copy the host name into UT_HOST, and ensure it's nul terminated. */
- stzncpy (ut_host, utmp_ent->ut_host, sizeof (utmp_ent->ut_host));
+# ifdef UT_HOST_SIZE
+ char ut_host[UT_HOST_SIZE + 1];
+ stzncpy (ut_host, utmp_ent->ut_host, UT_HOST_SIZE);
+# else
+ char *ut_host = utmp_ent->ut_host;
+# endif
/* Look for an X display. */
display = strchr (ut_host, ':');
@@ -394,23 +409,29 @@ print_user (const STRUCT_UTMP *utmp_ent, time_t boottime)
if (display)
{
- if (hostlen < strlen (host) + strlen (display) + 4)
+ idx_t needed = strlen (host) + strlen (display) + 4;
+ if (hostlen < needed)
{
- hostlen = strlen (host) + strlen (display) + 4;
free (hoststr);
- hoststr = xmalloc (hostlen);
+ hoststr = xpalloc (nullptr, &hostlen, needed - hostlen, -1, 1);
}
- sprintf (hoststr, "(%s:%s)", host, display);
+ char *p = hoststr;
+ *p++ = '(';
+ p = stpcpy (p, host);
+ *p++ = ':';
+ strcpy (stpcpy (p, display), ")");
}
else
{
- if (hostlen < strlen (host) + 3)
+ idx_t needed = strlen (host) + 3;
+ if (hostlen < needed)
{
- hostlen = strlen (host) + 3;
free (hoststr);
- hoststr = xmalloc (hostlen);
+ hoststr = xpalloc (nullptr, &hostlen, needed - hostlen, -1, 1);
}
- sprintf (hoststr, "(%s)", host);
+ char *p = hoststr;
+ *p++ = '(';
+ strcpy (stpcpy (p, host), ")");
}
if (host != ut_host)
@@ -419,17 +440,13 @@ print_user (const STRUCT_UTMP *utmp_ent, time_t boottime)
else
{
if (hostlen < 1)
- {
- hostlen = 1;
- free (hoststr);
- hoststr = xmalloc (hostlen);
- }
+ hoststr = xpalloc (hoststr, &hostlen, 1, -1, 1);
*hoststr = '\0';
}
#endif
- print_line (sizeof UT_USER (utmp_ent), UT_USER (utmp_ent), mesg,
- sizeof utmp_ent->ut_line, utmp_ent->ut_line,
+ print_line (UT_USER_SIZE, UT_USER (utmp_ent), mesg,
+ UT_LINE_SIZE, utmp_ent->ut_line,
time_string (utmp_ent), idlestr, pidstr,
hoststr ? hoststr : "", "");
}
@@ -444,11 +461,14 @@ print_boottime (const STRUCT_UTMP *utmp_ent)
static char *
make_id_equals_comment (STRUCT_UTMP const *utmp_ent)
{
- size_t utmpsize = sizeof UT_ID (utmp_ent);
- char *comment = xmalloc (strlen (_("id=")) + utmpsize + 1);
-
- char *p = stpcpy (comment, _("id="));
- stzncpy (p, UT_ID (utmp_ent), utmpsize);
+ char const *id = UT_ID (utmp_ent);
+ idx_t idlen = strnlen (id, UT_ID_SIZE);
+ char const *prefix = _("id=");
+ idx_t prefixlen = strlen (prefix);
+ char *comment = xmalloc (prefixlen + idlen + 1);
+ char *p = mempcpy (comment, prefix, prefixlen);
+ p = mempcpy (p, id, idlen);
+ *p = '\0';
return comment;
}
@@ -470,7 +490,7 @@ print_deadprocs (const STRUCT_UTMP *utmp_ent)
/* FIXME: add idle time? */
- print_line (-1, "", ' ', sizeof utmp_ent->ut_line, utmp_ent->ut_line,
+ print_line (-1, "", ' ', UT_LINE_SIZE, utmp_ent->ut_line,
time_string (utmp_ent), "", pidstr, comment, exitstr);
free (comment);
}
@@ -483,7 +503,7 @@ print_login (const STRUCT_UTMP *utmp_ent)
/* FIXME: add idle time? */
- print_line (-1, _("LOGIN"), ' ', sizeof utmp_ent->ut_line, utmp_ent->ut_line,
+ print_line (-1, _("LOGIN"), ' ', UT_LINE_SIZE, utmp_ent->ut_line,
time_string (utmp_ent), "", pidstr, comment, "");
free (comment);
}
@@ -494,7 +514,7 @@ print_initspawn (const STRUCT_UTMP *utmp_ent)
char *comment = make_id_equals_comment (utmp_ent);
PIDSTR_DECL_AND_INIT (pidstr, utmp_ent);
- print_line (-1, "", ' ', sizeof utmp_ent->ut_line, utmp_ent->ut_line,
+ print_line (-1, "", ' ', UT_LINE_SIZE, utmp_ent->ut_line,
time_string (utmp_ent), "", pidstr, comment, "");
free (comment);
}
@@ -531,9 +551,9 @@ print_runlevel (const STRUCT_UTMP *utmp_ent)
/* Print the username of each valid entry and the number of valid entries
in UTMP_BUF, which should have N elements. */
static void
-list_entries_who (size_t n, const STRUCT_UTMP *utmp_buf)
+list_entries_who (idx_t n, const STRUCT_UTMP *utmp_buf)
{
- unsigned long int entries = 0;
+ idx_t entries = 0;
char const *separator = "";
while (n--)
@@ -551,7 +571,7 @@ list_entries_who (size_t n, const STRUCT_UTMP *utmp_buf)
}
utmp_buf++;
}
- printf (_("\n# users=%lu\n"), entries);
+ printf (_("\n# users=%td\n"), entries);
}
static void
@@ -561,9 +581,15 @@ print_heading (void)
_("PID"), _("COMMENT"), _("EXIT"));
}
+/* Work around <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109614>,
+ triggered by STREQ_LEN with a negative length. */
+#if 11 <= __GNUC__
+# pragma GCC diagnostic ignored "-Wstringop-overread"
+#endif
+
/* Display UTMP_BUF, which should have N entries. */
static void
-scan_entries (size_t n, const STRUCT_UTMP *utmp_buf)
+scan_entries (idx_t n, const STRUCT_UTMP *utmp_buf)
{
char *ttyname_b IF_LINT ( = nullptr);
time_t boottime = TYPE_MINIMUM (time_t);
@@ -576,15 +602,14 @@ scan_entries (size_t n, const STRUCT_UTMP *utmp_buf)
ttyname_b = ttyname (STDIN_FILENO);
if (!ttyname_b)
return;
- if (STRNCMP_LIT (ttyname_b, DEV_DIR_WITH_TRAILING_SLASH) == 0)
- ttyname_b += DEV_DIR_LEN; /* Discard /dev/ prefix. */
+ if (STRNCMP_LIT (ttyname_b, "/dev/") == 0)
+ ttyname_b += sizeof "/dev/" - 1; /* Discard /dev/ prefix. */
}
while (n--)
{
if (!my_line_only
- || STREQ_LEN (ttyname_b, utmp_buf->ut_line,
- sizeof (utmp_buf->ut_line)))
+ || STREQ_LEN (ttyname_b, utmp_buf->ut_line, UT_LINE_SIZE))
{
if (need_users && IS_USER_PROCESS (utmp_buf))
print_user (utmp_buf, boottime);
@@ -617,7 +642,7 @@ scan_entries (size_t n, const STRUCT_UTMP *utmp_buf)
static void
who (char const *filename, int options)
{
- size_t n_users;
+ idx_t n_users;
STRUCT_UTMP *utmp_buf;
if (read_utmp (filename, &n_users, &utmp_buf, options) != 0)
--
2.39.2