/* * 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 #include #include #include #include #include #include #include #include #include #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; }