diff --git a/Makefile.am b/Makefile.am index ed92afac4..43e1b4770 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 @@ -380,9 +400,11 @@ endif # ------- solaris_platform_headers = \ + UserSessionsMeter.h \ generic/gettime.h \ generic/hostname.h \ generic/uname.h \ + generic/utmpx.h \ solaris/ProcessField.h \ solaris/Platform.h \ solaris/SolarisMachine.h \ @@ -393,9 +415,11 @@ solaris_platform_headers = \ zfs/ZfsCompressedArcMeter.h solaris_platform_sources = \ + UserSessionsMeter.c \ generic/gettime.c \ generic/hostname.c \ generic/uname.c \ + generic/utmpx.c \ solaris/Platform.c \ solaris/SolarisMachine.c \ solaris/SolarisProcess.c \ diff --git a/UserSessionsMeter.c b/UserSessionsMeter.c new file mode 100644 index 000000000..138a83bd5 --- /dev/null +++ b/UserSessionsMeter.c @@ -0,0 +1,157 @@ +/* +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 + +# ifdef HTOP_LINUX +static int (*sym_sd_get_sessions)(char***); +static void* dlopenHandle; +static size_t activeHandles; +# endif /* HTOP_LINUX */ + +#endif /* BUILD_STATIC */ + + +static void UserSessionsMeter_init(ATTR_UNUSED Meter* this) { +#if !defined(BUILD_STATIC) && defined(HTOP_LINUX) + 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 && HTOP_LINUX */ +} + +static void UserSessionsMeter_done(ATTR_UNUSED Meter* this) { +#if !defined(BUILD_STATIC) && defined(HTOP_LINUX) + if (activeHandles > 0) { + activeHandles--; + if (activeHandles == 0) { + Platform_close_libsystemd(); + dlopenHandle = NULL; + } + } +#endif /* !BUILD_STATIC && HTOP_LINUX */ +} + +#if (!defined(BUILD_STATIC) && defined(HTOP_LINUX)) || 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 && HTOP_LINUX) || HAVE_LIBSYSTEMD */ + +static void UserSessionsMeter_updateValues(Meter* this) { + int ret; +#if (!defined(BUILD_STATIC) && defined(HTOP_LINUX)) || 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 && HTOP_LINUX) || 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 }; diff --git a/solaris/Platform.c b/solaris/Platform.c index 5faa91ae7..2b3ae70dd 100644 --- a/solaris/Platform.c +++ b/solaris/Platform.c @@ -36,6 +36,7 @@ in the source distribution for its full text. #include "HostnameMeter.h" #include "SysArchMeter.h" #include "UptimeMeter.h" +#include "UserSessionsMeter.h" #include "XUtils.h" #include "solaris/SolarisMachine.h" @@ -130,6 +131,7 @@ const MeterClass* const Platform_meterTypes[] = { &RightCPUs8Meter_class, &ZfsArcMeter_class, &ZfsCompressedArcMeter_class, + &UserSessionsMeter_class, &BlankMeter_class, NULL };