diff --git a/Generic.c b/Generic.c new file mode 100644 index 00000000..185ecb41 --- /dev/null +++ b/Generic.c @@ -0,0 +1,102 @@ +/* +htop - Generic.c +(C) 2021 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.h" + +#include +#ifdef HAVE_SYS_UTSNAME_H +#include +#endif +#include + +#include "XUtils.h" + +void Generic_Hostname(char* buffer, size_t size) { + gethostname(buffer, size - 1); +} + +#ifdef HAVE_SYS_UTSNAME_H + +#ifndef OSRELEASEFILE +#define OSRELEASEFILE "/etc/os-release" +#endif + +static void parseOSRelease(char* buffer, size_t bufferLen) { + FILE* stream = fopen(OSRELEASEFILE, "r"); + if (!stream) { + xSnprintf(buffer, bufferLen, "No OS Release"); + return; + } + + char name[64] = {'\0'}; + char version[64] = {'\0'}; + char lineBuffer[256]; + while (fgets(lineBuffer, sizeof(lineBuffer), stream)) { + if (String_startsWith(lineBuffer, "PRETTY_NAME=\"")) { + const char* start = lineBuffer + strlen("PRETTY_NAME=\""); + const char* stop = strrchr(lineBuffer, '"'); + if (!stop || stop <= start) + continue; + String_safeStrncpy(buffer, start, MINIMUM(bufferLen, (size_t)(stop - start + 1))); + fclose(stream); + return; + } + if (String_startsWith(lineBuffer, "NAME=\"")) { + const char* start = lineBuffer + strlen("NAME=\""); + const char* stop = strrchr(lineBuffer, '"'); + if (!stop || stop <= start) + continue; + String_safeStrncpy(name, start, MINIMUM(sizeof(name), (size_t)(stop - start + 1))); + continue; + } + if (String_startsWith(lineBuffer, "VERSION=\"")) { + const char* start = lineBuffer + strlen("VERSION=\""); + const char* stop = strrchr(lineBuffer, '"'); + if (!stop || stop <= start) + continue; + String_safeStrncpy(version, start, MINIMUM(sizeof(version), (size_t)(stop - start + 1))); + continue; + } + } + fclose(stream); + + snprintf(buffer, bufferLen, "%s%s%s", name[0] ? name : "", name[0] && version[0] ? " " : "", version); +} + +char* Generic_OSRelease(void) { + static struct utsname uname_info; + + static char savedString[ + /* uname structure fields - manpages recommend sizeof */ + sizeof(uname_info.sysname) + + sizeof(uname_info.release) + + sizeof(uname_info.machine) + + 16/*markup*/ + + 128/*distro*/] = {'\0'}; + static bool loaded_data = false; + + if (!loaded_data) { + int uname_result = uname(&uname_info); + + char distro[128]; + parseOSRelease(distro, sizeof(distro)); + + if (uname_result == 0) { + size_t written = xSnprintf(savedString, sizeof(savedString), "%s %s [%s]", uname_info.sysname, uname_info.release, uname_info.machine); + if (!String_contains_i(savedString, distro) && sizeof(savedString) > written) + snprintf(savedString + written, sizeof(savedString) - written, " @ %s", distro); + } else { + snprintf(savedString, sizeof(savedString), "%s", distro); + } + + loaded_data = true; + } + + return savedString; +} +#endif diff --git a/Generic.h b/Generic.h new file mode 100644 index 00000000..44adc09e --- /dev/null +++ b/Generic.h @@ -0,0 +1,16 @@ +#ifndef HEADER_Generic +#define HEADER_Generic +/* +htop - Generic.h +(C) 2021 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include + +void Generic_Hostname(char* buffer, size_t size); + +char* Generic_OSRelease(void); + +#endif diff --git a/HostnameMeter.c b/HostnameMeter.c index af8e3493..924def11 100644 --- a/HostnameMeter.c +++ b/HostnameMeter.c @@ -8,6 +8,7 @@ in the source distribution for its full text. #include "config.h" // IWYU pragma: keep #include "HostnameMeter.h" +#include "Platform.h" #include @@ -19,9 +20,8 @@ static const int HostnameMeter_attributes[] = { HOSTNAME }; -static void HostnameMeter_updateValues(Meter* this, char* buffer, size_t size) { - (void) this; - gethostname(buffer, size - 1); +static void HostnameMeter_updateValues(ATTR_UNUSED Meter* this, char* buffer, size_t size) { + Platform_getHostname(buffer, size); } const MeterClass HostnameMeter_class = { diff --git a/Makefile.am b/Makefile.am index 0498fc8a..082f6e7a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -42,6 +42,7 @@ myhtopsources = \ DisplayOptionsPanel.c \ EnvScreen.c \ FunctionBar.c \ + Generic.c \ Hashtable.c \ Header.c \ HostnameMeter.c \ @@ -96,6 +97,7 @@ myhtopheaders = \ DisplayOptionsPanel.h \ EnvScreen.h \ FunctionBar.h \ + Generic.h \ Hashtable.h \ Header.h \ HostnameMeter.h \ diff --git a/SysArchMeter.c b/SysArchMeter.c index cc962630..c368e944 100644 --- a/SysArchMeter.c +++ b/SysArchMeter.c @@ -6,90 +6,21 @@ in the source distribution for its full text. */ #include "config.h" // IWYU pragma: keep +#include "Platform.h" #include "SysArchMeter.h" -#include -#include - #include "XUtils.h" static const int SysArchMeter_attributes[] = {HOSTNAME}; -static void parseOSRelease(char* buffer, size_t bufferLen) { - FILE* stream = fopen("/etc/os-release", "r"); - if (!stream) { - stream = fopen("/usr/lib/os-release", "r"); - if (!stream) { - xSnprintf(buffer, bufferLen, "Unknown Distro"); - return; - } - } - - char name[64] = {'\0'}; - char version[64] = {'\0'}; - char lineBuffer[256]; - while (fgets(lineBuffer, sizeof(lineBuffer), stream)) { - if (String_startsWith(lineBuffer, "PRETTY_NAME=\"")) { - const char* start = lineBuffer + strlen("PRETTY_NAME=\""); - const char* stop = strrchr(lineBuffer, '"'); - if (!stop || stop <= start) - continue; - String_safeStrncpy(buffer, start, MINIMUM(bufferLen, (size_t)(stop - start + 1))); - fclose(stream); - return; - } - if (String_startsWith(lineBuffer, "NAME=\"")) { - const char* start = lineBuffer + strlen("NAME=\""); - const char* stop = strrchr(lineBuffer, '"'); - if (!stop || stop <= start) - continue; - String_safeStrncpy(name, start, MINIMUM(sizeof(name), (size_t)(stop - start + 1))); - continue; - } - if (String_startsWith(lineBuffer, "VERSION=\"")) { - const char* start = lineBuffer + strlen("VERSION=\""); - const char* stop = strrchr(lineBuffer, '"'); - if (!stop || stop <= start) - continue; - String_safeStrncpy(version, start, MINIMUM(sizeof(version), (size_t)(stop - start + 1))); - continue; - } - } - fclose(stream); - - snprintf(buffer, bufferLen, "%s%s%s", name[0] ? name : "", name[0] && version[0] ? " " : "", version); -} - static void SysArchMeter_updateValues(ATTR_UNUSED Meter* this, char* buffer, size_t size) { - static char savedString[ - /* uname structure fields - manpages recommend sizeof */ - sizeof(((struct utsname*)0)->sysname) + - sizeof(((struct utsname*)0)->release) + - sizeof(((struct utsname*)0)->machine) + - 16/*markup*/ + - 128/*distro*/] = {'\0'}; - static bool loaded_data = false; + static char* string; - if (!loaded_data) { - struct utsname uname_info; - int uname_result = uname(&uname_info); + if (string == NULL) + Platform_getRelease(&string); - char distro[128]; - parseOSRelease(distro, sizeof(distro)); - - if (uname_result == 0) { - size_t written = xSnprintf(savedString, sizeof(savedString), "%s %s [%s]", uname_info.sysname, uname_info.release, uname_info.machine); - if (!String_contains_i(savedString, distro) && sizeof(savedString) > written) - snprintf(savedString + written, sizeof(savedString) - written, " @ %s", distro); - } else { - snprintf(savedString, sizeof(savedString), "%s", distro); - } - - loaded_data = true; - } - - String_safeStrncpy(buffer, savedString, size); + String_safeStrncpy(buffer, string, size); } const MeterClass SysArchMeter_class = { diff --git a/configure.ac b/configure.ac index ee7e8ee5..95b01143 100644 --- a/configure.ac +++ b/configure.ac @@ -108,6 +108,7 @@ AC_CHECK_HEADERS([ \ strings.h \ sys/param.h \ sys/time.h \ + sys/utsname.h \ unistd.h ], [], [AC_MSG_ERROR([can not find required generic header files])]) @@ -316,6 +317,18 @@ case "$enable_hwloc" in ;; esac +AC_ARG_WITH([os-release], + [AS_HELP_STRING([--with-os-release=FILE], + [location of an os-release file @<:@default=/etc/os-release@:>@])], + [], + [with_os_release=/etc/os-release]) +if test -n "$with_os_release" -a ! -f "$with_os_release"; then + if test -f "/usr/lib/os-release"; then + with_os_release="/usr/lib/os-release" + fi +fi +AC_DEFINE_UNQUOTED([OSRELEASEFILE], ["$with_os_release"], [File with OS release details.]) + # ---------------------------------------------------------------------- @@ -608,6 +621,7 @@ AC_MSG_RESULT([ ${PACKAGE_NAME} ${VERSION} platform: $my_htop_platform + os-release file: $with_os_release (Linux) proc directory: $with_proc (Linux) openvz: $enable_openvz (Linux) vserver: $enable_vserver diff --git a/darwin/Platform.h b/darwin/Platform.h index 2a97270a..59c2b9c7 100644 --- a/darwin/Platform.h +++ b/darwin/Platform.h @@ -16,6 +16,7 @@ in the source distribution for its full text. #include "CPUMeter.h" #include "DarwinProcess.h" #include "DiskIOMeter.h" +#include "Generic.h" #include "NetworkIOMeter.h" #include "ProcessLocksScreen.h" #include "SignalsPanel.h" @@ -67,4 +68,12 @@ bool Platform_getNetworkIO(NetworkIOData* data); void Platform_getBattery(double *percent, ACPresence *isOnAC); +static inline void Platform_getHostname(char* buffer, size_t size) { + Generic_Hostname(buffer, size); +} + +static inline void Platform_getRelease(char** string) { + *string = Generic_OSRelease(); +} + #endif diff --git a/dragonflybsd/Platform.h b/dragonflybsd/Platform.h index 1ae13938..4d70e4b7 100644 --- a/dragonflybsd/Platform.h +++ b/dragonflybsd/Platform.h @@ -14,6 +14,7 @@ in the source distribution for its full text. #include "Action.h" #include "BatteryMeter.h" #include "DiskIOMeter.h" +#include "Generic.h" #include "NetworkIOMeter.h" #include "ProcessLocksScreen.h" #include "SignalsPanel.h" @@ -57,4 +58,12 @@ bool Platform_getNetworkIO(NetworkIOData* data); void Platform_getBattery(double* percent, ACPresence* isOnAC); +static inline void Platform_getHostname(char* buffer, size_t size) { + Generic_Hostname(buffer, size); +} + +static inline void Platform_getRelease(char** string) { + *string = Generic_OSRelease(); +} + #endif diff --git a/freebsd/Platform.h b/freebsd/Platform.h index 8f25d83a..4ec130d7 100644 --- a/freebsd/Platform.h +++ b/freebsd/Platform.h @@ -13,6 +13,7 @@ in the source distribution for its full text. #include "Action.h" #include "BatteryMeter.h" #include "DiskIOMeter.h" +#include "Generic.h" #include "Meter.h" #include "NetworkIOMeter.h" #include "Process.h" @@ -62,4 +63,12 @@ bool Platform_getNetworkIO(NetworkIOData* data); void Platform_getBattery(double* percent, ACPresence* isOnAC); +static inline void Platform_getHostname(char* buffer, size_t size) { + Generic_Hostname(buffer, size); +} + +static inline void Platform_getRelease(char** string) { + *string = Generic_OSRelease(); +} + #endif diff --git a/linux/Platform.h b/linux/Platform.h index f932c583..c2a86f73 100644 --- a/linux/Platform.h +++ b/linux/Platform.h @@ -14,6 +14,7 @@ in the source distribution for its full text. #include "Action.h" #include "BatteryMeter.h" #include "DiskIOMeter.h" +#include "Generic.h" #include "Meter.h" #include "NetworkIOMeter.h" #include "Process.h" @@ -72,4 +73,12 @@ bool Platform_getNetworkIO(NetworkIOData* data); void Platform_getBattery(double *percent, ACPresence *isOnAC); +static inline void Platform_getHostname(char* buffer, size_t size) { + Generic_Hostname(buffer, size); +} + +static inline void Platform_getRelease(char** string) { + *string = Generic_OSRelease(); +} + #endif diff --git a/openbsd/Platform.h b/openbsd/Platform.h index 66b804de..ca739988 100644 --- a/openbsd/Platform.h +++ b/openbsd/Platform.h @@ -14,6 +14,7 @@ in the source distribution for its full text. #include "Action.h" #include "BatteryMeter.h" #include "DiskIOMeter.h" +#include "Generic.h" #include "Meter.h" #include "NetworkIOMeter.h" #include "Process.h" @@ -60,4 +61,12 @@ bool Platform_getNetworkIO(NetworkIOData* data); void Platform_getBattery(double* percent, ACPresence* isOnAC); +static inline void Platform_getHostname(char* buffer, size_t size) { + Generic_Hostname(buffer, size); +} + +static inline void Platform_getRelease(char** string) { + *string = Generic_OSRelease(); +} + #endif diff --git a/solaris/Platform.h b/solaris/Platform.h index 08636ef9..d4496bc2 100644 --- a/solaris/Platform.h +++ b/solaris/Platform.h @@ -19,6 +19,7 @@ in the source distribution for its full text. #include "Action.h" #include "BatteryMeter.h" #include "DiskIOMeter.h" +#include "Generic.h" #include "NetworkIOMeter.h" #include "ProcessLocksScreen.h" #include "SignalsPanel.h" @@ -79,4 +80,12 @@ bool Platform_getNetworkIO(NetworkIOData* data); void Platform_getBattery(double* percent, ACPresence* isOnAC); +static inline void Platform_getHostname(char* buffer, size_t size) { + Generic_Hostname(buffer, size); +} + +static inline void Platform_getRelease(char** string) { + *string = Generic_OSRelease(); +} + #endif diff --git a/unsupported/Platform.c b/unsupported/Platform.c index 5791acca..9dc457b7 100644 --- a/unsupported/Platform.c +++ b/unsupported/Platform.c @@ -64,6 +64,8 @@ const MeterClass* const Platform_meterTypes[] = { NULL }; +static const char Platform_unsupported[] = "unsupported"; + void Platform_init(void) { /* no platform-specific setup needed */ } @@ -146,3 +148,11 @@ void Platform_getBattery(double* percent, ACPresence* isOnAC) { *percent = NAN; *isOnAC = AC_ERROR; } + +void Platform_getHostname(char* buffer, size_t size) { + String_safeStrncpy(buffer, Platform_unsupported, size); +} + +void Platform_getRelease(char** string) { + *string = xStrdup(Platform_unsupported); +} diff --git a/unsupported/Platform.h b/unsupported/Platform.h index 9b98fd97..837daca4 100644 --- a/unsupported/Platform.h +++ b/unsupported/Platform.h @@ -57,4 +57,8 @@ bool Platform_getNetworkIO(NetworkIOData* data); void Platform_getBattery(double *percent, ACPresence *isOnAC); +void Platform_getHostname(char* buffer, size_t size); + +void Platform_getRelease(char** string); + #endif