diff --git a/CRT.c b/CRT.c index 149cd519b..0a7666da4 100644 --- a/CRT.c +++ b/CRT.c @@ -129,6 +129,7 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { [FAILED_READ] = A_BOLD | ColorPair(Red, Black), [PAUSED] = A_BOLD | ColorPair(Yellow, Cyan), [UPTIME] = A_BOLD | ColorPair(Cyan, Black), + [FLEX] = A_BOLD | ColorPair(Cyan, Black), [BATTERY] = A_BOLD | ColorPair(Cyan, Black), [LARGE_NUMBER] = A_BOLD | ColorPair(Red, Black), [METER_SHADOW] = A_BOLD | ColorPairGrayBlack, @@ -247,6 +248,7 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { [FAILED_READ] = A_BOLD, [PAUSED] = A_BOLD | A_REVERSE, [UPTIME] = A_BOLD, + [FLEX] = A_BOLD, [BATTERY] = A_BOLD, [LARGE_NUMBER] = A_BOLD, [METER_SHADOW] = A_DIM, @@ -365,6 +367,7 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { [FAILED_READ] = ColorPair(Red, White), [PAUSED] = A_BOLD | ColorPair(Yellow, Cyan), [UPTIME] = ColorPair(Yellow, White), + [FLEX] = ColorPair(Yellow, White), [BATTERY] = ColorPair(Yellow, White), [LARGE_NUMBER] = ColorPair(Red, White), [METER_SHADOW] = ColorPair(Blue, White), @@ -483,6 +486,7 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { [FAILED_READ] = ColorPair(Red, Black), [PAUSED] = A_BOLD | ColorPair(Yellow, Cyan), [UPTIME] = ColorPair(Yellow, Black), + [FLEX] = ColorPair(Yellow, Black), [BATTERY] = ColorPair(Yellow, Black), [LARGE_NUMBER] = ColorPair(Red, Black), [METER_SHADOW] = A_BOLD | ColorPairGrayBlack, @@ -601,6 +605,7 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { [FAILED_READ] = A_BOLD | ColorPair(Red, Blue), [PAUSED] = A_BOLD | ColorPair(Yellow, Cyan), [UPTIME] = A_BOLD | ColorPair(Yellow, Blue), + [FLEX] = A_BOLD | ColorPair(Yellow, Blue), [BATTERY] = A_BOLD | ColorPair(Yellow, Blue), [LARGE_NUMBER] = A_BOLD | ColorPair(Red, Blue), [METER_SHADOW] = ColorPair(Cyan, Blue), @@ -719,6 +724,7 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { [FAILED_READ] = A_BOLD | ColorPair(Red, Black), [PAUSED] = A_BOLD | ColorPair(Yellow, Green), [UPTIME] = ColorPair(Green, Black), + [FLEX] = ColorPair(Green, Black), [BATTERY] = ColorPair(Green, Black), [LARGE_NUMBER] = A_BOLD | ColorPair(Red, Black), [METER_SHADOW] = A_BOLD | ColorPairGrayBlack, diff --git a/CRT.h b/CRT.h index eb3df1d7f..5d27a2a7c 100644 --- a/CRT.h +++ b/CRT.h @@ -154,6 +154,7 @@ typedef enum ColorElements_ { DYNAMIC_MAGENTA, DYNAMIC_YELLOW, DYNAMIC_WHITE, + FLEX, LAST_COLORELEMENT } ColorElements; diff --git a/FlexMeter.c b/FlexMeter.c new file mode 100644 index 000000000..93f74cf38 --- /dev/null +++ b/FlexMeter.c @@ -0,0 +1,205 @@ +/* +htop - FlexMeter.c +(C) 2024 Stoyan Bogdanov +Released under the GNU GPLv2+, see the COPYING file +in the source distribution for its full text. +*/ + +#include +#include +#include +#include +#include +#include +#include "FlexMeter.h" +#include "Object.h" +#include "config.h" +#include "CRT.h" + +#define FLEX_CFG_FOLDER ".config/htop/FlexMeter" + +typedef struct { + char* name; + char* command; + char* type; + char* caption; + char* uiName; +}_flex_meter; + +_flex_meter meter_list[30]; + +int meter_list_idx=0; +static int meters_count=0; + +static const int DateMeter_attributes[] = { + FLEX +}; + +MeterClass * FlexMeter_class = NULL; + +int check_for_meters(void); + +static int parse_input(char * line) +{ + if (!strncmp(line,"name=",5)) + { + meter_list[meters_count].uiName = xStrdup(line+5); + } + else if (!strncmp(line,"command=",7)) + { + meter_list[meters_count].command = xStrdup(line+8); + } + else if (!strncmp(line,"caption=",7)) + { + meter_list[meters_count].caption = xStrdup(line+8); + } + else if (!strncmp(line,"type=",5)) + { + meter_list[meters_count].type = xStrdup(line+6); + } + else + { + return -1; + } + + return 0; +} + +static int load_config(char * file) +{ + int ret = -1; + char *buff; + FILE *fp = fopen( file , "r"); + + if (fp != NULL) { + while(1) + { + buff = String_readLine(fp); + if (buff!=NULL) + parse_input(buff); + else + break; + } + + fclose(fp); + ret = 0; + } + + return ret; +} + +int check_for_meters(void) +{ + char path[400]; // full path + DIR *d; + struct dirent *dir; + struct passwd *pw = getpwuid(getuid()); + const char *homedir = pw->pw_dir; + + // path to home folder 1 for zero 1 for slash + char * home = (char * ) xCalloc(1,(strlen(homedir) + strlen(FLEX_CFG_FOLDER) + 2)); + + xSnprintf(home,(strlen(homedir) + strlen(FLEX_CFG_FOLDER) + 2),"%s/%s",homedir,FLEX_CFG_FOLDER); + + d = opendir(home); + if (d) { + while ((dir = readdir(d)) != NULL) { + if ( dir->d_name[0]!='.') + { + // We are ignoring all files starting with . like ".Template" and "." ".." directories + meter_list[meters_count].name = xStrdup(dir->d_name); + memset(path,0,80); + xSnprintf(path,400,"%s/%s",home,dir->d_name); + if( 0 != load_config(path) ) + { + break; + } + + if ( meters_count < MAX_METERS_COUNT ) + { + meters_count++; + } + else + { + break; // go out we reach the limit + } + } + } + closedir(d); + } + else + { + mkdir(home,0700); + } + + free(home); + return meters_count; +} + +static void FlexMeter_updateValues(Meter* this) +{ + for (int i =0 ; i < meters_count; i++) + { + if (this->m_ptr == &FlexMeter_class[i] ) + { + char buff[256]={0}; + int ret = -1; + memset(buff,0,256); + if ( meter_list[i].command[0] != 0 ) + { + FILE* fd = popen(meter_list[i].command, "r"); + if (fd) + { + if (fgets(buff, 256, fd) == NULL) + ret = pclose(fd); + else + ret = pclose(fd); + } + + if( (buff[0] != 0) && (ret == 0) ) + { + int l = strlen(buff); + buff[l-1] = '\0'; + xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%s",buff); + } + else + { + xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%s", "Read CMD ERR"); + } + } + } + } +} + +const MeterClass FlexMeter_class_template = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete + }, + .updateValues = FlexMeter_updateValues, + .defaultMode = TEXT_METERMODE, + .maxItems = 1, + .total = 100, + .attributes = DateMeter_attributes, + .name = NULL, + .uiName = NULL, + .caption = NULL, +}; + +int load_flex_modules(void) +{ + uint8_t meters_num = check_for_meters(); + if (FlexMeter_class == NULL && meters_num!=0) + { + FlexMeter_class = (MeterClass*) xCalloc(meters_num,sizeof(MeterClass)); + for (uint8_t i=0 ; ihost->settings; Header_setLayout(this, settings->hLayout); + int num = load_flex_modules(); + int platform_size = 0; + + for (platform_size = 0; Platform_meterTypes[platform_size] != NULL; platform_size++); + for (int i = 0; i < num; i++) Platform_meterTypes[platform_size+i]=FlexMeter_class+i; + + Platform_meterTypes[platform_size+num]=NULL; + Header_forEachColumn(this, col) { const MeterColumnSetting* colSettings = &settings->hColumns[col]; Vector_prune(this->columns[col]); diff --git a/Makefile.am b/Makefile.am index 2580252b8..1adb93a74 100644 --- a/Makefile.am +++ b/Makefile.am @@ -91,7 +91,8 @@ myhtopsources = \ UptimeMeter.c \ UsersTable.c \ Vector.c \ - XUtils.c + XUtils.c \ + FlexMeter.c myhtopheaders = \ Action.h \ @@ -163,7 +164,8 @@ myhtopheaders = \ UptimeMeter.h \ UsersTable.h \ Vector.h \ - XUtils.h + XUtils.h \ + FlexMeter.h # Linux # ----- diff --git a/Meter.c b/Meter.c index 3dbdfcc66..25c0940cb 100644 --- a/Meter.c +++ b/Meter.c @@ -377,6 +377,7 @@ Meter* Meter_new(const Machine* host, unsigned int param, const MeterClass* type this->values = type->maxItems ? xCalloc(type->maxItems, sizeof(double)) : NULL; this->total = type->total; this->caption = xStrdup(type->caption); + this->m_ptr = type; if (Meter_initFn(this)) { Meter_init(this); } diff --git a/Meter.h b/Meter.h index 0d93759f6..6ab1d8a85 100644 --- a/Meter.h +++ b/Meter.h @@ -67,9 +67,9 @@ typedef struct MeterClass_ { const MeterModeId defaultMode; const double total; const int* const attributes; - const char* const name; /* internal name of the meter, must not contain any space */ - const char* const uiName; /* display name in header setup menu */ - const char* const caption; /* prefix in the actual header */ + const char* name; /* internal name of the meter, must not contain any space */ + const char* uiName; /* display name in header setup menu */ + const char* caption; /* prefix in the actual header */ const char* const description; /* optional meter description in header setup menu */ const uint8_t maxItems; const bool isMultiColumn; /* whether the meter draws multiple sub-columns (defaults to false) */ @@ -102,8 +102,9 @@ typedef struct GraphData_ { struct Meter_ { Object super; Meter_Draw draw; - const Machine* host; + const Machine* host; + const MeterClass * m_ptr; char* caption; MeterModeId mode; unsigned int param; diff --git a/configure.ac b/configure.ac index 81836e8e7..13d1ee0c9 100644 --- a/configure.ac +++ b/configure.ac @@ -25,6 +25,7 @@ AM_INIT_AUTOMAKE([-Wall std-options subdir-objects]) # ---------------------------------------------------------------------- +AC_DEFINE([MAX_PLATFORM_METERS], [100], [Set max meters for number]) # ---------------------------------------------------------------------- # Checks for platform. diff --git a/darwin/Platform.c b/darwin/Platform.c index ba31a59f8..97c1334cc 100644 --- a/darwin/Platform.c +++ b/darwin/Platform.c @@ -53,6 +53,7 @@ in the source distribution for its full text. #include "generic/fdstat_sysctl.h" #include "zfs/ZfsArcMeter.h" #include "zfs/ZfsCompressedArcMeter.h" +#include "FlexMeter.h" #ifdef HAVE_HOST_GET_CLOCK_SERVICE #include @@ -112,7 +113,7 @@ const SignalItem Platform_signals[] = { const unsigned int Platform_numberOfSignals = ARRAYSIZE(Platform_signals); -const MeterClass* const Platform_meterTypes[] = { +const MeterClass* Platform_meterTypes[MAX_PLATFORM_METERS] = { &CPUMeter_class, &ClockMeter_class, &DateMeter_class, diff --git a/darwin/Platform.h b/darwin/Platform.h index f67db8ff4..bac3187fc 100644 --- a/darwin/Platform.h +++ b/darwin/Platform.h @@ -34,7 +34,7 @@ extern const SignalItem Platform_signals[]; extern const unsigned int Platform_numberOfSignals; -extern const MeterClass* const Platform_meterTypes[]; +extern const MeterClass* Platform_meterTypes[MAX_PLATFORM_METERS]; bool Platform_init(void); diff --git a/docs/FlexMeter/Template b/docs/FlexMeter/Template new file mode 100644 index 000000000..7ad3015f4 --- /dev/null +++ b/docs/FlexMeter/Template @@ -0,0 +1,4 @@ +name=template +command=echo "`uptime`" +type=TEXT_METERMODE +caption="UPTIME" \ No newline at end of file diff --git a/dragonflybsd/Platform.c b/dragonflybsd/Platform.c index f3412ef9e..1aac00aa7 100644 --- a/dragonflybsd/Platform.c +++ b/dragonflybsd/Platform.c @@ -42,7 +42,7 @@ in the source distribution for its full text. #include "dragonflybsd/DragonFlyBSDProcess.h" #include "dragonflybsd/DragonFlyBSDProcessTable.h" #include "generic/fdstat_sysctl.h" - +#include "FlexMeter.h" const ScreenDefaults Platform_defaultScreens[] = { { @@ -93,7 +93,7 @@ const SignalItem Platform_signals[] = { const unsigned int Platform_numberOfSignals = ARRAYSIZE(Platform_signals); -const MeterClass* const Platform_meterTypes[] = { +const MeterClass* Platform_meterTypes[MAX_PLATFORM_METERS] = { &CPUMeter_class, &ClockMeter_class, &DateMeter_class, diff --git a/dragonflybsd/Platform.h b/dragonflybsd/Platform.h index 606b004c0..343f67849 100644 --- a/dragonflybsd/Platform.h +++ b/dragonflybsd/Platform.h @@ -37,7 +37,7 @@ extern const SignalItem Platform_signals[]; extern const unsigned int Platform_numberOfSignals; -extern const MeterClass* const Platform_meterTypes[]; +extern const MeterClass* Platform_meterTypes[MAX_PLATFORM_METERS]; bool Platform_init(void); diff --git a/freebsd/Platform.c b/freebsd/Platform.c index 9be7195e5..a6dde929d 100644 --- a/freebsd/Platform.c +++ b/freebsd/Platform.c @@ -50,6 +50,7 @@ in the source distribution for its full text. #include "generic/fdstat_sysctl.h" #include "zfs/ZfsArcMeter.h" #include "zfs/ZfsCompressedArcMeter.h" +#include "FlexMeter.h" const ScreenDefaults Platform_defaultScreens[] = { { @@ -100,7 +101,7 @@ const SignalItem Platform_signals[] = { const unsigned int Platform_numberOfSignals = ARRAYSIZE(Platform_signals); -const MeterClass* const Platform_meterTypes[] = { +const MeterClass* Platform_meterTypes[MAX_PLATFORM_METERS] = { &CPUMeter_class, &ClockMeter_class, &DateMeter_class, diff --git a/freebsd/Platform.h b/freebsd/Platform.h index c358d85d3..5604b8111 100644 --- a/freebsd/Platform.h +++ b/freebsd/Platform.h @@ -33,7 +33,7 @@ extern const SignalItem Platform_signals[]; extern const unsigned int Platform_numberOfSignals; -extern const MeterClass* const Platform_meterTypes[]; +extern const MeterClass* Platform_meterTypes[MAX_PLATFORM_METERS]; bool Platform_init(void); diff --git a/linux/Platform.c b/linux/Platform.c index 3316d1dba..157079844 100644 --- a/linux/Platform.c +++ b/linux/Platform.c @@ -64,6 +64,7 @@ in the source distribution for its full text. #include "zfs/ZfsArcMeter.h" #include "zfs/ZfsArcStats.h" #include "zfs/ZfsCompressedArcMeter.h" +#include "FlexMeter.h" #ifdef HAVE_LIBCAP #include @@ -209,7 +210,7 @@ void Platform_setBindings(Htop_Action* keys) { keys[KEY_F(20)] = Platform_actionHigherAutogroupPriority; // Shift-F8 } -const MeterClass* const Platform_meterTypes[] = { +const MeterClass* Platform_meterTypes[MAX_PLATFORM_METERS] = { &CPUMeter_class, &ClockMeter_class, &DateMeter_class, diff --git a/linux/Platform.h b/linux/Platform.h index e99d1a226..a8fcb1594 100644 --- a/linux/Platform.h +++ b/linux/Platform.h @@ -47,7 +47,8 @@ extern const SignalItem Platform_signals[]; extern const unsigned int Platform_numberOfSignals; -extern const MeterClass* const Platform_meterTypes[]; +extern const MeterClass* Platform_meterTypes[MAX_PLATFORM_METERS]; + bool Platform_init(void); void Platform_done(void); diff --git a/netbsd/Platform.c b/netbsd/Platform.c index f458c239f..62ca5241b 100644 --- a/netbsd/Platform.c +++ b/netbsd/Platform.c @@ -57,6 +57,7 @@ in the source distribution for its full text. #include "generic/fdstat_sysctl.h" #include "netbsd/NetBSDMachine.h" #include "netbsd/NetBSDProcess.h" +#include "FlexMeter.h" /* * The older proplib APIs will be deprecated in NetBSD 10, but we still @@ -152,7 +153,7 @@ const SignalItem Platform_signals[] = { const unsigned int Platform_numberOfSignals = ARRAYSIZE(Platform_signals); -const MeterClass* const Platform_meterTypes[] = { +const MeterClass* Platform_meterTypes[MAX_PLATFORM_METERS] = { &CPUMeter_class, &ClockMeter_class, &DateMeter_class, diff --git a/netbsd/Platform.h b/netbsd/Platform.h index a543f52dd..509e324e8 100644 --- a/netbsd/Platform.h +++ b/netbsd/Platform.h @@ -43,7 +43,7 @@ extern const SignalItem Platform_signals[]; extern const unsigned int Platform_numberOfSignals; -extern const MeterClass* const Platform_meterTypes[]; +extern const MeterClass* Platform_meterTypes[MAX_PLATFORM_METERS]; bool Platform_init(void); diff --git a/openbsd/Platform.c b/openbsd/Platform.c index a8b5d212d..0ec6e13a2 100644 --- a/openbsd/Platform.c +++ b/openbsd/Platform.c @@ -46,7 +46,7 @@ in the source distribution for its full text. #include "XUtils.h" #include "openbsd/OpenBSDMachine.h" #include "openbsd/OpenBSDProcess.h" - +#include "FlexMeter.h" const ScreenDefaults Platform_defaultScreens[] = { { @@ -100,7 +100,7 @@ const SignalItem Platform_signals[] = { const unsigned int Platform_numberOfSignals = ARRAYSIZE(Platform_signals); -const MeterClass* const Platform_meterTypes[] = { +const MeterClass* Platform_meterTypes[MAX_PLATFORM_METERS] = { &CPUMeter_class, &ClockMeter_class, &DateMeter_class, diff --git a/openbsd/Platform.h b/openbsd/Platform.h index 339616c11..3e8527201 100644 --- a/openbsd/Platform.h +++ b/openbsd/Platform.h @@ -35,7 +35,7 @@ extern const SignalItem Platform_signals[]; extern const unsigned int Platform_numberOfSignals; -extern const MeterClass* const Platform_meterTypes[]; +extern const MeterClass* Platform_meterTypes[MAX_PLATFORM_METERS]; bool Platform_init(void); diff --git a/pcp/Platform.c b/pcp/Platform.c index d50edd254..2973e7ac4 100644 --- a/pcp/Platform.c +++ b/pcp/Platform.c @@ -54,7 +54,7 @@ in the source distribution for its full text. #include "zfs/ZfsArcMeter.h" #include "zfs/ZfsArcStats.h" #include "zfs/ZfsCompressedArcMeter.h" - +#include "FlexMeter.h" Platform* pcp; @@ -79,7 +79,7 @@ const SignalItem Platform_signals[] = { const unsigned int Platform_numberOfSignals = ARRAYSIZE(Platform_signals); -const MeterClass* const Platform_meterTypes[] = { +const MeterClass* Platform_meterTypes[MAX_PLATFORM_METERS] = { &CPUMeter_class, &DynamicMeter_class, &ClockMeter_class, diff --git a/pcp/Platform.h b/pcp/Platform.h index f43ed54f2..53dfcce25 100644 --- a/pcp/Platform.h +++ b/pcp/Platform.h @@ -68,7 +68,7 @@ extern const SignalItem Platform_signals[]; extern const unsigned int Platform_numberOfSignals; -extern const MeterClass* const Platform_meterTypes[]; +extern const MeterClass* Platform_meterTypes[MAX_PLATFORM_METERS]; bool Platform_init(void); diff --git a/solaris/Platform.c b/solaris/Platform.c index 3934f7896..b287b3ada 100644 --- a/solaris/Platform.c +++ b/solaris/Platform.c @@ -42,7 +42,7 @@ in the source distribution for its full text. #include "zfs/ZfsArcMeter.h" #include "zfs/ZfsCompressedArcMeter.h" - +#include "FlexMeter.h" const ScreenDefaults Platform_defaultScreens[] = { { @@ -101,7 +101,9 @@ const SignalItem Platform_signals[] = { const unsigned int Platform_numberOfSignals = ARRAYSIZE(Platform_signals); -const MeterClass* const Platform_meterTypes[] = { +const ProcessField Platform_defaultFields[] = { PID, LWPID, USER, PRIORITY, NICE, M_VIRT, M_RESIDENT, STATE, PERCENT_CPU, PERCENT_MEM, TIME, COMM, 0 }; + +const MeterClass* Platform_meterTypes[MAX_PLATFORM_METERS] = { &CPUMeter_class, &ClockMeter_class, &DateMeter_class, diff --git a/solaris/Platform.h b/solaris/Platform.h index 1a31c2e7a..2702f4949 100644 --- a/solaris/Platform.h +++ b/solaris/Platform.h @@ -58,7 +58,9 @@ extern const SignalItem Platform_signals[]; extern const unsigned int Platform_numberOfSignals; -extern const MeterClass* const Platform_meterTypes[]; +extern const ProcessField Platform_defaultFields[]; + +extern const MeterClass* Platform_meterTypes[MAX_PLATFORM_METERS]; bool Platform_init(void); diff --git a/unsupported/Platform.c b/unsupported/Platform.c index dbfddd916..ed98c4793 100644 --- a/unsupported/Platform.c +++ b/unsupported/Platform.c @@ -26,7 +26,7 @@ in the source distribution for its full text. #include "SysArchMeter.h" #include "TasksMeter.h" #include "UptimeMeter.h" - +#include "FlexMeter.h" const ScreenDefaults Platform_defaultScreens[] = { { @@ -44,7 +44,9 @@ const SignalItem Platform_signals[] = { const unsigned int Platform_numberOfSignals = ARRAYSIZE(Platform_signals); -const MeterClass* const Platform_meterTypes[] = { +const ProcessField Platform_defaultFields[] = { PID, USER, PRIORITY, NICE, M_VIRT, M_RESIDENT, STATE, PERCENT_CPU, PERCENT_MEM, TIME, COMM, 0 }; + +const MeterClass* Platform_meterTypes[MAX_PLATFORM_METERS] = { &CPUMeter_class, &ClockMeter_class, &DateMeter_class, diff --git a/unsupported/Platform.h b/unsupported/Platform.h index c4cd06a04..f61ddd063 100644 --- a/unsupported/Platform.h +++ b/unsupported/Platform.h @@ -31,7 +31,9 @@ extern const SignalItem Platform_signals[]; extern const unsigned int Platform_numberOfSignals; -extern const MeterClass* const Platform_meterTypes[]; +extern const ProcessField Platform_defaultFields[]; + +extern const MeterClass* Platform_meterTypes[MAX_PLATFORM_METERS]; bool Platform_init(void);