Top/ps process monitor
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1260 lines
33 KiB

6 years ago
/*
Copyright (c) 2017, Alastair Roy Poole <netstar@gmail.com>
All rights reserved.
6 years ago
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
6 years ago
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
6 years ago
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6 years ago
*/
#define _DEFAULT_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
#include <stdint.h>
#include <unistd.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <math.h>
#include <sys/stat.h>
6 years ago
#include <sys/types.h>
#include <sys/param.h>
#if !defined(__linux__)
# include <sys/sysctl.h>
#endif
6 years ago
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <pthread.h>
#if defined(__APPLE__) && defined(__MACH__)
#define __MacOS__
# include <mach/mach.h>
# include <mach/vm_statistics.h>
# include <mach/mach_types.h>
# include <mach/mach_init.h>
# include <mach/mach_host.h>
# include <net/if_mib.h>
#endif
#if defined(__OpenBSD__)
# include <sys/sched.h>
6 years ago
# include <sys/swap.h>
# include <sys/mount.h>
# include <sys/sensors.h>
# include <net/if_types.h>
# include <ifaddrs.h>
#endif
#if defined(__FreeBSD__) || defined(__DragonFly__)
# include <net/if_mib.h>
# include <vm/vm_param.h>
# include <dev/acpica/acpiio.h>
6 years ago
#endif
#include "machine.h"
6 years ago
#if defined(__OpenBSD__)
# define CPU_STATES 6
#else
4 years ago
# define CPU_STATES 5
#endif
6 years ago
#if defined(__linux__)
static char *
file_contents(const char *path)
6 years ago
{
4 years ago
FILE *f;
char *buf, *tmp;
size_t n = 1, len = 0;
const size_t block = 4096;
4 years ago
f = fopen(path, "r");
6 years ago
if (!f) return NULL;
buf = NULL;
6 years ago
while ((!feof(f)) && (!ferror(f)))
6 years ago
{
tmp = realloc(buf, ++n * (sizeof(char) * block) + 1);
if (!tmp) return NULL;
buf = tmp;
len += fread(buf + len, sizeof(char), block, f);
6 years ago
}
if (ferror(f))
{
free(buf);
fclose(f);
return NULL;
}
6 years ago
fclose(f);
buf[len] = 0;
6 years ago
return buf;
}
#endif
#if defined(__FreeBSD__) || defined(__DragonFly__)
static long int
_sysctlfromname(const char *name, void *mib, int depth, size_t *len)
{
long int result;
if (sysctlnametomib(name, mib, len) < 0)
return -1;
*len = sizeof(result);
if (sysctl(mib, depth, &result, len, NULL, 0) < 0)
return -1;
return result;
}
#endif
static int
cpu_count(void)
{
static int cores = 0;
if (cores != 0)
return cores;
6 years ago
#if defined(__linux__)
char buf[4096];
FILE *f;
int line = 0;
f = fopen("/proc/stat", "r");
if (!f) return 0;
while (fgets(buf, sizeof(buf), f))
{
if (line)
{
if (!strncmp(buf, "cpu", 3))
cores++;
else
break;
}
line++;
}
fclose(f);
#elif defined(__MacOS__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
6 years ago
size_t len;
int mib[2] = { CTL_HW, HW_NCPU };
len = sizeof(cores);
if (sysctl(mib, 2, &cores, &len, NULL, 0) < 0)
return 0;
#endif
return cores;
}
int
system_cpu_online_count_get(void)
{
#if defined(__OpenBSD__)
static int cores = 0;
if (cores != 0) return cores;
size_t len;
int mib[2] = { CTL_HW, HW_NCPUONLINE };
len = sizeof(cores);
if (sysctl(mib, 2, &cores, &len, NULL, 0) < 0)
return cpu_count();
return cores;
#else
return cpu_count();
#endif
}
6 years ago
static void
_cpu_state_get(cpu_core_t **cores, int ncpu)
{
int diff_total, diff_idle;
double ratio, percent;
unsigned long total, idle, used;
cpu_core_t *core;
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
6 years ago
size_t size;
int i, j;
#endif
#if defined(__FreeBSD__) || defined(__DragonFly__)
if (!ncpu)
return;
size = sizeof(unsigned long) * (CPU_STATES * ncpu);
unsigned long cpu_times[ncpu][CPU_STATES];
if (sysctlbyname("kern.cp_times", cpu_times, &size, NULL, 0) < 0)
return;
for (i = 0; i < ncpu; i++) {
core = cores[i];
unsigned long *cpu = cpu_times[i];
total = 0;
for (j = 0; j < CPU_STATES; j++)
total += cpu[j];
idle = cpu[4];
diff_total = total - core->total;
diff_idle = idle - core->idle;
if (diff_total == 0) diff_total = 1;
ratio = diff_total / 100.0;
used = diff_total - diff_idle;
percent = used / ratio;
if (percent > 100) percent = 100;
else if (percent < 0)
percent = 0;
core->percent = percent;
core->total = total;
core->idle = idle;
}
#elif defined(__OpenBSD__)
static struct cpustats cpu_times[CPU_STATES];
static int cpu_time_mib[] = { CTL_KERN, KERN_CPUSTATS, 0 };
memset(&cpu_times, 0, CPU_STATES * sizeof(struct cpustats));
6 years ago
if (!ncpu)
return;
for (i = 0; i < ncpu; i++)
6 years ago
{
core = cores[i];
5 years ago
size = sizeof(struct cpustats);
cpu_time_mib[2] = i;
if (sysctl(cpu_time_mib, 3, &cpu_times[i], &size, NULL, 0) < 0)
6 years ago
return;
total = 0;
for (j = 0; j < CPU_STATES; j++)
total += cpu_times[i].cs_time[j];
6 years ago
idle = cpu_times[i].cs_time[CP_IDLE];
6 years ago
diff_total = total - core->total;
if (diff_total == 0) diff_total = 1;
diff_idle = idle - core->idle;
6 years ago
ratio = diff_total / 100.0;
used = diff_total - diff_idle;
percent = used / ratio;
if (percent > 100) percent = 100;
else if (percent < 0)
percent = 0;
core->percent = percent;
core->total = total;
core->idle = idle;
}
#elif defined(__linux__)
char *buf, name[128];
int i;
buf = file_contents("/proc/stat");
6 years ago
if (!buf) return;
for (i = 0; i < ncpu; i++) {
core = cores[i];
snprintf(name, sizeof(name), "cpu%d", i);
char *line = strstr(buf, name);
if (line)
{
line = strchr(line, ' ') + 1;
unsigned long cpu_times[4] = { 0 };
if (4 != sscanf(line, "%lu %lu %lu %lu", &cpu_times[0],
&cpu_times[1], &cpu_times[2], &cpu_times[3]))
6 years ago
return;
total = cpu_times[0] + cpu_times[1] + cpu_times[2] + cpu_times[3];
idle = cpu_times[3];
diff_total = total - core->total;
if (diff_total == 0) diff_total = 1;
diff_idle = idle - core->idle;
ratio = diff_total / 100.0;
used = diff_total - diff_idle;
percent = used / ratio;
if (percent > 100) percent = 100;
else if (percent < 0)
percent = 0;
core->percent = percent;
core->total = total;
core->idle = idle;
}
}
free(buf);
#elif defined(__MacOS__)
mach_msg_type_number_t count;
processor_cpu_load_info_t load;
mach_port_t mach_port;
unsigned int cpu_count;
int i;
cpu_count = ncpu;
count = HOST_CPU_LOAD_INFO_COUNT;
mach_port = mach_host_self();
if (host_processor_info(mach_port, PROCESSOR_CPU_LOAD_INFO, &cpu_count,
(processor_info_array_t *)&load, &count) != KERN_SUCCESS)
exit(-1);
6 years ago
for (i = 0; i < ncpu; i++) {
core = cores[i];
total = load[i].cpu_ticks[CPU_STATE_USER] +
load[i].cpu_ticks[CPU_STATE_SYSTEM] +
load[i].cpu_ticks[CPU_STATE_IDLE] +
load[i].cpu_ticks[CPU_STATE_NICE];
6 years ago
idle = load[i].cpu_ticks[CPU_STATE_IDLE];
diff_total = total - core->total;
if (diff_total == 0) diff_total = 1;
diff_idle = idle - core->idle;
ratio = diff_total / 100.0;
used = diff_total - diff_idle;
percent = used / ratio;
if (percent > 100) percent = 100;
else if (percent < 0)
percent = 0;
core->percent = percent;
core->total = total;
core->idle = idle;
}
#endif
}
cpu_core_t **
system_cpu_usage_get(int *ncpu)
6 years ago
{
cpu_core_t **cores;
int i;
*ncpu = cpu_count();
cores = malloc((*ncpu) * sizeof(cpu_core_t *));
for (i = 0; i < *ncpu; i++)
cores[i] = calloc(1, sizeof(cpu_core_t));
_cpu_state_get(cores, *ncpu);
usleep(1000000);
_cpu_state_get(cores, *ncpu);
return cores;
}
#if defined(__linux__)
static unsigned long
_meminfo_parse_line(const char *line)
{
char *p, *tok;
p = strchr(line, ':') + 1;
while (isspace(*p))
p++;
tok = strtok(p, " ");
return atol(tok);
}
#endif
void
system_memory_usage_get(meminfo_t *memory)
6 years ago
{
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
size_t len = 0, miblen;
6 years ago
int i = 0;
#endif
memset(memory, 0, sizeof(meminfo_t));
#if defined(__linux__)
FILE *f;
unsigned long swap_free = 0, tmp_free = 0, tmp_slab = 0;
char line[256];
int fields = 0;
f = fopen("/proc/meminfo", "r");
if (!f) return;
while (fgets(line, sizeof(line), f) != NULL)
{
if (!strncmp("MemTotal:", line, 9))
{
memory->total = _meminfo_parse_line(line);
fields++;
}
else if (!strncmp("MemFree:", line, 8))
{
tmp_free = _meminfo_parse_line(line);
fields++;
}
else if (!strncmp("Cached:", line, 7))
{
memory->cached = _meminfo_parse_line(line);
fields++;
}
else if (!strncmp("Slab:", line, 5))
{
tmp_slab = _meminfo_parse_line(line);
fields++;
}
else if (!strncmp("Buffers:", line, 8))
{
memory->buffered = _meminfo_parse_line(line);
fields++;
}
else if (!strncmp("Shmem:", line, 6))
{
memory->shared = _meminfo_parse_line(line);
fields++;
}
else if (!strncmp("SwapTotal:", line, 10))
{
memory->swap_total = _meminfo_parse_line(line);
fields++;
}
else if (!strncmp("SwapFree:", line, 9))
{
swap_free = _meminfo_parse_line(line);
fields++;
}
if (fields >= 8)
break;
}
memory->cached += tmp_slab;
memory->used = memory->total - tmp_free - memory->cached - memory->buffered;
memory->swap_used = memory->swap_total - swap_free;
6 years ago
memory->total *= 1024;
memory->used *= 1024;
memory->buffered *= 1024;
memory->cached *= 1024;
memory->shared *= 1024;
memory->swap_total *= 1024;
memory->swap_used *= 1024;
6 years ago
fclose(f);
#elif defined(__FreeBSD__) || defined(__DragonFly__)
unsigned int free = 0, active = 0, inactive = 0, wired = 0;
unsigned int cached = 0, buffered = 0, zfs_arc = 0;
6 years ago
long int result = 0;
int page_size = getpagesize();
int mib[5] = { CTL_HW, HW_PHYSMEM, 0, 0, 0 };
6 years ago
len = sizeof(memory->total);
if (sysctl(mib, 2, &memory->total, &len, NULL, 0) == -1)
return;
if ((active =
_sysctlfromname("vm.stats.vm.v_active_count", mib, 4, &len)) < 0)
6 years ago
return;
if ((inactive =
_sysctlfromname("vm.stats.vm.v_inactive_count", mib, 4, &len)) < 0)
6 years ago
return;
if ((wired =
_sysctlfromname("vm.stats.vm.v_wire_count", mib, 4, &len)) < 0)
return;
if ((cached =
_sysctlfromname("vm.stats.vm.v_cache_count", mib, 4, &len)) < 0)
return;
if ((free = _sysctlfromname("vm.stats.vm.v_free_count", mib, 4, &len)) < 0)
return;
if ((buffered = _sysctlfromname("vfs.bufspace", mib, 2, &len)) < 0)
6 years ago
return;
memory->used = ((active + wired + cached) * page_size);
memory->buffered = buffered;
memory->cached = (cached * page_size);
6 years ago
result = _sysctlfromname("vm.swap_total", mib, 2, &len);
if (result < 0)
return;
memory->swap_total = result;
6 years ago
miblen = 3;
if (sysctlnametomib("vm.swap_info", mib, &miblen) == -1) return;
if ((zfs_arc = _sysctlfromname("kstat.zfs.misc.arcstats.c", mib, 5, &len)) != -1)
{
memory->zfs_arc_used = zfs_arc;
}
6 years ago
struct xswdev xsw;
for (i = 0; ; i++)
6 years ago
{
mib[miblen] = i;
6 years ago
len = sizeof(xsw);
if (sysctl(mib, miblen + 1, &xsw, &len, NULL, 0) == -1)
6 years ago
break;
memory->swap_used += (unsigned long) xsw.xsw_used * page_size;
6 years ago
}
#elif defined(__OpenBSD__)
static int mib[] = { CTL_HW, HW_PHYSMEM64 };
static int bcstats_mib[] = { CTL_VFS, VFS_GENERIC, VFS_BCACHESTAT };
struct bcachestats bcstats;
static int uvmexp_mib[] = { CTL_VM, VM_UVMEXP };
struct uvmexp uvmexp;
int nswap, rnswap;
struct swapent *swdev = NULL;
(void) miblen;
6 years ago
len = sizeof(memory->total);
if (sysctl(mib, 2, &memory->total, &len, NULL, 0) == -1)
return;
len = sizeof(uvmexp);
if (sysctl(uvmexp_mib, 2, &uvmexp, &len, NULL, 0) == -1)
return;
len = sizeof(bcstats);
if (sysctl(bcstats_mib, 3, &bcstats, &len, NULL, 0) == -1)
return;
nswap = swapctl(SWAP_NSWAP, 0, 0);
if (nswap == 0)
goto swap_out;
swdev = calloc(nswap, sizeof(*swdev));
if (swdev == NULL)
goto swap_out;
rnswap = swapctl(SWAP_STATS, swdev, nswap);
if (rnswap == -1)
goto swap_out;
for (i = 0; i < nswap; i++) {
if (swdev[i].se_flags & SWF_ENABLE)
{
memory->swap_used += (swdev[i].se_inuse / (1024 / DEV_BSIZE));
memory->swap_total += (swdev[i].se_nblks / (1024 / DEV_BSIZE));
}
}
memory->swap_total *= 1024;
memory->swap_used *= 1024;
6 years ago
swap_out:
if (swdev)
free(swdev);
memory->cached = (uint64_t)(uvmexp.pagesize * bcstats.numbufpages);
memory->used = (uint64_t)(uvmexp.active * uvmexp.pagesize);
memory->buffered = (uint64_t)(uvmexp.pagesize * (uint64_t)(uvmexp.npages - uvmexp.free));
memory->shared = (uint64_t)(uvmexp.pagesize * uvmexp.wired);
6 years ago
#elif defined(__MacOS__)
int mib[2] = { CTL_HW, HW_MEMSIZE };
size_t total;
vm_size_t page_size;
mach_port_t mach_port;
mach_msg_type_number_t count;
vm_statistics64_data_t vm_stats;
struct xsw_usage xsu;
size_t len = sizeof(size_t);
if (sysctl(mib, 2, &total, &len, NULL, 0) == -1)
return;
mach_port = mach_host_self();
count = sizeof(vm_stats) / sizeof(natural_t);
memory->total = total;
if (host_page_size(mach_port, &page_size) == KERN_SUCCESS &&
host_statistics64(mach_port, HOST_VM_INFO,
(host_info64_t)&vm_stats, &count) == KERN_SUCCESS)
6 years ago
{
memory->used = memory->total - (vm_stats.inactive_count * page_size);
6 years ago
memory->cached = vm_stats.active_count * page_size;
memory->shared = vm_stats.wire_count * page_size;
memory->buffered = vm_stats.inactive_count * page_size;
}
total = sizeof(xsu);
if (sysctlbyname("vm.swapusage", &xsu, &total, NULL, 0) != -1)
{
memory->swap_total = xsu.xsu_total;
memory->swap_used = xsu.xsu_used;
}
#endif
}
sensor_t **
system_sensors_thermal_get(int *sensor_count)
6 years ago
{
sensor_t **sensors = NULL;
#if defined(__OpenBSD__)
sensor_t *sensor;
6 years ago
int mibs[5] = { CTL_HW, HW_SENSORS, 0, 0, 0 };
int devn, n;
6 years ago
struct sensor snsr;
size_t slen = sizeof(struct sensor);
struct sensordev snsrdev;
size_t sdlen = sizeof(struct sensordev);
for (devn = 0;; devn++)
{
6 years ago
mibs[2] = devn;
if (sysctl(mibs, 3, &snsrdev, &sdlen, NULL, 0) == -1)
{
if (errno == ENOENT) break;
continue;
6 years ago
}
for (n = 0; n < snsrdev.maxnumt[SENSOR_TEMP]; n++)
{
mibs[4] = n;
6 years ago
if (sysctl(mibs, 5, &snsr, &slen, NULL, 0) == -1)
continue;
if (slen > 0 && (snsr.flags & SENSOR_FINVALID) == 0)
break;
}
if (sysctl(mibs, 5, &snsr, &slen, NULL, 0) == -1)
continue;
if (snsr.type != SENSOR_TEMP)
continue;
sensors = realloc(sensors, (1 + *sensor_count) * sizeof(sensor_t *));
sensors[(*sensor_count)++] = sensor = calloc(1, sizeof(sensor_t));
sensor->name = strdup(snsrdev.xname);
sensor->value = (snsr.value - 273150000) / 1000000.0; // (uK -> C)
6 years ago
}
#elif defined(__FreeBSD__) || defined(__DragonFly__)
sensor_t *sensor;
int value;
6 years ago
size_t len = sizeof(value);
if ((sysctlbyname("hw.acpi.thermal.tz0.temperature", &value, &len, NULL, 0)) != -1)
6 years ago
{
sensors = realloc(sensors, (1 + *sensor_count) * sizeof(sensor_t *));
sensors[(*sensor_count)++] = sensor = calloc(1, sizeof(sensor_t));
sensor->name = strdup("hw.acpi.thermal.tz0");
sensor->value = (float) (value - 2732) / 10;
6 years ago
}
#elif defined(__linux__)
sensor_t *sensor;
char *type, *value;
6 years ago
char path[PATH_MAX];
struct dirent **names;
int i, n;
6 years ago
n = scandir("/sys/class/thermal", &names, 0, alphasort);
if (n < 0) return NULL;
6 years ago
for (i = 0; i < n; i++)
6 years ago
{
if (strncmp(names[i]->d_name, "thermal_zone", 12))
{
free(names[i]);
continue;
}
snprintf(path, sizeof(path), "/sys/class/thermal/%s/type",
names[i]->d_name);
type = file_contents(path);
if (type)
6 years ago
{
sensors =
realloc(sensors, (1 + (*sensor_count)) * sizeof(sensor_t *));
sensors[(*sensor_count)++] =
sensor = calloc(1, sizeof(sensor_t));
sensor->name = strdup(type);
snprintf(path, sizeof(path), "/sys/class/thermal/%s/temp",
names[i]->d_name);
value = file_contents(path);
if (!value)
sensor->invalid = true;
else
6 years ago
{
sensor->value = (float)atoi(value) / 1000.0;
free(value);
6 years ago
}
free(type);
6 years ago
}
free(names[i]);
6 years ago
}
free(names);
6 years ago
#elif defined(__MacOS__)
#endif
return sensors;
6 years ago
}
static int
_power_battery_count_get(power_t *power)
{
#if defined(__OpenBSD__)
6 years ago
struct sensordev snsrdev;
size_t sdlen = sizeof(struct sensordev);
int mib[5] = { CTL_HW, HW_SENSORS, 0, 0, 0 };
3 years ago
int i, devn, id;
6 years ago
for (devn = 0;; devn++) {
mib[2] = devn;
if (sysctl(mib, 3, &snsrdev, &sdlen, NULL, 0) == -1)
{
if (errno == ENXIO)
continue;
if (errno == ENOENT)
break;
}
3 years ago
for (i = 0; i < 10; i++) {
6 years ago
char buf[64];
snprintf(buf, sizeof(buf), "acpibat%d", i);
if (!strcmp(buf, snsrdev.xname))
{
3 years ago
id = power->battery_count;
power->batteries = realloc(power->batteries, 1 +
power->battery_count * sizeof(bat_t **));
3 years ago
power->batteries[id] = calloc(1, sizeof(bat_t));
power->batteries[id]->name = strdup(buf);
power->batteries[id]->present = true;
power->batteries[id]->mibs = malloc(sizeof(int) * 5);
int *tmp = power->batteries[id]->mibs;
6 years ago
tmp[0] = mib[0];
tmp[1] = mib[1];
tmp[2] = mib[2];
3 years ago
power->battery_count++;
6 years ago
}
}
if (!strcmp("acpiac0", snsrdev.xname))
{
power->ac_mibs[0] = mib[0];
power->ac_mibs[1] = mib[1];
power->ac_mibs[2] = mib[2];
}
}
#elif defined(__FreeBSD__) || defined(__DragonFly__)
size_t len;
if ((sysctlbyname("hw.acpi.battery.units", &power->battery_count, &len, NULL, 0)) < 0)
6 years ago
{
power->battery_count = 0;
6 years ago
}
if ((sysctlbyname("hw.acpi.acline", NULL, &len, NULL, 0)) != -1)
{
sysctlnametomib("hw.acpi.acline", power->ac_mibs, &len);
}
power->batteries = malloc(power->battery_count * sizeof(bat_t **));
for (int i = 0; i < power->battery_count; i++)
{
power->batteries[i] = calloc(1, sizeof(bat_t));
power->batteries[i]->present = true;
}
6 years ago
#elif defined(__linux__)
char *type;
char path[PATH_MAX];
struct dirent **names;
int i, n, id;
6 years ago
n = scandir("/sys/class/power_supply", &names, 0, alphasort);
if (n < 0) return power->battery_count;
for (i = 0; i < n; i++)
{
snprintf(path, sizeof(path), "/sys/class/power_supply/%s/type",
names[i]->d_name);
type = file_contents(path);
if (type)
6 years ago
{
if (!strncmp(type, "Battery", 7))
{
id = power->battery_count;
power->batteries = realloc(power->batteries, (1 +
power->battery_count) * sizeof(bat_t **));
power->batteries[id] = calloc(1, sizeof(bat_t));
power->batteries[id]->name = strdup(names[i]->d_name);
power->batteries[id]->present = true;
power->battery_count++;
}
free(type);
6 years ago
}
free(names[i]);
6 years ago
}
free(names);
6 years ago
#endif
6 years ago
return power->battery_count;
}
static void
_battery_state_get(power_t *power)
6 years ago
{
#if defined(__OpenBSD__)
int *mib;
double charge_full, charge_current;
6 years ago
size_t slen = sizeof(struct sensor);
struct sensor snsr;
for (int i = 0; i < power->battery_count; i++)
6 years ago
{
charge_full = charge_current = 0;
3 years ago
mib = power->batteries[i]->mibs;
mib[3] = SENSOR_WATTHOUR;
6 years ago
mib[4] = 0;
if (sysctl(mib, 5, &snsr, &slen, NULL, 0) != -1)
charge_full = (double)snsr.value;
mib[3] = SENSOR_WATTHOUR;
6 years ago
mib[4] = 3;
if (sysctl(mib, 5, &snsr, &slen, NULL, 0) != -1)
charge_current = (double)snsr.value;
if (charge_current == 0 || charge_full == 0)
{
mib[3] = SENSOR_AMPHOUR;
mib[4] = 0;
if (sysctl(mib, 5, &snsr, &slen, NULL, 0) != -1)
charge_full = (double)snsr.value;
mib[3] = SENSOR_AMPHOUR;
mib[4] = 3;
if (sysctl(mib, 5, &snsr, &slen, NULL, 0) != -1)
charge_current = (double)snsr.value;
}
power->batteries[i]->charge_full = charge_full;
power->batteries[i]->charge_current = charge_current;
}
6 years ago
#elif defined(__FreeBSD__) || defined(__DragonFly__)
int fd, i;
union acpi_battery_ioctl_arg battio;
char name[256];
if ((fd = open("/dev/acpi", O_RDONLY)) == -1) return;
for (i = 0; i < power->battery_count; i++)