2 * Copyright (c) 2007 Daniel Borca All rights reserved.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 #include <arpa/inet.h>
22 #include <net/ethernet.h>
24 #include <netinet/in.h>
27 #include <sys/ioctl.h>
29 #include <linux/wireless.h>
32 #include "../sensors.h"
33 #include "../system.h"
37 system_get_uptime (int *days
, int *hours
, int *mins
)
43 if (sensors_read_line("/proc/uptime", BUFSIZ
, buf
) <= 0) {
47 if (sscanf(buf
, "%lu", &ut
) != 1) {
63 system_get_cpu_load (int num
, CPUSTAT
*avg
, CPUSTAT load
[])
71 f
= fopen("/proc/stat", "rt");
79 for (i
= 0; i
< num
; i
++) {
83 while (fgets(buf
, BUFSIZ
, f
)) {
88 if (buf
[0] == 'c' && buf
[1] == 'p' && buf
[2] == 'u' && buf
[3] == ' ') {
92 n
= sscanf(buf
+ 4, "%d %d %d %d %d %d %d %d %d %d",
93 &array
[0], &array
[1], &array
[2], &array
[3],
94 &array
[4], &array
[5], &array
[6], &array
[7],
95 &array
[8], &array
[9]);
96 if (n
< 4 || avg
== NULL
) {
105 n
= sscanf(buf
, "cpu%d %d %d %d %d %d %d %d %d %d %d", &i
,
106 &array
[0], &array
[1], &array
[2], &array
[3],
107 &array
[4], &array
[5], &array
[6], &array
[7],
108 &array
[8], &array
[9]);
109 if (--n
< 4 || i
>= num
) {
116 for (total
= 0; n
--; total
+= array
[n
]) {
120 if (total
!= p
->old_total
) {
121 p
->used
= 100 - 100 * (array
[3] - p
->old_idle
) / (total
- p
->old_total
);
124 p
->old_idle
= array
[3];
125 p
->old_total
= total
;
134 system_get_cpu_speed (int num
, int speed
[])
142 f
= fopen("/proc/cpuinfo", "rt");
147 for (i
= 0; i
< num
; i
++) {
151 while (fgets(buf
, BUFSIZ
, f
)) {
152 sscanf(buf
, "processor : %d", &i
);
154 ok
+= sscanf(buf
, "cpu MHz : %d", &speed
[i
]);
164 system_get_cpu_gov (int cpu
, int max
, char *out
)
168 sprintf(filename
, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor", cpu
);
170 if (sensors_read_line(filename
, max
, out
) <= 0) {
179 system_get_mem_stat (int *mem_free
, int *mem_total
, int *swp_free
, int *swp_total
)
184 f
= fopen("/proc/meminfo", "rt");
194 while (fgets(buf
, BUFSIZ
, f
)) {
195 sscanf(buf
, "MemTotal: %d", mem_total
);
196 sscanf(buf
, "MemFree: %d", mem_free
);
197 sscanf(buf
, "SwapTotal: %d", swp_total
);
198 sscanf(buf
, "SwapFree: %d", swp_free
);
207 system_get_max_temp (SENSOR
*list
, int *temp
, int *crit
)
216 list_foreach (s
, list
) {
217 if (s
->type
== S_ACPI_THERMAL_ZONE
&&
218 sensors_read_line(s
->filename
, BUFSIZ
, buf
) > 0 &&
219 sscanf(buf
, "temperature: %d", &tmp
) == 1) {
220 if (100 * tmp
> 90 * s
->idata
) {
227 if (s
->type
== S_HWMON_CORETEMP
&&
228 sensors_read_line(s
->filename
, BUFSIZ
, buf
) > 0 &&
229 sscanf(buf
, "%d", &tmp
) == 1) {
230 if (100 * tmp
> 90 * s
->idata
) {
233 if (max
* 1000 < tmp
) {
249 system_get_temperature (SENSOR
*list
, int num
, TEMPSTAT temp
[])
255 list_foreach (s
, list
) {
259 if (s
->type
== S_ACPI_THERMAL_ZONE
&&
260 sensors_read_line(s
->filename
, BUFSIZ
, buf
) > 0 &&
261 sscanf(buf
, "temperature: %d", &temp
[i
].temp
) == 1) {
262 temp
[i
].max
= s
->idata
;
263 strncpy(temp
[i
].name
, s
->name
, 7);
264 temp
[i
].name
[7] = '\0';
267 if (s
->type
== S_HWMON_CORETEMP
&&
268 sensors_read_line(s
->filename
, BUFSIZ
, buf
) > 0 &&
269 sscanf(buf
, "%d", &temp
[i
].temp
) == 1) {
270 temp
[i
].temp
/= 1000;
271 temp
[i
].max
= s
->idata
/ 1000;
272 strncpy(temp
[i
].name
, s
->name
, 7);
273 temp
[i
].name
[7] = '\0';
276 if (s
->type
== S_NVIDIA_SETTINGS_GPUCORETEMP
&&
277 sensors_nvidia(s
->name
, &temp
[i
].temp
) == 0) {
278 temp
[i
].max
= s
->idata
;
279 strncpy(temp
[i
].name
, s
->name
, 7);
280 temp
[i
].name
[7] = '\0';
290 system_get_best_wifi (int *wifi
)
297 f
= fopen("/proc/net/wireless", "rt");
302 while (fgets(buf
, BUFSIZ
, f
)) {
303 if (sscanf(buf
, "%*s %*d %d", &tmp
) == 1 &&
320 system_get_ac_adapter (SENSOR
*list
)
325 list_foreach (s
, list
) {
326 if (s
->type
== S_ACPI_AC_ADAPTER
&&
327 sensors_read_line(s
->filename
, BUFSIZ
, buf
) > 0 &&
328 strstr(buf
, "on-line")) {
338 system_get_battery (SENSOR
*list
, int num
, BATSTAT
*total
, BATSTAT batt
[])
346 total
->name
[0] = '\0';
351 list_foreach (s
, list
) {
352 if (s
->type
== S_ACPI_BATTERY
) {
360 strcpy(strrchr(s
->filename
, '/'), "/state");
361 f
= fopen(s
->filename
, "rt");
365 while (fgets(buf
, sizeof(buf
), f
)) {
366 if (strstr(buf
, "present:") && strstr(buf
, "yes")) {
369 /*if (strstr(buf, "charging state:")) {
370 if (strstr(buf + 15, "charging")) {
373 if (strstr(buf + 15, "discharging")) {
376 if (all_state * charging < 0) {
377 printf("cannot charge and discharge at the same time\n");
380 sscanf(buf
, "remaining capacity: %d", &curr_cap
);
381 sscanf(buf
, "present rate: %d", &rate
);
389 strcpy(strrchr(s
->filename
, '/'), "/info");
390 f
= fopen(s
->filename
, "rt");
394 while (fgets(buf
, sizeof(buf
), f
)) {
395 sscanf(buf
, "design capacity: %d", &full_cap
);
396 sscanf(buf
, "last full capacity: %d", &full_cap
);
404 total
->full_cap
+= full_cap
;
405 total
->curr_cap
+= curr_cap
;
408 strncpy(batt
[n
].name
, s
->name
, sizeof(total
->name
) - 1);
409 batt
[n
].name
[sizeof(total
->name
) - 1] = '\0';
410 batt
[n
].full_cap
= full_cap
;
411 batt
[n
].curr_cap
= curr_cap
;
414 all_state
|= charging
;
424 system_get_netif (int num
, IFSTAT
*ifaces
)
433 /* proc does not expose ethX:Y aliases */
434 /* http://www-128.ibm.com/developerworks/aix/library/au-ioctl-socket.html */
435 f
= fopen("/proc/net/dev", "rt");
440 sock
= socket(AF_INET
, SOCK_DGRAM
, 0);
446 while (fgets(buf
, BUFSIZ
, f
)) {
450 struct iw_statistics iws
;
455 if (q
- ifaces
>= num
) {
458 p
= strrchr(buf
, ':');
463 for (p
= buf
; isspace(*p
); p
++) {
466 strcpy(ifr
.ifr_name
, p
);
467 if (ioctl(sock
, SIOCGIFFLAGS
, (caddr_t
)&ifr
) < 0) {
470 if (ifr
.ifr_flags
& IFF_LOOPBACK
) {
473 if (!(ifr
.ifr_flags
& IFF_UP
)) {
477 strncpy(q
->name
, p
, sizeof(q
->name
));
478 q
->name
[sizeof(q
->name
) - 1] = '\0';
483 if (ifr
.ifr_flags
& IFF_UP
) {
484 if (ioctl(sock
, SIOCGIFADDR
, (caddr_t
)&ifr
) >= 0) {
485 q
->ipv4
= ntohl(((struct sockaddr_in
*)&ifr
.ifr_addr
)->sin_addr
.s_addr
);
489 strncpy(iwr
.ifr_name
, p
, IFNAMSIZ
);
490 iwr
.u
.essid
.pointer
= (caddr_t
)&q
->essid
;
491 iwr
.u
.essid
.length
= sizeof(q
->essid
);
492 iwr
.u
.essid
.flags
= 0;
493 if (ioctl(sock
, SIOCGIWESSID
, &iwr
) >= 0) {
494 q
->essid
[iwr
.u
.essid
.length
] = '\0';
497 iwr
.u
.essid
.pointer
= (caddr_t
)&iws
;
498 iwr
.u
.essid
.length
= sizeof(iws
);
499 iwr
.u
.essid
.flags
= 0;
500 if (ioctl(sock
, SIOCGIWSTATS
, &iwr
) >= 0) {
501 q
->wlink
= iws
.qual
.qual
;