bug-coreutils
[Top][All Lists]
Advanced

[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








reply via email to

[Prev in Thread] Current Thread [Next in Thread]