Add missing libraries to examples' Makefiles
[dockapps.git] / wmfu / linux / system.c
bloba2dddc882db45f577fa389326767de0ff5c619c7
1 /*
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>
21 #include <ctype.h>
22 #include <net/ethernet.h>
23 #include <net/if.h>
24 #include <netinet/in.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <sys/ioctl.h>
28 #include <unistd.h>
29 #include <linux/wireless.h>
31 #include "../list.h"
32 #include "../sensors.h"
33 #include "../system.h"
36 int
37 system_get_uptime (int *days, int *hours, int *mins)
39 char buf[BUFSIZ];
41 unsigned long ut;
43 if (sensors_read_line("/proc/uptime", BUFSIZ, buf) <= 0) {
44 return 0;
47 if (sscanf(buf, "%lu", &ut) != 1) {
48 return 0;
51 ut /= 60;
52 *mins = ut % 60;
53 ut /= 60;
54 *hours = ut % 24;
55 ut /= 24;
56 *days = ut;
58 return 1;
62 int
63 system_get_cpu_load (int num, CPUSTAT *avg, CPUSTAT load[])
65 FILE *f;
66 char buf[BUFSIZ];
68 int i;
69 int ok = 0;
71 f = fopen("/proc/stat", "rt");
72 if (f == NULL) {
73 return 0;
76 if (avg != NULL) {
77 avg->used = -1;
79 for (i = 0; i < num; i++) {
80 load[i].used = -1;
83 while (fgets(buf, BUFSIZ, f)) {
84 CPUSTAT *p;
85 int array[10], total;
86 int n;
88 if (buf[0] == 'c' && buf[1] == 'p' && buf[2] == 'u' && buf[3] == ' ') {
89 if (avg == NULL) {
90 continue;
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) {
97 continue;
99 p = avg;
100 ok |= 1;
101 } else {
102 if (!num) {
103 continue;
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) {
110 continue;
112 p = &load[i];
113 ok |= 2;
116 for (total = 0; n--; total += array[n]) {
119 p->used = 0;
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;
127 fclose(f);
129 return ok;
134 system_get_cpu_speed (int num, int speed[])
136 FILE *f;
137 char buf[BUFSIZ];
139 int i;
140 int ok = 0;
142 f = fopen("/proc/cpuinfo", "rt");
143 if (f == NULL) {
144 return 0;
147 for (i = 0; i < num; i++) {
148 speed[i] = -1;
151 while (fgets(buf, BUFSIZ, f)) {
152 sscanf(buf, "processor : %d", &i);
153 if (i < num) {
154 ok += sscanf(buf, "cpu MHz : %d", &speed[i]);
157 fclose(f);
159 return ok;
164 system_get_cpu_gov (int cpu, int max, char *out)
166 char filename[128];
168 sprintf(filename, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor", cpu);
170 if (sensors_read_line(filename, max, out) <= 0) {
171 return 0;
174 return 1;
179 system_get_mem_stat (int *mem_free, int *mem_total, int *swp_free, int *swp_total)
181 FILE *f;
182 char buf[BUFSIZ];
184 f = fopen("/proc/meminfo", "rt");
185 if (f == NULL) {
186 return 0;
189 *mem_free = 0;
190 *mem_total = 0;
191 *swp_free = 0;
192 *swp_total = 0;
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);
200 fclose(f);
202 return 1;
207 system_get_max_temp (SENSOR *list, int *temp, int *crit)
209 SENSOR *s;
210 char buf[BUFSIZ];
212 int tmp, max = -1;
214 *crit = 0;
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) {
221 *crit = 1;
223 if (max < tmp) {
224 max = tmp;
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) {
231 *crit = 1;
233 if (max * 1000 < tmp) {
234 max = tmp / 1000;
239 if (max < 0) {
240 return 0;
243 *temp = max;
244 return 1;
249 system_get_temperature (SENSOR *list, int num, TEMPSTAT temp[])
251 SENSOR *s;
252 char buf[BUFSIZ];
253 int i = 0;
255 list_foreach (s, list) {
256 if (i >= num) {
257 break;
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';
265 i++;
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';
274 i++;
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';
281 i++;
285 return i;
290 system_get_best_wifi (int *wifi)
292 FILE *f;
293 char buf[BUFSIZ];
295 int tmp, max = -1;
297 f = fopen("/proc/net/wireless", "rt");
298 if (f == NULL) {
299 return 0;
302 while (fgets(buf, BUFSIZ, f)) {
303 if (sscanf(buf, "%*s %*d %d", &tmp) == 1 &&
304 max < tmp) {
305 max = tmp;
308 fclose(f);
310 if (max < 0) {
311 return 0;
314 *wifi = max;
315 return 1;
320 system_get_ac_adapter (SENSOR *list)
322 SENSOR *s;
323 char buf[BUFSIZ];
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")) {
329 return 1;
333 return 0;
338 system_get_battery (SENSOR *list, int num, BATSTAT *total, BATSTAT batt[])
340 SENSOR *s;
341 char buf[BUFSIZ];
343 int n = 0;
345 int all_state = 0;
346 total->name[0] = '\0';
347 total->full_cap = 0;
348 total->curr_cap = 0;
349 total->rate = 0;
351 list_foreach (s, list) {
352 if (s->type == S_ACPI_BATTERY) {
353 FILE *f;
354 int present = 0;
355 int full_cap = 0;
356 int curr_cap = 0;
357 int charging = 0;
358 int rate = 0;
360 strcpy(strrchr(s->filename, '/'), "/state");
361 f = fopen(s->filename, "rt");
362 if (f == NULL) {
363 continue;
365 while (fgets(buf, sizeof(buf), f)) {
366 if (strstr(buf, "present:") && strstr(buf, "yes")) {
367 present = 1;
369 /*if (strstr(buf, "charging state:")) {
370 if (strstr(buf + 15, "charging")) {
371 charging = 1;
373 if (strstr(buf + 15, "discharging")) {
374 charging = -1;
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);
383 fclose(f);
385 if (!present) {
386 continue;
389 strcpy(strrchr(s->filename, '/'), "/info");
390 f = fopen(s->filename, "rt");
391 if (f == NULL) {
392 continue;
394 while (fgets(buf, sizeof(buf), f)) {
395 sscanf(buf, "design capacity: %d", &full_cap);
396 sscanf(buf, "last full capacity: %d", &full_cap);
398 fclose(f);
400 if (!full_cap) {
401 continue;
404 total->full_cap += full_cap;
405 total->curr_cap += curr_cap;
406 total->rate += rate;
407 if (n < num) {
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;
412 batt[n].rate = rate;
414 all_state |= charging;
415 n++;
419 return n;
424 system_get_netif (int num, IFSTAT *ifaces)
426 FILE *f;
427 int sock;
428 char buf[BUFSIZ];
430 IFSTAT *q = ifaces;
431 int i = 0;
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");
436 if (f == NULL) {
437 return 0;
440 sock = socket(AF_INET, SOCK_DGRAM, 0);
441 if (sock < 0) {
442 fclose(f);
443 return 0;
446 while (fgets(buf, BUFSIZ, f)) {
447 char *p;
448 struct ifreq ifr;
449 struct iwreq iwr;
450 struct iw_statistics iws;
452 if (i++ < 2) {
453 continue;
455 if (q - ifaces >= num) {
456 break;
458 p = strrchr(buf, ':');
459 if (p == NULL) {
460 continue;
462 *p = '\0';
463 for (p = buf; isspace(*p); p++) {
466 strcpy(ifr.ifr_name, p);
467 if (ioctl(sock, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
468 continue;
470 if (ifr.ifr_flags & IFF_LOOPBACK) {
471 continue;
473 if (!(ifr.ifr_flags & IFF_UP)) {
474 continue;
477 strncpy(q->name, p, sizeof(q->name));
478 q->name[sizeof(q->name) - 1] = '\0';
479 q->essid[0] = '\0';
480 q->ipv4 = -1;
481 q->wlink = -1;
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;
504 q++;
506 close(sock);
507 fclose(f);
509 return q - ifaces;