[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#64954: GNU 'uptime' on OpenBSD always prints "0 users"
From: |
Bruno Haible |
Subject: |
bug#64954: GNU 'uptime' on OpenBSD always prints "0 users" |
Date: |
Mon, 31 Jul 2023 16:17:13 +0200 |
I wrote in <https://debbugs.gnu.org/cgi/bugreport.cgi?bug=64954>:
> - Gnulib modules should better provide .h files that can be #included
> on any platform. Thus, it's Gnulib's task to provide a readutmp.h
> and a read_utmp() function that can also be used on native Windows.
Done as follows:
2023-07-31 Bruno Haible <bruno@clisp.org>
readutmp: Make the header file and function usable on all platforms.
* lib/readutmp.h (struct gl_utmp, UTMP_STRUCT_NAME, UT_TIME_MEMBER,
UT_EXIT_E_TERMINATION, UT_EXIT_E_EXIT, UT_USER): Provide fallback
definitions.
(READ_UTMP_SUPPORTED): New macro.
* lib/readutmp.c (read_utmp) [!READ_UTMP_SUPPORTED]: Provide a dummy
definition.
* modules/readutmp (Depends-on): Add sys_time.
(configure.ac): Remove conditional.
(Makefile.am): Compile readutmp.c on all platforms.
(Include): Include readutmp.h on all platforms.
* tests/test-readutmp.c: Include readutmp.h on all platforms.
(main): Invoke read_utmp on all platforms.
diff --git a/lib/readutmp.c b/lib/readutmp.c
index acffe1000e..af43d1ad6b 100644
--- a/lib/readutmp.c
+++ b/lib/readutmp.c
@@ -61,6 +61,8 @@ extract_trimmed_name (const STRUCT_UTMP *ut)
return trimmed_name;
}
+#if READ_UTMP_SUPPORTED
+
/* Is the utmp entry U desired by the user who asked for OPTIONS? */
static bool
@@ -77,12 +79,12 @@ desirable_utmp_entry (STRUCT_UTMP const *u, int options)
return true;
}
-#ifdef UTMP_NAME_FUNCTION
+# if defined UTMP_NAME_FUNCTION
static void
copy_utmp_entry (STRUCT_UTMP *dst, STRUCT_UTMP *src)
{
-#if __GLIBC__ && _TIME_BITS == 64
+# if __GLIBC__ && _TIME_BITS == 64
/* Convert from external form in SRC to internal form in DST.
It is OK to convert now, rather than earlier, before
desirable_utmp_entry was invoked, because desirable_utmp_entry
@@ -119,9 +121,9 @@ copy_utmp_entry (STRUCT_UTMP *dst, STRUCT_UTMP *src)
dst->ut_tv.tv_sec = s->ut_tv.tv_sec;
dst->ut_tv.tv_usec = s->ut_tv.tv_usec;
memcpy (&dst->ut_addr_v6, s->ut_addr_v6, sizeof dst->ut_addr_v6);
-#else
+# else
*dst = *src;
-#endif
+# endif
}
int
@@ -158,7 +160,7 @@ read_utmp (char const *file, size_t *n_entries, STRUCT_UTMP
**utmp_buf,
return 0;
}
-#else
+# else
int
read_utmp (char const *file, size_t *n_entries, STRUCT_UTMP **utmp_buf,
@@ -198,4 +200,16 @@ read_utmp (char const *file, size_t *n_entries,
STRUCT_UTMP **utmp_buf,
return 0;
}
+# endif
+
+#else /* dummy fallback */
+
+int
+read_utmp (char const *file, size_t *n_entries, STRUCT_UTMP **utmp_buf,
+ int options)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
#endif
diff --git a/lib/readutmp.h b/lib/readutmp.h
index 7d2a628135..d710699525 100644
--- a/lib/readutmp.h
+++ b/lib/readutmp.h
@@ -38,6 +38,7 @@
# endif
# if HAVE_UTMPX_H
+
# if HAVE_UTMP_H
/* HPUX 10.20 needs utmp.h, for the definition of e.g., UTMP_FILE. */
# include <utmp.h>
@@ -114,6 +115,24 @@
# endif
# 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_PTR) ((UT_PTR)->ut_tv.tv_sec)
+# define UT_EXIT_E_TERMINATION(U) 0
+# define UT_EXIT_E_EXIT(U) 0
+
# endif
/* Accessor macro for the member named ut_user or ut_name. */
@@ -137,6 +156,10 @@
# define UT_USER(Utmp) ((Utmp)->ut_name)
# endif
+# else /* dummy fallback */
+
+# define UT_USER(Utmp) ((Utmp)->ut_user)
+
# endif
# define HAVE_STRUCT_XTMP_UT_EXIT \
@@ -151,10 +174,14 @@
(HAVE_STRUCT_UTMP_UT_PID \
|| HAVE_STRUCT_UTMPX_UT_PID)
+/* Type of entry returned by read_utmp(). */
typedef struct UTMP_STRUCT_NAME STRUCT_UTMP;
+/* Size of the UT_USER (ut) member. */
enum { UT_USER_SIZE = sizeof UT_USER ((STRUCT_UTMP *) 0) };
+/* Definition of UTMP_FILE and WTMP_FILE. */
+
# if !defined UTMP_FILE && defined _PATH_UTMP
# define UTMP_FILE _PATH_UTMP
# endif
@@ -181,12 +208,15 @@ enum { UT_USER_SIZE = sizeof UT_USER ((STRUCT_UTMP *) 0)
};
# define WTMP_FILE "/etc/wtmp"
# endif
+/* Accessor macro for the member named ut_pid. */
# if HAVE_STRUCT_XTMP_UT_PID
# define UT_PID(U) ((U)->ut_pid)
# else
# define UT_PID(U) 0
# endif
+/* Accessor macros for the member named ut_type. */
+
# if HAVE_STRUCT_UTMP_UT_TYPE || HAVE_STRUCT_UTMPX_UT_TYPE
# define UT_TYPE_EQ(U, V) ((U)->ut_type == (V))
# define UT_TYPE_NOT_DEFINED 0
@@ -207,11 +237,17 @@ enum { UT_USER_SIZE = sizeof UT_USER ((STRUCT_UTMP *) 0)
};
# define UT_TYPE_USER_PROCESS(U) 0
# endif
+/* Determines whether an entry *U corresponds to a user process. */
# define IS_USER_PROCESS(U) \
(UT_USER (U)[0] \
&& (UT_TYPE_USER_PROCESS (U) \
|| (UT_TYPE_NOT_DEFINED && UT_TIME_MEMBER (U) != 0)))
+/* Define if read_utmp is not just a dummy. */
+# if HAVE_UTMPX_H || HAVE_UTMP_H
+# define READ_UTMP_SUPPORTED 1
+# endif
+
/* Options for read_utmp. */
enum
{
diff --git a/modules/readutmp b/modules/readutmp
index 7f84f189ea..4b2de331dc 100644
--- a/modules/readutmp
+++ b/modules/readutmp
@@ -11,23 +11,18 @@ extensions
xalloc
stdbool
stdint
+sys_time
fopen-gnu
unlocked-io-internal
configure.ac:
gl_READUTMP
-gl_CONDITIONAL([GL_COND_OBJ_READUTMP],
- [test $ac_cv_header_utmp_h = yes || test $ac_cv_header_utmpx_h
= yes])
Makefile.am:
-if GL_COND_OBJ_READUTMP
lib_SOURCES += readutmp.c
-endif
Include:
-#if HAVE_UTMPX_H || HAVE_UTMP_H
-#include "readutmp.h"
-#endif
+"readutmp.h"
License:
GPL
diff --git a/tests/test-readutmp.c b/tests/test-readutmp.c
index 1dbf70b351..933808b257 100644
--- a/tests/test-readutmp.c
+++ b/tests/test-readutmp.c
@@ -18,25 +18,23 @@
#include <config.h>
-#if HAVE_UTMPX_H || HAVE_UTMP_H
+#include "readutmp.h"
-# include "readutmp.h"
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
-# include <stddef.h>
-# include <stdio.h>
-# include <stdlib.h>
-# include <string.h>
-# include <time.h>
+#include "xalloc.h"
-# include "xalloc.h"
+#define ELEMENT STRUCT_UTMP
+#define COMPARE(entry1, entry2) \
+ _GL_CMP (UT_TIME_MEMBER (entry1), UT_TIME_MEMBER (entry2))
+#define STATIC static
+#include "array-mergesort.h"
-# define ELEMENT STRUCT_UTMP
-# define COMPARE(entry1, entry2) \
- _GL_CMP (UT_TIME_MEMBER (entry1), UT_TIME_MEMBER (entry2))
-# define STATIC static
-# include "array-mergesort.h"
-
-# include "macros.h"
+#include "macros.h"
int
main (int argc, char *argv[])
@@ -46,7 +44,11 @@ main (int argc, char *argv[])
if (read_utmp (UTMP_FILE, &num_entries, &entries, 0) < 0)
{
+ #if READ_UTMP_SUPPORTED
fprintf (stderr, "Skipping test: cannot open %s\n", UTMP_FILE);
+ #else
+ fprintf (stderr, "Skipping test: neither <utmpx.h> nor <utmp.h> is
available\n");
+ #endif
return 77;
}
@@ -99,16 +101,3 @@ main (int argc, char *argv[])
return 0;
}
-
-#else
-
-# include <stdio.h>
-
-int
-main ()
-{
- fprintf (stderr, "Skipping test: neither <utmpx.h> nor <utmp.h> is
available\n");
- return 77;
-}
-
-#endif