From 9499ecbdad3cf89b95efa150526f19b9394f86fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Tue, 9 Jan 2024 21:02:46 +0100 Subject: [PATCH] Linux: add meter showing the current active user sessions Display the active user sessions either via systemd-logind or utmp. On Linux try to query systemd-login first, and otherwise count only the number of distinct sessions. On other platforms the number of unique sessions can not be determined and the number of all user entries are returned. Suggested in #1363. --- Makefile.am | 24 ++++++- UserSessionsMeter.c | 155 ++++++++++++++++++++++++++++++++++++++++ UserSessionsMeter.h | 16 +++++ configure.ac | 6 +- darwin/Platform.c | 2 + dragonflybsd/Platform.c | 2 + freebsd/Platform.c | 2 + generic/utmpx.c | 64 +++++++++++++++++ generic/utmpx.h | 12 ++++ linux/Platform.c | 37 ++++++++++ linux/Platform.h | 9 ++- linux/SystemdMeter.c | 103 +++++++++++++++----------- netbsd/Platform.c | 2 + 13 files changed, 389 insertions(+), 45 deletions(-) create mode 100644 UserSessionsMeter.c create mode 100644 UserSessionsMeter.h create mode 100644 generic/utmpx.c create mode 100644 generic/utmpx.h diff --git a/Makefile.am b/Makefile.am index ed92afac4..20f570474 100644 --- a/Makefile.am +++ b/Makefile.am @@ -168,9 +168,11 @@ myhtopheaders = \ # ----- linux_platform_headers = \ + UserSessionsMeter.h \ generic/gettime.h \ generic/hostname.h \ generic/uname.h \ + generic/utmpx.h \ linux/CGroupUtils.h \ linux/HugePageMeter.h \ linux/IOPriority.h \ @@ -192,9 +194,11 @@ linux_platform_headers = \ zfs/ZfsCompressedArcMeter.h linux_platform_sources = \ + UserSessionsMeter.c \ generic/gettime.c \ generic/hostname.c \ generic/uname.c \ + generic/utmpx.c \ linux/CGroupUtils.c \ linux/HugePageMeter.c \ linux/IOPriorityPanel.c \ @@ -220,6 +224,7 @@ endif # ------- freebsd_platform_headers = \ + UserSessionsMeter.h \ freebsd/FreeBSDMachine.h \ freebsd/FreeBSDProcessTable.h \ freebsd/FreeBSDProcess.h \ @@ -230,11 +235,13 @@ freebsd_platform_headers = \ generic/hostname.h \ generic/openzfs_sysctl.h \ generic/uname.h \ + generic/utmpx.h \ zfs/ZfsArcMeter.h \ zfs/ZfsArcStats.h \ zfs/ZfsCompressedArcMeter.h freebsd_platform_sources = \ + UserSessionsMeter.c \ freebsd/Platform.c \ freebsd/FreeBSDMachine.c \ freebsd/FreeBSDProcessTable.c \ @@ -244,6 +251,7 @@ freebsd_platform_sources = \ generic/hostname.c \ generic/openzfs_sysctl.c \ generic/uname.c \ + generic/utmpx.c \ zfs/ZfsArcMeter.c \ zfs/ZfsCompressedArcMeter.c @@ -256,6 +264,7 @@ endif # ------------ dragonflybsd_platform_headers = \ + UserSessionsMeter.h \ dragonflybsd/DragonFlyBSDMachine.h \ dragonflybsd/DragonFlyBSDProcessTable.h \ dragonflybsd/DragonFlyBSDProcess.h \ @@ -264,9 +273,11 @@ dragonflybsd_platform_headers = \ generic/fdstat_sysctl.h \ generic/gettime.h \ generic/hostname.h \ - generic/uname.h + generic/uname.h \ + generic/utmpx.h dragonflybsd_platform_sources = \ + UserSessionsMeter.c \ dragonflybsd/DragonFlyBSDMachine.c \ dragonflybsd/DragonFlyBSDProcessTable.c \ dragonflybsd/DragonFlyBSDProcess.c \ @@ -274,7 +285,8 @@ dragonflybsd_platform_sources = \ generic/fdstat_sysctl.c \ generic/gettime.c \ generic/hostname.c \ - generic/uname.c + generic/uname.c \ + generic/utmpx.c if HTOP_DRAGONFLYBSD myhtopplatheaders = $(dragonflybsd_platform_headers) @@ -285,10 +297,12 @@ endif # ------- netbsd_platform_headers = \ + UserSessionsMeter.h \ generic/fdstat_sysctl.h \ generic/gettime.h \ generic/hostname.h \ generic/uname.h \ + generic/utmpx.h \ netbsd/Platform.h \ netbsd/ProcessField.h \ netbsd/NetBSDMachine.h \ @@ -296,10 +310,12 @@ netbsd_platform_headers = \ netbsd/NetBSDProcessTable.h netbsd_platform_sources = \ + UserSessionsMeter.c \ generic/fdstat_sysctl.c \ generic/gettime.c \ generic/hostname.c \ generic/uname.c \ + generic/utmpx.c \ netbsd/Platform.c \ netbsd/NetBSDMachine.c \ netbsd/NetBSDProcess.c \ @@ -341,6 +357,7 @@ endif # ------ darwin_platform_headers = \ + UserSessionsMeter.h \ darwin/DarwinMachine.h \ darwin/DarwinProcess.h \ darwin/DarwinProcessTable.h \ @@ -352,11 +369,13 @@ darwin_platform_headers = \ generic/hostname.h \ generic/openzfs_sysctl.h \ generic/uname.h \ + generic/utmpx.h \ zfs/ZfsArcMeter.h \ zfs/ZfsArcStats.h \ zfs/ZfsCompressedArcMeter.h darwin_platform_sources = \ + UserSessionsMeter.c \ darwin/Platform.c \ darwin/PlatformHelpers.c \ darwin/DarwinMachine.c \ @@ -367,6 +386,7 @@ darwin_platform_sources = \ generic/hostname.c \ generic/openzfs_sysctl.c \ generic/uname.c \ + generic/utmpx.c \ zfs/ZfsArcMeter.c \ zfs/ZfsCompressedArcMeter.c diff --git a/UserSessionsMeter.c b/UserSessionsMeter.c new file mode 100644 index 000000000..019b578c3 --- /dev/null +++ b/UserSessionsMeter.c @@ -0,0 +1,155 @@ +/* +htop - UserSessionsMeter.c +(C) 2024 htop dev team +Released under the GNU GPLv2+, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "UserSessionsMeter.h" + +#include + + +#include "CRT.h" +#include "Macros.h" +#include "Object.h" +#include "RichString.h" +#include "XUtils.h" +#include "generic/utmpx.h" + +#if defined(BUILD_STATIC) && defined(HAVE_LIBSYSTEMD) +#include +#endif + +#ifndef BUILD_STATIC +#include +#include "linux/Platform.h" +#endif + + +static int users = 0; + +#ifdef BUILD_STATIC +#define sym_sd_get_sessions sd_get_sessions +#else + +static int (*sym_sd_get_sessions)(char***); +static void* dlopenHandle; +static size_t activeHandles; + +#endif /* BUILD_STATIC */ + + +static void UserSessionsMeter_init(ATTR_UNUSED Meter* this) { +#ifndef BUILD_STATIC + assert(activeHandles != SIZE_MAX); + assert((dlopenHandle != NULL) == (activeHandles > 0)); + + if (activeHandles > 0) { + activeHandles++; + return; + } + + dlopenHandle = Platform_load_libsystemd(); + if (!dlopenHandle) + return; + + /* Clear any errors */ + dlerror(); + + #define resolve(symbolname) do { \ + *(void **)(&sym_##symbolname) = dlsym(dlopenHandle, #symbolname); \ + if (!sym_##symbolname || dlerror() != NULL) \ + goto dlfailure; \ + } while(0) + + resolve(sd_get_sessions); + + #undef resolve + + activeHandles++; + return; + +dlfailure: + Platform_close_libsystemd(); + dlopenHandle = NULL; +#endif /* !BUILD_STATIC */ +} + +static void UserSessionsMeter_done(ATTR_UNUSED Meter* this) { +#ifndef BUILD_STATIC + if (activeHandles > 0) { + activeHandles--; + if (activeHandles == 0) { + Platform_close_libsystemd(); + dlopenHandle = NULL; + } + } +#endif /* !BUILD_STATIC */ +} + +#if !defined(BUILD_STATIC) || defined(HAVE_LIBSYSTEMD) +static int update_via_sd_login(void) { +#ifndef BUILD_STATIC + if (!dlopenHandle) + return -1; +#endif /* !BUILD_STATIC */ + + return sym_sd_get_sessions(NULL); +} +#endif /* !BUILD_STATIC || HAVE_LIBSYSTEMD */ + +static void UserSessionsMeter_updateValues(Meter* this) { + int ret; +#if !defined(BUILD_STATIC) || defined(HAVE_LIBSYSTEMD) + ret = update_via_sd_login(); + if (ret < 0) + ret = Generic_utmpx_get_users(); +#else + ret = Generic_utmpx_get_users(); +#endif /* !BUILD_STATIC || HAVE_LIBSYSTEMD */ + + users = ret; + + if (users >= 0) { + xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%d", ret); + } else { + xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "N/A"); + } +} + +static void UserSessionsMeter_display(ATTR_UNUSED const Object* cast, RichString* out) { + char buffer[16]; + + if (users >= 0) { + int len = xSnprintf(buffer, sizeof(buffer), "%d", users); + RichString_appendnAscii(out, CRT_colors[METER_VALUE], buffer, len); + } else { + RichString_appendAscii(out, CRT_colors[METER_VALUE], "N/A"); + } +} + +static const int UserSessionsMeter_attributes[] = { + METER_VALUE +}; + +const MeterClass UserSessionsMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = UserSessionsMeter_display + }, + .updateValues = UserSessionsMeter_updateValues, + .init = UserSessionsMeter_init, + .done = UserSessionsMeter_done, + .defaultMode = TEXT_METERMODE, + .maxItems = 0, + .total = 100.0, + .attributes = UserSessionsMeter_attributes, + .name = "Users", + .uiName = "User Sessions", + .description = "Number of currently active user sessions", + .caption = "User sessions: ", +}; diff --git a/UserSessionsMeter.h b/UserSessionsMeter.h new file mode 100644 index 000000000..878b1fa81 --- /dev/null +++ b/UserSessionsMeter.h @@ -0,0 +1,16 @@ +#ifndef HEADER_UserSessionsMeter +#define HEADER_UserSessionsMeter + +/* +htop - UserSessionsMeter.h +(C) 2024 htop dev team +Released under the GNU GPLv2+, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Meter.h" + + +extern const MeterClass UserSessionsMeter_class; + +#endif /* HEADER_UserSessionsMeter */ diff --git a/configure.ac b/configure.ac index fe7f7b399..d94ade151 100644 --- a/configure.ac +++ b/configure.ac @@ -158,7 +158,7 @@ fi]) # Optional Section -AC_CHECK_HEADERS([execinfo.h]) +AC_CHECK_HEADERS([execinfo.h utmpx.h]) if test "$my_htop_platform" = darwin; then AC_CHECK_HEADERS([mach/mach_time.h]) @@ -183,6 +183,8 @@ AC_TYPE_UINT16_T AC_TYPE_UINT32_T AC_TYPE_UINT64_T +AC_CHECK_MEMBERS([struct utmpx.ut_session], [], [], [[#include ]]) + AC_MSG_CHECKING(for alloc_size) old_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -Wno-error -Werror=attributes" @@ -336,7 +338,7 @@ if test "$my_htop_platform" = pcp; then fi if test "$my_htop_platform" = linux && test "x$enable_static" = xyes; then - AC_CHECK_LIB([systemd], [sd_bus_open_system]) + AC_CHECK_LIB([systemd], [sd_bus_open_system], [], [], [-lcap]) fi # ---------------------------------------------------------------------- diff --git a/darwin/Platform.c b/darwin/Platform.c index 387910e16..12e974017 100644 --- a/darwin/Platform.c +++ b/darwin/Platform.c @@ -48,6 +48,7 @@ in the source distribution for its full text. #include "SysArchMeter.h" #include "TasksMeter.h" #include "UptimeMeter.h" +#include "UserSessionsMeter.h" #include "darwin/DarwinMachine.h" #include "darwin/PlatformHelpers.h" #include "generic/fdstat_sysctl.h" @@ -144,6 +145,7 @@ const MeterClass* const Platform_meterTypes[] = { &DiskIOMeter_class, &NetworkIOMeter_class, &FileDescriptorMeter_class, + &UserSessionsMeter_class, &BlankMeter_class, NULL }; diff --git a/dragonflybsd/Platform.c b/dragonflybsd/Platform.c index 25afa8b18..73a7f3eb7 100644 --- a/dragonflybsd/Platform.c +++ b/dragonflybsd/Platform.c @@ -33,6 +33,7 @@ in the source distribution for its full text. #include "SysArchMeter.h" #include "TasksMeter.h" #include "UptimeMeter.h" +#include "UserSessionsMeter.h" #include "XUtils.h" #include "dragonflybsd/DragonFlyBSDProcess.h" #include "dragonflybsd/DragonFlyBSDProcessTable.h" @@ -116,6 +117,7 @@ const MeterClass* const Platform_meterTypes[] = { &LeftCPUs8Meter_class, &RightCPUs8Meter_class, &FileDescriptorMeter_class, + &UserSessionsMeter_class, &BlankMeter_class, NULL }; diff --git a/freebsd/Platform.c b/freebsd/Platform.c index 9be7195e5..eace5417e 100644 --- a/freebsd/Platform.c +++ b/freebsd/Platform.c @@ -45,6 +45,7 @@ in the source distribution for its full text. #include "SysArchMeter.h" #include "TasksMeter.h" #include "UptimeMeter.h" +#include "UserSessionsMeter.h" #include "XUtils.h" #include "freebsd/FreeBSDMachine.h" #include "generic/fdstat_sysctl.h" @@ -133,6 +134,7 @@ const MeterClass* const Platform_meterTypes[] = { &DiskIOMeter_class, &FileDescriptorMeter_class, &NetworkIOMeter_class, + &UserSessionsMeter_class, NULL }; diff --git a/generic/utmpx.c b/generic/utmpx.c new file mode 100644 index 000000000..127cd391d --- /dev/null +++ b/generic/utmpx.c @@ -0,0 +1,64 @@ +/* +htop - generic/utmpx.c +(C) 2024 htop dev team +Released under the GNU GPLv2+, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "generic/utmpx.h" + +#include "Macros.h" +#include "XUtils.h" + +#ifdef HAVE_UTMPX_H +#include +#endif + + +int Generic_utmpx_get_users(void) { +#ifdef HAVE_UTMPX_H + struct utmpx *ut; + int ret = 0; +#ifdef HAVE_STRUCT_UTMPX_UT_SESSION + size_t sessions_cap = 32, sessions_size = 0; + long* sessions = xMallocArray(sessions_cap, sizeof(*sessions)); +#endif /* HAVE_STRUCT_UTMPX_UT_SESSION */ + + setutxent(); + while ((ut = getutxent())) { + if (ut->ut_type == USER_PROCESS) { +#ifdef HAVE_STRUCT_UTMPX_UT_SESSION + bool found = false; + for (size_t i = 0; i < sessions_size; i++) { + if (sessions[i] == ut->ut_session) { + found = true; + break; + } + } + if (!found) { + ret++; + + if (sessions_size +1 >= sessions_cap) { + sessions_cap *= 2; + xReallocArray(sessions, sessions_cap, sizeof(*sessions)); + } + sessions[sessions_size++] = ut->ut_session; + } +#else + ret++; +#endif /* HAVE_STRUCT_UTMPX_UT_SESSION */ + } + } + endutxent(); + +#ifdef HAVE_STRUCT_UTMPX_UT_SESSION + free(sessions); +#endif /* HAVE_STRUCT_UTMPX_UT_SESSION */ + + return ret; +#else + return -1; +#endif /* HAVE_UTMPX_H */ +} diff --git a/generic/utmpx.h b/generic/utmpx.h new file mode 100644 index 000000000..64ca7a5c1 --- /dev/null +++ b/generic/utmpx.h @@ -0,0 +1,12 @@ +#ifndef HEADER_utmpx +#define HEADER_utmpx +/* +htop - generic/utmpx.h +(C) 2024 htop dev team +Released under the GNU GPLv2+, see the COPYING file +in the source distribution for its full text. +*/ + +int Generic_utmpx_get_users(void); + +#endif /* HEADER_utmpx */ diff --git a/linux/Platform.c b/linux/Platform.c index 8dc8bb595..7cd79106a 100644 --- a/linux/Platform.c +++ b/linux/Platform.c @@ -50,6 +50,7 @@ in the source distribution for its full text. #include "SysArchMeter.h" #include "TasksMeter.h" #include "UptimeMeter.h" +#include "UserSessionsMeter.h" #include "XUtils.h" #include "linux/IOPriority.h" #include "linux/IOPriorityPanel.h" @@ -64,6 +65,10 @@ in the source distribution for its full text. #include "zfs/ZfsArcStats.h" #include "zfs/ZfsCompressedArcMeter.h" +#ifndef BUILD_STATIC +#include +#endif + #ifdef HAVE_LIBCAP #include #endif @@ -252,6 +257,7 @@ const MeterClass* const Platform_meterTypes[] = { &SystemdMeter_class, &SystemdUserMeter_class, &FileDescriptorMeter_class, + &UserSessionsMeter_class, NULL }; @@ -1085,3 +1091,34 @@ void Platform_done(void) { LibSensors_cleanup(); #endif } + +#ifndef BUILD_STATIC + +static void* libsystemd_handle; +static size_t libsystemd_loaded; + +void* Platform_load_libsystemd(void) { + assert(libsystemd_loaded != SIZE_MAX); + assert((libsystemd_handle != NULL) == (libsystemd_loaded > 0)); + + if (!libsystemd_handle) + libsystemd_handle = dlopen("libsystemd.so.0", RTLD_LAZY); + + if (libsystemd_handle) + libsystemd_loaded++; + + return libsystemd_handle; +} + +void Platform_close_libsystemd(void) { + assert(libsystemd_handle != NULL); + assert(libsystemd_loaded > 0); + + libsystemd_loaded--; + if (libsystemd_loaded == 0) { + dlclose(libsystemd_handle); + libsystemd_handle = NULL; + } +} + +#endif /* !BUILD_STATIC */ diff --git a/linux/Platform.h b/linux/Platform.h index e99d1a226..7449feb31 100644 --- a/linux/Platform.h +++ b/linux/Platform.h @@ -153,4 +153,11 @@ static inline void Platform_addDynamicScreenAvailableColumns(ATTR_UNUSED Panel* static inline void Platform_dynamicScreensDone(ATTR_UNUSED Hashtable* screens) { } -#endif +#ifndef BUILD_STATIC + +void* Platform_load_libsystemd(void); +void Platform_close_libsystemd(void); + +#endif /* !BUILD_STATIC */ + +#endif /* HEADER_Platform */ diff --git a/linux/SystemdMeter.c b/linux/SystemdMeter.c index e13c64618..253dcd903 100644 --- a/linux/SystemdMeter.c +++ b/linux/SystemdMeter.c @@ -9,7 +9,6 @@ in the source distribution for its full text. #include "linux/SystemdMeter.h" -#include #include #include #include @@ -29,10 +28,16 @@ in the source distribution for its full text. #include #endif +#ifndef BUILD_STATIC +#include +#include "linux/Platform.h" +#endif + #ifdef BUILD_STATIC #define sym_sd_bus_open_system sd_bus_open_system +#define sym_sd_bus_open_user sd_bus_open_user #define sym_sd_bus_get_property_string sd_bus_get_property_string #define sym_sd_bus_get_property_trivial sd_bus_get_property_trivial #define sym_sd_bus_unref sd_bus_unref @@ -46,7 +51,8 @@ static int (*sym_sd_bus_open_user)(sd_bus**); static int (*sym_sd_bus_get_property_string)(sd_bus*, const char*, const char*, const char*, const char*, sd_bus_error*, char**); static int (*sym_sd_bus_get_property_trivial)(sd_bus*, const char*, const char*, const char*, const char*, sd_bus_error*, char, void*); static sd_bus* (*sym_sd_bus_unref)(sd_bus*); -static void* dlopenHandle = NULL; +static void* dlopenHandle; +static size_t activeHandles; #endif /* BUILD_STATIC */ @@ -67,6 +73,46 @@ typedef struct SystemdMeterContext { static SystemdMeterContext_t ctx_system; static SystemdMeterContext_t ctx_user; +static void SystemdMeter_init(ATTR_UNUSED Meter* this) { +#ifndef BUILD_STATIC + assert(activeHandles != SIZE_MAX); + assert((dlopenHandle != NULL) == (activeHandles > 0)); + + if (activeHandles > 0) { + activeHandles++; + return; + } + + dlopenHandle = Platform_load_libsystemd(); + if (!dlopenHandle) + return; + + /* Clear any errors */ + dlerror(); + + #define resolve(symbolname) do { \ + *(void **)(&sym_##symbolname) = dlsym(dlopenHandle, #symbolname); \ + if (!sym_##symbolname || dlerror() != NULL) \ + goto dlfailure; \ + } while(0) + + resolve(sd_bus_open_system); + resolve(sd_bus_open_user); + resolve(sd_bus_get_property_string); + resolve(sd_bus_get_property_trivial); + resolve(sd_bus_unref); + + #undef resolve + + activeHandles++; + return; + +dlfailure: + Platform_close_libsystemd(); + dlopenHandle = NULL; +#endif /* !BUILD_STATIC */ +} + static void SystemdMeter_done(ATTR_UNUSED Meter* this) { SystemdMeterContext_t* ctx = String_eq(Meter_name(this), "SystemdUser") ? &ctx_user : &ctx_system; @@ -77,50 +123,34 @@ static void SystemdMeter_done(ATTR_UNUSED Meter* this) { # ifdef HAVE_LIBSYSTEMD if (ctx->bus) { sym_sd_bus_unref(ctx->bus); + ctx->bus = NULL; } - ctx->bus = NULL; # endif /* HAVE_LIBSYSTEMD */ #else /* BUILD_STATIC */ - if (ctx->bus && dlopenHandle) { + if (ctx->bus) { sym_sd_bus_unref(ctx->bus); + ctx->bus = NULL; } - ctx->bus = NULL; - if (!ctx_system.systemState && !ctx_user.systemState && dlopenHandle) { - dlclose(dlopenHandle); - dlopenHandle = NULL; + if (activeHandles > 0) { + activeHandles--; + if (activeHandles == 0) { + Platform_close_libsystemd(); + dlopenHandle = NULL; + } } #endif /* BUILD_STATIC */ } #if !defined(BUILD_STATIC) || defined(HAVE_LIBSYSTEMD) static int updateViaLib(bool user) { - SystemdMeterContext_t* ctx = user ? &ctx_user : &ctx_system; #ifndef BUILD_STATIC - if (!dlopenHandle) { - dlopenHandle = dlopen("libsystemd.so.0", RTLD_LAZY); - if (!dlopenHandle) - goto dlfailure; - - /* Clear any errors */ - dlerror(); - - #define resolve(symbolname) do { \ - *(void **)(&sym_##symbolname) = dlsym(dlopenHandle, #symbolname); \ - if (!sym_##symbolname || dlerror() != NULL) \ - goto dlfailure; \ - } while(0) - - resolve(sd_bus_open_system); - resolve(sd_bus_open_user); - resolve(sd_bus_get_property_string); - resolve(sd_bus_get_property_trivial); - resolve(sd_bus_unref); - - #undef resolve - } + if (!dlopenHandle) + return -1; #endif /* !BUILD_STATIC */ + SystemdMeterContext_t* ctx = user ? &ctx_user : &ctx_system; + int r; /* Connect to the system bus */ if (!ctx->bus) { @@ -198,15 +228,6 @@ static int updateViaLib(bool user) { sym_sd_bus_unref(ctx->bus); ctx->bus = NULL; return -2; - -#ifndef BUILD_STATIC -dlfailure: - if (dlopenHandle) { - dlclose(dlopenHandle); - dlopenHandle = NULL; - } - return -1; -#endif /* !BUILD_STATIC */ } #endif /* !BUILD_STATIC || HAVE_LIBSYSTEMD */ @@ -405,6 +426,7 @@ const MeterClass SystemdMeter_class = { .display = SystemdMeter_display }, .updateValues = SystemdMeter_updateValues, + .init = SystemdMeter_init, .done = SystemdMeter_done, .defaultMode = TEXT_METERMODE, .maxItems = 0, @@ -423,6 +445,7 @@ const MeterClass SystemdUserMeter_class = { .display = SystemdUserMeter_display }, .updateValues = SystemdMeter_updateValues, + .init = SystemdMeter_init, .done = SystemdMeter_done, .defaultMode = TEXT_METERMODE, .maxItems = 0, diff --git a/netbsd/Platform.c b/netbsd/Platform.c index f458c239f..0074d2519 100644 --- a/netbsd/Platform.c +++ b/netbsd/Platform.c @@ -53,6 +53,7 @@ in the source distribution for its full text. #include "SysArchMeter.h" #include "TasksMeter.h" #include "UptimeMeter.h" +#include "UserSessionsMeter.h" #include "XUtils.h" #include "generic/fdstat_sysctl.h" #include "netbsd/NetBSDMachine.h" @@ -183,6 +184,7 @@ const MeterClass* const Platform_meterTypes[] = { &DiskIOMeter_class, &NetworkIOMeter_class, &FileDescriptorMeter_class, + &UserSessionsMeter_class, NULL };