mirror of https://github.com/xzeldon/htop.git
Merge branch 'master' of https://github.com/hishamhm/htop
This commit is contained in:
commit
d20160cb4f
276
BatteryMeter.c
276
BatteryMeter.c
|
@ -9,14 +9,13 @@ This meter written by Ian P. Hands (iphands@gmail.com, ihands@redhat.com).
|
||||||
|
|
||||||
#include "BatteryMeter.h"
|
#include "BatteryMeter.h"
|
||||||
|
|
||||||
|
#include "Platform.h"
|
||||||
#include "ProcessList.h"
|
#include "ProcessList.h"
|
||||||
#include "CRT.h"
|
#include "CRT.h"
|
||||||
#include "String.h"
|
#include "String.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <dirent.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
/*{
|
/*{
|
||||||
#include "Meter.h"
|
#include "Meter.h"
|
||||||
|
@ -26,273 +25,22 @@ typedef enum ACPresence_ {
|
||||||
AC_PRESENT,
|
AC_PRESENT,
|
||||||
AC_ERROR
|
AC_ERROR
|
||||||
} ACPresence;
|
} ACPresence;
|
||||||
|
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
int BatteryMeter_attributes[] = {
|
int BatteryMeter_attributes[] = {
|
||||||
BATTERY
|
BATTERY
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned long int parseUevent(FILE * file, const char *key) {
|
|
||||||
char line[100];
|
|
||||||
unsigned long int dValue = 0;
|
|
||||||
char* saveptr;
|
|
||||||
|
|
||||||
while (fgets(line, sizeof line, file)) {
|
|
||||||
if (strncmp(line, key, strlen(key)) == 0) {
|
|
||||||
char *value;
|
|
||||||
strtok_r(line, "=", &saveptr);
|
|
||||||
value = strtok_r(NULL, "=", &saveptr);
|
|
||||||
dValue = atoi(value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned long int parseBatInfo(const char *fileName, const unsigned short int lineNum, const unsigned short int wordNum) {
|
|
||||||
const char batteryPath[] = PROCDIR "/acpi/battery/";
|
|
||||||
DIR* batteryDir = opendir(batteryPath);
|
|
||||||
if (!batteryDir)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
#define MAX_BATTERIES 64
|
|
||||||
char* batteries[MAX_BATTERIES];
|
|
||||||
unsigned int nBatteries = 0;
|
|
||||||
memset(batteries, 0, MAX_BATTERIES * sizeof(char*));
|
|
||||||
|
|
||||||
struct dirent result;
|
|
||||||
struct dirent* dirEntry;
|
|
||||||
while (nBatteries < MAX_BATTERIES) {
|
|
||||||
int err = readdir_r(batteryDir, &result, &dirEntry);
|
|
||||||
if (err || !dirEntry)
|
|
||||||
break;
|
|
||||||
char* entryName = dirEntry->d_name;
|
|
||||||
if (strncmp(entryName, "BAT", 3))
|
|
||||||
continue;
|
|
||||||
batteries[nBatteries] = strdup(entryName);
|
|
||||||
nBatteries++;
|
|
||||||
}
|
|
||||||
closedir(batteryDir);
|
|
||||||
|
|
||||||
unsigned long int total = 0;
|
|
||||||
for (unsigned int i = 0; i < nBatteries; i++) {
|
|
||||||
char infoPath[30];
|
|
||||||
snprintf(infoPath, sizeof infoPath, "%s%s/%s", batteryPath, batteries[i], fileName);
|
|
||||||
|
|
||||||
FILE* file = fopen(infoPath, "r");
|
|
||||||
if (!file) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
char line[50] = "";
|
|
||||||
for (unsigned short int i = 0; i < lineNum; i++) {
|
|
||||||
char* ok = fgets(line, sizeof line, file);
|
|
||||||
if (!ok) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(file);
|
|
||||||
|
|
||||||
char *foundNumStr = String_getToken(line, wordNum);
|
|
||||||
const unsigned long int foundNum = atoi(foundNumStr);
|
|
||||||
free(foundNumStr);
|
|
||||||
|
|
||||||
total += foundNum;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < nBatteries; i++) {
|
|
||||||
free(batteries[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return total;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ACPresence procAcpiCheck() {
|
|
||||||
ACPresence isOn = AC_ERROR;
|
|
||||||
const char *power_supplyPath = PROCDIR "/acpi/ac_adapter";
|
|
||||||
DIR *power_supplyDir = opendir(power_supplyPath);
|
|
||||||
if (!power_supplyDir) {
|
|
||||||
return AC_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct dirent result;
|
|
||||||
struct dirent* dirEntry;
|
|
||||||
for (;;) {
|
|
||||||
int err = readdir_r((DIR *) power_supplyDir, &result, &dirEntry);
|
|
||||||
if (err || !dirEntry)
|
|
||||||
break;
|
|
||||||
|
|
||||||
char* entryName = (char *) dirEntry->d_name;
|
|
||||||
|
|
||||||
if (entryName[0] != 'A')
|
|
||||||
continue;
|
|
||||||
|
|
||||||
char statePath[50];
|
|
||||||
snprintf((char *) statePath, sizeof statePath, "%s/%s/state", power_supplyPath, entryName);
|
|
||||||
FILE* file = fopen(statePath, "r");
|
|
||||||
|
|
||||||
if (!file) {
|
|
||||||
isOn = AC_ERROR;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
char line[100];
|
|
||||||
fgets(line, sizeof line, file);
|
|
||||||
line[sizeof(line) - 1] = '\0';
|
|
||||||
|
|
||||||
fclose(file);
|
|
||||||
|
|
||||||
const char *isOnline = String_getToken(line, 2);
|
|
||||||
|
|
||||||
if (strcmp(isOnline, "on-line") == 0) {
|
|
||||||
isOn = AC_PRESENT;
|
|
||||||
} else {
|
|
||||||
isOn = AC_ABSENT;
|
|
||||||
}
|
|
||||||
free((char *) isOnline);
|
|
||||||
if (isOn == AC_PRESENT) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (power_supplyDir)
|
|
||||||
closedir(power_supplyDir);
|
|
||||||
return isOn;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ACPresence sysCheck() {
|
|
||||||
ACPresence isOn = AC_ERROR;
|
|
||||||
const char *power_supplyPath = "/sys/class/power_supply";
|
|
||||||
DIR *power_supplyDir = opendir(power_supplyPath);
|
|
||||||
if (!power_supplyDir) {
|
|
||||||
return AC_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct dirent result;
|
|
||||||
struct dirent* dirEntry;
|
|
||||||
for (;;) {
|
|
||||||
int err = readdir_r((DIR *) power_supplyDir, &result, &dirEntry);
|
|
||||||
if (err || !dirEntry)
|
|
||||||
break;
|
|
||||||
|
|
||||||
char* entryName = (char *) dirEntry->d_name;
|
|
||||||
if (strncmp(entryName, "A", 1)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
char onlinePath[50];
|
|
||||||
snprintf((char *) onlinePath, sizeof onlinePath, "%s/%s/online", power_supplyPath, entryName);
|
|
||||||
FILE* file = fopen(onlinePath, "r");
|
|
||||||
if (!file) {
|
|
||||||
isOn = AC_ERROR;
|
|
||||||
} else {
|
|
||||||
isOn = (fgetc(file) - '0');
|
|
||||||
fclose(file);
|
|
||||||
if (isOn == AC_PRESENT) {
|
|
||||||
// If any AC adapter is being used then stop
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (power_supplyDir)
|
|
||||||
closedir(power_supplyDir);
|
|
||||||
|
|
||||||
return isOn;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ACPresence chkIsOnline() {
|
|
||||||
if (access(PROCDIR "/acpi/ac_adapter", F_OK) == 0) {
|
|
||||||
return procAcpiCheck();
|
|
||||||
} else if (access("/sys/class/power_supply", F_OK) == 0) {
|
|
||||||
return sysCheck();
|
|
||||||
} else {
|
|
||||||
return AC_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static double getProcBatData() {
|
|
||||||
const unsigned long int totalFull = parseBatInfo("info", 3, 4);
|
|
||||||
if (totalFull == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
const unsigned long int totalRemain = parseBatInfo("state", 5, 3);
|
|
||||||
if (totalRemain == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return totalRemain * 100.0 / (double) totalFull;
|
|
||||||
}
|
|
||||||
|
|
||||||
static double getSysBatData() {
|
|
||||||
const char *power_supplyPath = "/sys/class/power_supply/";
|
|
||||||
DIR *power_supplyDir = opendir(power_supplyPath);
|
|
||||||
if (!power_supplyDir)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
unsigned long int totalFull = 0;
|
|
||||||
unsigned long int totalRemain = 0;
|
|
||||||
|
|
||||||
struct dirent result;
|
|
||||||
struct dirent* dirEntry;
|
|
||||||
for (;;) {
|
|
||||||
int err = readdir_r((DIR *) power_supplyDir, &result, &dirEntry);
|
|
||||||
if (err || !dirEntry)
|
|
||||||
break;
|
|
||||||
char* entryName = (char *) dirEntry->d_name;
|
|
||||||
|
|
||||||
if (strncmp(entryName, "BAT", 3)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char ueventPath[50];
|
|
||||||
|
|
||||||
snprintf((char *) ueventPath, sizeof ueventPath, "%s%s/uevent", power_supplyPath, entryName);
|
|
||||||
|
|
||||||
FILE *file;
|
|
||||||
if ((file = fopen(ueventPath, "r")) == NULL) {
|
|
||||||
closedir(power_supplyDir);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((totalFull += parseUevent(file, "POWER_SUPPLY_ENERGY_FULL="))) {
|
|
||||||
totalRemain += parseUevent(file, "POWER_SUPPLY_ENERGY_NOW=");
|
|
||||||
} else {
|
|
||||||
//reset file pointer
|
|
||||||
if (fseek(file, 0, SEEK_SET) < 0) {
|
|
||||||
closedir(power_supplyDir);
|
|
||||||
fclose(file);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Some systems have it as CHARGE instead of ENERGY.
|
|
||||||
if ((totalFull += parseUevent(file, "POWER_SUPPLY_CHARGE_FULL="))) {
|
|
||||||
totalRemain += parseUevent(file, "POWER_SUPPLY_CHARGE_NOW=");
|
|
||||||
} else {
|
|
||||||
//reset file pointer
|
|
||||||
if (fseek(file, 0, SEEK_SET) < 0) {
|
|
||||||
closedir(power_supplyDir);
|
|
||||||
fclose(file);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
const double percent = totalFull > 0 ? ((double) totalRemain * 100) / (double) totalFull : 0;
|
|
||||||
closedir(power_supplyDir);
|
|
||||||
return percent;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void BatteryMeter_setValues(Meter * this, char *buffer, int len) {
|
static void BatteryMeter_setValues(Meter * this, char *buffer, int len) {
|
||||||
double percent = getProcBatData();
|
ACPresence isOnAC;
|
||||||
|
double percent;
|
||||||
|
|
||||||
if (percent == 0) {
|
Platform_getBatteryLevel(&percent, &isOnAC);
|
||||||
percent = getSysBatData();
|
|
||||||
if (percent == 0) {
|
if (percent == -1) {
|
||||||
snprintf(buffer, len, "n/a");
|
this->values[0] = 0;
|
||||||
return;
|
snprintf(buffer, len, "n/a");
|
||||||
}
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->values[0] = percent;
|
this->values[0] = percent;
|
||||||
|
@ -308,11 +56,9 @@ static void BatteryMeter_setValues(Meter * this, char *buffer, int len) {
|
||||||
onBatteryText = "%.1f%%(bat)";
|
onBatteryText = "%.1f%%(bat)";
|
||||||
}
|
}
|
||||||
|
|
||||||
ACPresence isOnLine = chkIsOnline();
|
if (isOnAC == AC_PRESENT) {
|
||||||
|
|
||||||
if (isOnLine == AC_PRESENT) {
|
|
||||||
snprintf(buffer, len, onAcText, percent);
|
snprintf(buffer, len, onAcText, percent);
|
||||||
} else if (isOnLine == AC_ABSENT) {
|
} else if (isOnAC == AC_ABSENT) {
|
||||||
snprintf(buffer, len, onBatteryText, percent);
|
snprintf(buffer, len, onBatteryText, percent);
|
||||||
} else {
|
} else {
|
||||||
snprintf(buffer, len, unknownText, percent);
|
snprintf(buffer, len, unknownText, percent);
|
||||||
|
|
|
@ -19,7 +19,6 @@ typedef enum ACPresence_ {
|
||||||
AC_ERROR
|
AC_ERROR
|
||||||
} ACPresence;
|
} ACPresence;
|
||||||
|
|
||||||
|
|
||||||
extern int BatteryMeter_attributes[];
|
extern int BatteryMeter_attributes[];
|
||||||
|
|
||||||
extern MeterClass BatteryMeter_class;
|
extern MeterClass BatteryMeter_class;
|
||||||
|
|
|
@ -35,10 +35,10 @@ HostnameMeter.h OpenFilesScreen.h Affinity.h IncSet.h Action.h
|
||||||
|
|
||||||
if HTOP_LINUX
|
if HTOP_LINUX
|
||||||
myhtopplatsources = linux/Platform.c linux/IOPriorityPanel.c linux/IOPriority.c \
|
myhtopplatsources = linux/Platform.c linux/IOPriorityPanel.c linux/IOPriority.c \
|
||||||
linux/LinuxProcess.c linux/LinuxProcessList.c linux/LinuxCRT.c
|
linux/LinuxProcess.c linux/LinuxProcessList.c linux/LinuxCRT.c linux/Battery.c
|
||||||
|
|
||||||
myhtopplatheaders = linux/Platform.h linux/IOPriorityPanel.h linux/IOPriority.h \
|
myhtopplatheaders = linux/Platform.h linux/IOPriorityPanel.h linux/IOPriority.h \
|
||||||
linux/LinuxProcess.h linux/LinuxProcessList.h linux/LinuxCRT.h
|
linux/LinuxProcess.h linux/LinuxProcessList.h linux/LinuxCRT.h linux/Battery.h
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if HTOP_UNSUPPORTED
|
if HTOP_UNSUPPORTED
|
||||||
|
|
|
@ -0,0 +1,269 @@
|
||||||
|
/*
|
||||||
|
htop - linux/Battery.c
|
||||||
|
(C) 2004-2014 Hisham H. Muhammad
|
||||||
|
Released under the GNU GPL, see the COPYING file
|
||||||
|
in the source distribution for its full text.
|
||||||
|
|
||||||
|
Linux battery readings written by Ian P. Hands (iphands@gmail.com, ihands@redhat.com).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _GNU_SOURCE
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#endif
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "BatteryMeter.h"
|
||||||
|
#include "String.h"
|
||||||
|
|
||||||
|
static unsigned long int parseUevent(FILE * file, const char *key) {
|
||||||
|
char line[100];
|
||||||
|
unsigned long int dValue = 0;
|
||||||
|
char* saveptr;
|
||||||
|
|
||||||
|
while (fgets(line, sizeof line, file)) {
|
||||||
|
if (strncmp(line, key, strlen(key)) == 0) {
|
||||||
|
char *value;
|
||||||
|
strtok_r(line, "=", &saveptr);
|
||||||
|
value = strtok_r(NULL, "=", &saveptr);
|
||||||
|
dValue = atoi(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long int parseBatInfo(const char *fileName, const unsigned short int lineNum, const unsigned short int wordNum) {
|
||||||
|
const char batteryPath[] = PROCDIR "/acpi/battery/";
|
||||||
|
DIR* batteryDir = opendir(batteryPath);
|
||||||
|
if (!batteryDir)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#define MAX_BATTERIES 64
|
||||||
|
char* batteries[MAX_BATTERIES];
|
||||||
|
unsigned int nBatteries = 0;
|
||||||
|
memset(batteries, 0, MAX_BATTERIES * sizeof(char*));
|
||||||
|
|
||||||
|
struct dirent result;
|
||||||
|
struct dirent* dirEntry;
|
||||||
|
while (nBatteries < MAX_BATTERIES) {
|
||||||
|
int err = readdir_r(batteryDir, &result, &dirEntry);
|
||||||
|
if (err || !dirEntry)
|
||||||
|
break;
|
||||||
|
char* entryName = dirEntry->d_name;
|
||||||
|
if (strncmp(entryName, "BAT", 3))
|
||||||
|
continue;
|
||||||
|
batteries[nBatteries] = strdup(entryName);
|
||||||
|
nBatteries++;
|
||||||
|
}
|
||||||
|
closedir(batteryDir);
|
||||||
|
|
||||||
|
unsigned long int total = 0;
|
||||||
|
for (unsigned int i = 0; i < nBatteries; i++) {
|
||||||
|
char infoPath[30];
|
||||||
|
snprintf(infoPath, sizeof infoPath, "%s%s/%s", batteryPath, batteries[i], fileName);
|
||||||
|
|
||||||
|
FILE* file = fopen(infoPath, "r");
|
||||||
|
if (!file) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
char line[50] = "";
|
||||||
|
for (unsigned short int i = 0; i < lineNum; i++) {
|
||||||
|
char* ok = fgets(line, sizeof line, file);
|
||||||
|
if (!ok) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
char *foundNumStr = String_getToken(line, wordNum);
|
||||||
|
const unsigned long int foundNum = atoi(foundNumStr);
|
||||||
|
free(foundNumStr);
|
||||||
|
|
||||||
|
total += foundNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < nBatteries; i++) {
|
||||||
|
free(batteries[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ACPresence procAcpiCheck() {
|
||||||
|
ACPresence isOn = AC_ERROR;
|
||||||
|
const char *power_supplyPath = PROCDIR "/acpi/ac_adapter";
|
||||||
|
DIR *power_supplyDir = opendir(power_supplyPath);
|
||||||
|
if (!power_supplyDir) {
|
||||||
|
return AC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dirent result;
|
||||||
|
struct dirent* dirEntry;
|
||||||
|
for (;;) {
|
||||||
|
int err = readdir_r((DIR *) power_supplyDir, &result, &dirEntry);
|
||||||
|
if (err || !dirEntry)
|
||||||
|
break;
|
||||||
|
|
||||||
|
char* entryName = (char *) dirEntry->d_name;
|
||||||
|
|
||||||
|
if (entryName[0] != 'A')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
char statePath[50];
|
||||||
|
snprintf((char *) statePath, sizeof statePath, "%s/%s/state", power_supplyPath, entryName);
|
||||||
|
FILE* file = fopen(statePath, "r");
|
||||||
|
|
||||||
|
if (!file) {
|
||||||
|
isOn = AC_ERROR;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
char line[100];
|
||||||
|
fgets(line, sizeof line, file);
|
||||||
|
line[sizeof(line) - 1] = '\0';
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
const char *isOnline = String_getToken(line, 2);
|
||||||
|
|
||||||
|
if (strcmp(isOnline, "on-line") == 0) {
|
||||||
|
isOn = AC_PRESENT;
|
||||||
|
} else {
|
||||||
|
isOn = AC_ABSENT;
|
||||||
|
}
|
||||||
|
free((char *) isOnline);
|
||||||
|
if (isOn == AC_PRESENT) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (power_supplyDir)
|
||||||
|
closedir(power_supplyDir);
|
||||||
|
return isOn;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ACPresence sysCheck() {
|
||||||
|
ACPresence isOn = AC_ERROR;
|
||||||
|
const char *power_supplyPath = "/sys/class/power_supply";
|
||||||
|
DIR *power_supplyDir = opendir(power_supplyPath);
|
||||||
|
if (!power_supplyDir) {
|
||||||
|
return AC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dirent result;
|
||||||
|
struct dirent* dirEntry;
|
||||||
|
for (;;) {
|
||||||
|
int err = readdir_r((DIR *) power_supplyDir, &result, &dirEntry);
|
||||||
|
if (err || !dirEntry)
|
||||||
|
break;
|
||||||
|
|
||||||
|
char* entryName = (char *) dirEntry->d_name;
|
||||||
|
if (strncmp(entryName, "A", 1)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
char onlinePath[50];
|
||||||
|
snprintf((char *) onlinePath, sizeof onlinePath, "%s/%s/online", power_supplyPath, entryName);
|
||||||
|
FILE* file = fopen(onlinePath, "r");
|
||||||
|
if (!file) {
|
||||||
|
isOn = AC_ERROR;
|
||||||
|
} else {
|
||||||
|
isOn = (fgetc(file) - '0');
|
||||||
|
fclose(file);
|
||||||
|
if (isOn == AC_PRESENT) {
|
||||||
|
// If any AC adapter is being used then stop
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (power_supplyDir)
|
||||||
|
closedir(power_supplyDir);
|
||||||
|
|
||||||
|
return isOn;
|
||||||
|
}
|
||||||
|
|
||||||
|
ACPresence Battery_isOnAC() {
|
||||||
|
if (access(PROCDIR "/acpi/ac_adapter", F_OK) == 0) {
|
||||||
|
return procAcpiCheck();
|
||||||
|
} else if (access("/sys/class/power_supply", F_OK) == 0) {
|
||||||
|
return sysCheck();
|
||||||
|
} else {
|
||||||
|
return AC_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double Battery_getProcBatData() {
|
||||||
|
const unsigned long int totalFull = parseBatInfo("info", 3, 4);
|
||||||
|
if (totalFull == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const unsigned long int totalRemain = parseBatInfo("state", 5, 3);
|
||||||
|
if (totalRemain == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return totalRemain * 100.0 / (double) totalFull;
|
||||||
|
}
|
||||||
|
|
||||||
|
double Battery_getSysBatData() {
|
||||||
|
const char *power_supplyPath = "/sys/class/power_supply/";
|
||||||
|
DIR *power_supplyDir = opendir(power_supplyPath);
|
||||||
|
if (!power_supplyDir)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
unsigned long int totalFull = 0;
|
||||||
|
unsigned long int totalRemain = 0;
|
||||||
|
|
||||||
|
struct dirent result;
|
||||||
|
struct dirent* dirEntry;
|
||||||
|
for (;;) {
|
||||||
|
int err = readdir_r((DIR *) power_supplyDir, &result, &dirEntry);
|
||||||
|
if (err || !dirEntry)
|
||||||
|
break;
|
||||||
|
char* entryName = (char *) dirEntry->d_name;
|
||||||
|
|
||||||
|
if (strncmp(entryName, "BAT", 3)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char ueventPath[50];
|
||||||
|
|
||||||
|
snprintf((char *) ueventPath, sizeof ueventPath, "%s%s/uevent", power_supplyPath, entryName);
|
||||||
|
|
||||||
|
FILE *file;
|
||||||
|
if ((file = fopen(ueventPath, "r")) == NULL) {
|
||||||
|
closedir(power_supplyDir);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((totalFull += parseUevent(file, "POWER_SUPPLY_ENERGY_FULL="))) {
|
||||||
|
totalRemain += parseUevent(file, "POWER_SUPPLY_ENERGY_NOW=");
|
||||||
|
} else {
|
||||||
|
//reset file pointer
|
||||||
|
if (fseek(file, 0, SEEK_SET) < 0) {
|
||||||
|
closedir(power_supplyDir);
|
||||||
|
fclose(file);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Some systems have it as CHARGE instead of ENERGY.
|
||||||
|
if ((totalFull += parseUevent(file, "POWER_SUPPLY_CHARGE_FULL="))) {
|
||||||
|
totalRemain += parseUevent(file, "POWER_SUPPLY_CHARGE_NOW=");
|
||||||
|
} else {
|
||||||
|
//reset file pointer
|
||||||
|
if (fseek(file, 0, SEEK_SET) < 0) {
|
||||||
|
closedir(power_supplyDir);
|
||||||
|
fclose(file);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
const double percent = totalFull > 0 ? ((double) totalRemain * 100) / (double) totalFull : 0;
|
||||||
|
closedir(power_supplyDir);
|
||||||
|
return percent;
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
/* Do not edit this file. It was automatically generated. */
|
||||||
|
|
||||||
|
#ifndef HEADER_Battery
|
||||||
|
#define HEADER_Battery
|
||||||
|
/*
|
||||||
|
htop - linux/Battery.h
|
||||||
|
(C) 2004-2014 Hisham H. Muhammad
|
||||||
|
Released under the GNU GPL, see the COPYING file
|
||||||
|
in the source distribution for its full text.
|
||||||
|
|
||||||
|
Linux battery readings written by Ian P. Hands (iphands@gmail.com, ihands@redhat.com).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _GNU_SOURCE
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ACPresence Battery_isOnAC();
|
||||||
|
|
||||||
|
double Battery_getProcBatData();
|
||||||
|
|
||||||
|
double Battery_getSysBatData();
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,17 @@
|
||||||
|
/* Do not edit this file. It was automatically generated. */
|
||||||
|
|
||||||
|
#ifndef HEADER_LinuxCRT
|
||||||
|
#define HEADER_LinuxCRT
|
||||||
|
/*
|
||||||
|
htop - LinuxCRT.h
|
||||||
|
(C) 2014 Hisham H. Muhammad
|
||||||
|
Released under the GNU GPL, see the COPYING file
|
||||||
|
in the source distribution for its full text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_EXECINFO_H
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void CRT_handleSIGSEGV(int sgn);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,39 @@
|
||||||
|
/* Do not edit this file. It was automatically generated. */
|
||||||
|
|
||||||
|
#ifndef HEADER_LinuxProcess
|
||||||
|
#define HEADER_LinuxProcess
|
||||||
|
/*
|
||||||
|
htop - LinuxProcess.h
|
||||||
|
(C) 2014 Hisham H. Muhammad
|
||||||
|
Released under the GNU GPL, see the COPYING file
|
||||||
|
in the source distribution for its full text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "IOPriority.h"
|
||||||
|
|
||||||
|
typedef struct LinuxProcess_ {
|
||||||
|
Process super;
|
||||||
|
IOPriority ioPriority;
|
||||||
|
} LinuxProcess;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
[1] Note that before kernel 2.6.26 a process that has not asked for
|
||||||
|
an io priority formally uses "none" as scheduling class, but the
|
||||||
|
io scheduler will treat such processes as if it were in the best
|
||||||
|
effort class. The priority within the best effort class will be
|
||||||
|
dynamically derived from the cpu nice level of the process:
|
||||||
|
extern io_priority;
|
||||||
|
*/
|
||||||
|
#define LinuxProcess_effectiveIOPriority(p_) (IOPriority_class(p_->ioPriority) == IOPRIO_CLASS_NONE ? IOPriority_tuple(IOPRIO_CLASS_BE, (p_->super.nice + 20) / 5) : p_->ioPriority)
|
||||||
|
|
||||||
|
IOPriority LinuxProcess_updateIOPriority(LinuxProcess* this);
|
||||||
|
|
||||||
|
bool LinuxProcess_setIOPriority(LinuxProcess* this, IOPriority ioprio);
|
||||||
|
|
||||||
|
void LinuxProcess_writeField(LinuxProcess* this, RichString* str, ProcessField field);
|
||||||
|
|
||||||
|
long LinuxProcess_compare(const void* v1, const void* v2);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,56 @@
|
||||||
|
/* Do not edit this file. It was automatically generated. */
|
||||||
|
|
||||||
|
#ifndef HEADER_LinuxProcessList
|
||||||
|
#define HEADER_LinuxProcessList
|
||||||
|
/*
|
||||||
|
htop - LinuxProcessList.h
|
||||||
|
(C) 2014 Hisham H. Muhammad
|
||||||
|
Released under the GNU GPL, see the COPYING file
|
||||||
|
in the source distribution for its full text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "ProcessList.h"
|
||||||
|
|
||||||
|
#ifndef PROCDIR
|
||||||
|
#define PROCDIR "/proc"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PROCSTATFILE
|
||||||
|
#define PROCSTATFILE PROCDIR "/stat"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PROCMEMINFOFILE
|
||||||
|
#define PROCMEMINFOFILE PROCDIR "/meminfo"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList);
|
||||||
|
|
||||||
|
void ProcessList_delete(ProcessList* this);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_TASKSTATS
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_OPENVZ
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_CGROUP
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_VSERVER
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_OOM
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void ProcessList_scan(ProcessList* this);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -9,6 +9,8 @@ in the source distribution for its full text.
|
||||||
#include "IOPriority.h"
|
#include "IOPriority.h"
|
||||||
#include "IOPriorityPanel.h"
|
#include "IOPriorityPanel.h"
|
||||||
#include "LinuxProcess.h"
|
#include "LinuxProcess.h"
|
||||||
|
#include "Battery.h"
|
||||||
|
|
||||||
#include "Meter.h"
|
#include "Meter.h"
|
||||||
#include "CPUMeter.h"
|
#include "CPUMeter.h"
|
||||||
#include "MemoryMeter.h"
|
#include "MemoryMeter.h"
|
||||||
|
@ -16,7 +18,6 @@ in the source distribution for its full text.
|
||||||
#include "TasksMeter.h"
|
#include "TasksMeter.h"
|
||||||
#include "LoadAverageMeter.h"
|
#include "LoadAverageMeter.h"
|
||||||
#include "UptimeMeter.h"
|
#include "UptimeMeter.h"
|
||||||
#include "BatteryMeter.h"
|
|
||||||
#include "ClockMeter.h"
|
#include "ClockMeter.h"
|
||||||
#include "HostnameMeter.h"
|
#include "HostnameMeter.h"
|
||||||
|
|
||||||
|
@ -25,6 +26,7 @@ in the source distribution for its full text.
|
||||||
|
|
||||||
/*{
|
/*{
|
||||||
#include "Action.h"
|
#include "Action.h"
|
||||||
|
#include "BatteryMeter.h"
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
static Htop_Reaction Platform_actionSetIOPriority(Panel* panel, ProcessList* pl, Header* header) {
|
static Htop_Reaction Platform_actionSetIOPriority(Panel* panel, ProcessList* pl, Header* header) {
|
||||||
|
@ -102,3 +104,19 @@ int Platform_getMaxPid() {
|
||||||
return maxPid;
|
return maxPid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Platform_getBatteryLevel(double* level, ACPresence* isOnAC) {
|
||||||
|
|
||||||
|
double percent = Battery_getProcBatData();
|
||||||
|
|
||||||
|
if (percent == 0) {
|
||||||
|
percent = Battery_getSysBatData();
|
||||||
|
if (percent == 0) {
|
||||||
|
*level = -1;
|
||||||
|
*isOnAC = AC_ERROR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*isOnAC = Battery_isOnAC();
|
||||||
|
*level = percent;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
/* Do not edit this file. It was automatically generated. */
|
||||||
|
|
||||||
|
#ifndef HEADER_Platform
|
||||||
|
#define HEADER_Platform
|
||||||
|
/*
|
||||||
|
htop - linux/Platform.h
|
||||||
|
(C) 2014 Hisham H. Muhammad
|
||||||
|
Released under the GNU GPL, see the COPYING file
|
||||||
|
in the source distribution for its full text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Action.h"
|
||||||
|
#include "BatteryMeter.h"
|
||||||
|
|
||||||
|
void Platform_setBindings(Htop_Action* keys);
|
||||||
|
|
||||||
|
extern MeterClass* Platform_meterTypes[];
|
||||||
|
|
||||||
|
int Platform_getUptime();
|
||||||
|
|
||||||
|
void Platform_getLoadAverage(double* one, double* five, double* fifteen);
|
||||||
|
|
||||||
|
int Platform_getMaxPid();
|
||||||
|
|
||||||
|
void Platform_getBatteryLevel(double* level, ACPresence* isOnAC);
|
||||||
|
|
||||||
|
#endif
|
|
@ -11,13 +11,13 @@ in the source distribution for its full text.
|
||||||
#include "SwapMeter.h"
|
#include "SwapMeter.h"
|
||||||
#include "TasksMeter.h"
|
#include "TasksMeter.h"
|
||||||
#include "LoadAverageMeter.h"
|
#include "LoadAverageMeter.h"
|
||||||
#include "BatteryMeter.h"
|
|
||||||
#include "ClockMeter.h"
|
#include "ClockMeter.h"
|
||||||
#include "HostnameMeter.h"
|
#include "HostnameMeter.h"
|
||||||
#include "UptimeMeter.h"
|
#include "UptimeMeter.h"
|
||||||
|
|
||||||
/*{
|
/*{
|
||||||
#include "Action.h"
|
#include "Action.h"
|
||||||
|
#include "BatteryMeter.h"
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
void Platform_setBindings(Htop_Action* keys) {
|
void Platform_setBindings(Htop_Action* keys) {
|
||||||
|
@ -58,3 +58,9 @@ void Platform_getLoadAverage(double* one, double* five, double* fifteen) {
|
||||||
int Platform_getMaxPid() {
|
int Platform_getMaxPid() {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Platform_getBatteryLevel(double* level, ACPresence* isOnAC) {
|
||||||
|
*level = -1;
|
||||||
|
*isOnAC = AC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue