+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.
+
2023-07-30 Bruno Haible <bruno@clisp.org>
readutmp: Add tests.
return trimmed_name;
}
+#if READ_UTMP_SUPPORTED
+
/* Is the utmp entry U desired by the user who asked for OPTIONS? */
static bool
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
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
return 0;
}
-#else
+# else
int
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
# 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>
# 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. */
# 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 \
(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
# 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
# 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
{
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
#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[])
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;
}
return 0;
}
-
-#else
-
-# include <stdio.h>
-
-int
-main ()
-{
- fprintf (stderr, "Skipping test: neither <utmpx.h> nor <utmp.h> is available\n");
- return 77;
-}
-
-#endif