dockapps/wmfu/linux/system.c
2017-02-24 10:08:06 +00:00

511 lines
9.7 KiB
C

/*
* Copyright (c) 2007 Daniel Borca All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <arpa/inet.h>
#include <ctype.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <linux/wireless.h>
#include "../list.h"
#include "../sensors.h"
#include "../system.h"
int
system_get_uptime (int *days, int *hours, int *mins)
{
char buf[BUFSIZ];
unsigned long ut;
if (sensors_read_line("/proc/uptime", BUFSIZ, buf) <= 0) {
return 0;
}
if (sscanf(buf, "%lu", &ut) != 1) {
return 0;
}
ut /= 60;
*mins = ut % 60;
ut /= 60;
*hours = ut % 24;
ut /= 24;
*days = ut;
return 1;
}
int
system_get_cpu_load (int num, CPUSTAT *avg, CPUSTAT load[])
{
FILE *f;
char buf[BUFSIZ];
int i;
int ok = 0;
f = fopen("/proc/stat", "rt");
if (f == NULL) {
return 0;
}
if (avg != NULL) {
avg->used = -1;
}
for (i = 0; i < num; i++) {
load[i].used = -1;
}
while (fgets(buf, BUFSIZ, f)) {
CPUSTAT *p;
int array[10], total;
int n;
if (buf[0] == 'c' && buf[1] == 'p' && buf[2] == 'u' && buf[3] == ' ') {
if (avg == NULL) {
continue;
}
n = sscanf(buf + 4, "%d %d %d %d %d %d %d %d %d %d",
&array[0], &array[1], &array[2], &array[3],
&array[4], &array[5], &array[6], &array[7],
&array[8], &array[9]);
if (n < 4 || avg == NULL) {
continue;
}
p = avg;
ok |= 1;
} else {
if (!num) {
continue;
}
n = sscanf(buf, "cpu%d %d %d %d %d %d %d %d %d %d %d", &i,
&array[0], &array[1], &array[2], &array[3],
&array[4], &array[5], &array[6], &array[7],
&array[8], &array[9]);
if (--n < 4 || i >= num) {
continue;
}
p = &load[i];
ok |= 2;
}
for (total = 0; n--; total += array[n]) {
}
p->used = 0;
if (total != p->old_total) {
p->used = 100 - 100 * (array[3] - p->old_idle) / (total - p->old_total);
}
p->old_idle = array[3];
p->old_total = total;
}
fclose(f);
return ok;
}
int
system_get_cpu_speed (int num, int speed[])
{
FILE *f;
char buf[BUFSIZ];
int i;
int ok = 0;
f = fopen("/proc/cpuinfo", "rt");
if (f == NULL) {
return 0;
}
for (i = 0; i < num; i++) {
speed[i] = -1;
}
while (fgets(buf, BUFSIZ, f)) {
sscanf(buf, "processor : %d", &i);
if (i < num) {
ok += sscanf(buf, "cpu MHz : %d", &speed[i]);
}
}
fclose(f);
return ok;
}
int
system_get_cpu_gov (int cpu, int max, char *out)
{
char filename[128];
sprintf(filename, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor", cpu);
if (sensors_read_line(filename, max, out) <= 0) {
return 0;
}
return 1;
}
int
system_get_mem_stat (int *mem_free, int *mem_total, int *swp_free, int *swp_total)
{
FILE *f;
char buf[BUFSIZ];
f = fopen("/proc/meminfo", "rt");
if (f == NULL) {
return 0;
}
*mem_free = 0;
*mem_total = 0;
*swp_free = 0;
*swp_total = 0;
while (fgets(buf, BUFSIZ, f)) {
sscanf(buf, "MemTotal: %d", mem_total);
sscanf(buf, "MemFree: %d", mem_free);
sscanf(buf, "SwapTotal: %d", swp_total);
sscanf(buf, "SwapFree: %d", swp_free);
}
fclose(f);
return 1;
}
int
system_get_max_temp (SENSOR *list, int *temp, int *crit)
{
SENSOR *s;
char buf[BUFSIZ];
int tmp, max = -1;
*crit = 0;
list_foreach (s, list) {
if (s->type == S_ACPI_THERMAL_ZONE &&
sensors_read_line(s->filename, BUFSIZ, buf) > 0 &&
sscanf(buf, "temperature: %d", &tmp) == 1) {
if (100 * tmp > 90 * s->idata) {
*crit = 1;
}
if (max < tmp) {
max = tmp;
}
}
if (s->type == S_HWMON_CORETEMP &&
sensors_read_line(s->filename, BUFSIZ, buf) > 0 &&
sscanf(buf, "%d", &tmp) == 1) {
if (100 * tmp > 90 * s->idata) {
*crit = 1;
}
if (max * 1000 < tmp) {
max = tmp / 1000;
}
}
}
if (max < 0) {
return 0;
}
*temp = max;
return 1;
}
int
system_get_temperature (SENSOR *list, int num, TEMPSTAT temp[])
{
SENSOR *s;
char buf[BUFSIZ];
int i = 0;
list_foreach (s, list) {
if (i >= num) {
break;
}
if (s->type == S_ACPI_THERMAL_ZONE &&
sensors_read_line(s->filename, BUFSIZ, buf) > 0 &&
sscanf(buf, "temperature: %d", &temp[i].temp) == 1) {
temp[i].max = s->idata;
strncpy(temp[i].name, s->name, 7);
temp[i].name[7] = '\0';
i++;
}
if (s->type == S_HWMON_CORETEMP &&
sensors_read_line(s->filename, BUFSIZ, buf) > 0 &&
sscanf(buf, "%d", &temp[i].temp) == 1) {
temp[i].temp /= 1000;
temp[i].max = s->idata / 1000;
strncpy(temp[i].name, s->name, 7);
temp[i].name[7] = '\0';
i++;
}
if (s->type == S_NVIDIA_SETTINGS_GPUCORETEMP &&
sensors_nvidia(s->name, &temp[i].temp) == 0) {
temp[i].max = s->idata;
strncpy(temp[i].name, s->name, 7);
temp[i].name[7] = '\0';
i++;
}
}
return i;
}
int
system_get_best_wifi (int *wifi)
{
FILE *f;
char buf[BUFSIZ];
int tmp, max = -1;
f = fopen("/proc/net/wireless", "rt");
if (f == NULL) {
return 0;
}
while (fgets(buf, BUFSIZ, f)) {
if (sscanf(buf, "%*s %*d %d", &tmp) == 1 &&
max < tmp) {
max = tmp;
}
}
fclose(f);
if (max < 0) {
return 0;
}
*wifi = max;
return 1;
}
int
system_get_ac_adapter (SENSOR *list)
{
SENSOR *s;
char buf[BUFSIZ];
list_foreach (s, list) {
if (s->type == S_ACPI_AC_ADAPTER &&
sensors_read_line(s->filename, BUFSIZ, buf) > 0 &&
strstr(buf, "on-line")) {
return 1;
}
}
return 0;
}
int
system_get_battery (SENSOR *list, int num, BATSTAT *total, BATSTAT batt[])
{
SENSOR *s;
char buf[BUFSIZ];
int n = 0;
int all_state = 0;
total->name[0] = '\0';
total->full_cap = 0;
total->curr_cap = 0;
total->rate = 0;
list_foreach (s, list) {
if (s->type == S_ACPI_BATTERY) {
FILE *f;
int present = 0;
int full_cap = 0;
int curr_cap = 0;
int charging = 0;
int rate = 0;
strcpy(strrchr(s->filename, '/'), "/state");
f = fopen(s->filename, "rt");
if (f == NULL) {
continue;
}
while (fgets(buf, sizeof(buf), f)) {
if (strstr(buf, "present:") && strstr(buf, "yes")) {
present = 1;
}
/*if (strstr(buf, "charging state:")) {
if (strstr(buf + 15, "charging")) {
charging = 1;
}
if (strstr(buf + 15, "discharging")) {
charging = -1;
}
if (all_state * charging < 0) {
printf("cannot charge and discharge at the same time\n");
}
}*/
sscanf(buf, "remaining capacity: %d", &curr_cap);
sscanf(buf, "present rate: %d", &rate);
}
fclose(f);
if (!present) {
continue;
}
strcpy(strrchr(s->filename, '/'), "/info");
f = fopen(s->filename, "rt");
if (f == NULL) {
continue;
}
while (fgets(buf, sizeof(buf), f)) {
sscanf(buf, "design capacity: %d", &full_cap);
sscanf(buf, "last full capacity: %d", &full_cap);
}
fclose(f);
if (!full_cap) {
continue;
}
total->full_cap += full_cap;
total->curr_cap += curr_cap;
total->rate += rate;
if (n < num) {
strncpy(batt[n].name, s->name, sizeof(total->name) - 1);
batt[n].name[sizeof(total->name) - 1] = '\0';
batt[n].full_cap = full_cap;
batt[n].curr_cap = curr_cap;
batt[n].rate = rate;
}
all_state |= charging;
n++;
}
}
return n;
}
int
system_get_netif (int num, IFSTAT *ifaces)
{
FILE *f;
int sock;
char buf[BUFSIZ];
IFSTAT *q = ifaces;
int i = 0;
/* proc does not expose ethX:Y aliases */
/* http://www-128.ibm.com/developerworks/aix/library/au-ioctl-socket.html */
f = fopen("/proc/net/dev", "rt");
if (f == NULL) {
return 0;
}
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
fclose(f);
return 0;
}
while (fgets(buf, BUFSIZ, f)) {
char *p;
struct ifreq ifr;
struct iwreq iwr;
struct iw_statistics iws;
if (i++ < 2) {
continue;
}
if (q - ifaces >= num) {
break;
}
p = strrchr(buf, ':');
if (p == NULL) {
continue;
}
*p = '\0';
for (p = buf; isspace(*p); p++) {
}
strcpy(ifr.ifr_name, p);
if (ioctl(sock, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
continue;
}
if (ifr.ifr_flags & IFF_LOOPBACK) {
continue;
}
if (!(ifr.ifr_flags & IFF_UP)) {
continue;
}
strncpy(q->name, p, sizeof(q->name));
q->name[sizeof(q->name) - 1] = '\0';
q->essid[0] = '\0';
q->ipv4 = -1;
q->wlink = -1;
if (ifr.ifr_flags & IFF_UP) {
if (ioctl(sock, SIOCGIFADDR, (caddr_t)&ifr) >= 0) {
q->ipv4 = ntohl(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr);
}
}
strncpy(iwr.ifr_name, p, IFNAMSIZ);
iwr.u.essid.pointer = (caddr_t)&q->essid;
iwr.u.essid.length = sizeof(q->essid);
iwr.u.essid.flags = 0;
if (ioctl(sock, SIOCGIWESSID, &iwr) >= 0) {
q->essid[iwr.u.essid.length] = '\0';
}
iwr.u.essid.pointer = (caddr_t)&iws;
iwr.u.essid.length = sizeof(iws);
iwr.u.essid.flags = 0;
if (ioctl(sock, SIOCGIWSTATS, &iwr) >= 0) {
q->wlink = iws.qual.qual;
}
q++;
}
close(sock);
fclose(f);
return q - ifaces;
}