From c0a858b24839d69858a5418f30971fd355b42fc4 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Thu, 3 Aug 2023 16:01:50 -0700 Subject: [PATCH] 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 , 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 + 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 , 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 #include +#include /* 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 +#endif -/* Get 'struct timeval'. */ -# include +/* 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 +#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 - +# 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 -# 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 # 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 # 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 - -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.5