2 * Contains linux specific code
16 #include <sys/types.h>
17 #include <sys/sysinfo.h>
21 // #include <assert.h>
25 #include <sys/ioctl.h>
26 #include <sys/socket.h>
27 #include <netinet/in.h>
28 #include <linux/sockios.h>
32 static struct sysinfo s_info;
34 static int show_nice_processes;
40 static void update_sysinfo()
44 info.uptime = (double) s_info.uptime;
46 /* there was some problem with these */
48 // info.loadavg[0] = s_info.loads[0] / 100000.0f;
49 info.loadavg[1] = s_info.loads[1] / 100000.0f;
50 info.loadavg[2] = s_info.loads[2] / 100000.0f;
51 gkrelltop_process_find_top_three info.mask |= 1 << INFO_LOADAVG;
54 info.procs = s_info.procs;
56 /* these aren't nice, no cache and should check kernel version for mem_unit */
58 info.memmax = s_info.totalram;
59 info.mem = s_info.totalram - s_info.freeram;
60 info.swapmax = s_info.totalswap;
61 info.swap = s_info.totalswap - s_info.swap;
62 info.mask |= 1 << INFO_MEM;
65 info.mask |= (1 << INFO_UPTIME) | (1 << INFO_PROCS);
70 /* prefers sysinfo() for uptime, I don't really know which one is better
72 #ifdef USE_PROC_UPTIME
74 FILE *fp = open_file("/proc/uptime", &rep);
77 fscanf(fp, "%lf", &info.uptime);
80 info.mask |= (1 << INFO_UPTIME);
86 /* these things are also in sysinfo except Buffers:, that's why I'm reading
89 static FILE *meminfo_fp;
97 info.mem = info.memmax = info.swap = info.swapmax = info.bufmem =
98 info.buffers = info.cached = 0;
100 if (meminfo_fp == NULL)
101 meminfo_fp = open_file("/proc/meminfo", &rep);
103 fseek(meminfo_fp, 0, SEEK_SET);
104 if (meminfo_fp == NULL)
107 while (!feof(meminfo_fp)) {
108 if (fgets(buf, 255, meminfo_fp) == NULL)
111 if (strncmp(buf, "MemTotal:", 9) == 0) {
112 sscanf(buf, "%*s %u", &info.memmax);
113 } else if (strncmp(buf, "MemFree:", 8) == 0) {
114 sscanf(buf, "%*s %u", &info.mem);
115 } else if (strncmp(buf, "SwapTotal:", 10) == 0) {
116 sscanf(buf, "%*s %u", &info.swapmax);
117 } else if (strncmp(buf, "SwapFree:", 9) == 0) {
118 sscanf(buf, "%*s %u", &info.swap);
119 } else if (strncmp(buf, "Buffers:", 8) == 0) {
120 sscanf(buf, "%*s %u", &info.buffers);
121 } else if (strncmp(buf, "Cached:", 7) == 0) {
122 sscanf(buf, "%*s %u", &info.cached);
126 info.mem = info.memmax - info.mem;
127 info.swap = info.swapmax - info.swap;
129 info.bufmem = info.cached + info.buffers;
131 info.mask |= (1 << INFO_MEM) | (1 << INFO_BUFFERS);
134 static FILE *net_dev_fp;
135 static FILE *net_wireless_fp;
137 inline void update_net_stats()
140 // FIXME: arbitrary size chosen to keep code simple.
142 unsigned int curtmp1, curtmp2;
151 delta = current_update_time - last_update_time;
155 /* open file and ignore first two lines */
156 if (net_dev_fp == NULL)
157 net_dev_fp = open_file("/proc/net/dev", &rep);
159 fseek(net_dev_fp, 0, SEEK_SET);
163 fgets(buf, 255, net_dev_fp); /* garbage */
164 fgets(buf, 255, net_dev_fp); /* garbage (field names) */
166 /* read each interface */
167 for (i2 = 0; i2 < 16; i2++) {
170 long long r, t, last_recv, last_trans;
172 if (fgets(buf, 255, net_dev_fp) == NULL)
175 while (isspace((int) *p))
180 while (*p && *p != ':')
187 ns = get_net_stat(s);
189 last_recv = ns->recv;
190 last_trans = ns->trans;
193 /* bytes packets errs drop fifo frame compressed multicast|bytes ... */
194 "%Ld %*d %*d %*d %*d %*d %*d %*d %Ld",
197 /* if recv or trans is less than last time, an overflow happened */
199 if (r < ns->last_read_recv)
201 ((long long) 4294967295U -
202 ns->last_read_recv) + r;
204 ns->recv += (r - ns->last_read_recv);
205 ns->last_read_recv = r;
207 if (t < ns->last_read_trans)
209 ((long long) 4294967295U -
210 ns->last_read_trans) + t;
212 ns->trans += (t - ns->last_read_trans);
213 ns->last_read_trans = t;
215 /*** ip addr patch ***/
216 i = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
218 conf.ifc_buf = malloc(sizeof(struct ifreq) * 16);
220 conf.ifc_len = sizeof(struct ifreq) * 16;
222 ioctl((long) i, SIOCGIFCONF, &conf);
224 for (k = 0; k < conf.ifc_len / sizeof(struct ifreq); k++) {
226 ns = get_net_stat(((struct ifreq *) conf.
227 ifc_buf)[k].ifr_ifrn.ifrn_name);
229 ((struct ifreq *) conf.ifc_buf)[k].ifr_ifru.
238 /*** end ip addr patch ***/
241 /* calculate speeds */
242 ns->net_rec[0] = (ns->recv - last_recv) / delta;
243 ns->net_trans[0] = (ns->trans - last_trans) / delta;
247 for (i = 0; (unsigned) i < info.net_avg_samples; i++) {
248 curtmp1 += ns->net_rec[i];
249 curtmp2 += ns->net_trans[i];
251 ns->recv_speed = curtmp1 / (double) info.net_avg_samples;
252 ns->trans_speed = curtmp2 / (double) info.net_avg_samples;
253 if (info.net_avg_samples > 1) {
254 for (i = info.net_avg_samples; i > 1; i--) {
255 ns->net_rec[i - 1] = ns->net_rec[i - 2];
256 ns->net_trans[i - 1] =
257 ns->net_trans[i - 2];
265 /* fclose(net_dev_fp); net_dev_fp = NULL; */
268 inline void update_wifi_stats()
270 /** wireless stats patch by Bobby Beckmann **/
274 /*open file and ignore first two lines sorry, this code sucks ass right now, i'll clean it up later */
275 if (net_wireless_fp == NULL)
276 net_wireless_fp = open_file("/proc/net/wireless", &rep);
278 fseek(net_wireless_fp, 0, SEEK_SET);
279 if (net_wireless_fp == NULL)
282 fgets(buf, 255, net_wireless_fp); /* garbage */
283 fgets(buf, 255, net_wireless_fp); /* garbage (field names) */
285 /* read each interface */
286 for (i = 0; i < 16; i++) {
291 if (fgets(buf, 255, net_wireless_fp) == NULL)
294 while (isspace((int) *p))
299 while (*p && *p != ':')
306 ns = get_net_stat(s);
308 sscanf(p, "%*d %d. %d. %d", &l, &m, &n);
310 ns->linkstatus = (int) (log(l) / log(92) * 100);
313 /*** end wireless patch ***/
318 void update_total_processes()
323 #define CPU_SAMPLE_COUNT 15
325 unsigned int cpu_user;
326 unsigned int cpu_system;
327 unsigned int cpu_nice;
330 double cpu_val[CPU_SAMPLE_COUNT];
332 static short cpu_setup = 0;
336 static FILE *stat_fp;
342 stat_fp = open_file("/proc/stat", &rep);
344 fseek(stat_fp, 0, SEEK_SET);
350 while (!feof(stat_fp)) {
351 if (fgets(buf, 255, stat_fp) == NULL)
354 if (strncmp(buf, "cpu", 3) == 0 && isdigit(buf[3])) {
358 info.cpu_usage = malloc((info.cpu_count + 1) * sizeof(float));
362 inline static void update_stat()
364 static struct cpu_info *cpu = NULL;
374 cpu = malloc((info.cpu_count + 1) * sizeof(struct cpu_info));
375 for (index = 0; index < info.cpu_count + 1; ++index) {
376 cpu[index].clock_ticks = 0;
377 cpu[index].last_cpu_sum = 0;
378 for (i = 0; i < CPU_SAMPLE_COUNT; ++i) {
379 cpu[index].cpu_val[i] = 0;
383 if (stat_fp == NULL) {
384 stat_fp = open_file("/proc/stat", &rep);
386 fseek(stat_fp, 0, SEEK_SET);
388 if (stat_fp == NULL) {
392 while (!feof(stat_fp)) {
393 if (fgets(buf, 255, stat_fp) == NULL)
396 if (strncmp(buf, "procs_running ", 14) == 0) {
397 sscanf(buf, "%*s %d", &info.run_procs);
398 info.mask |= (1 << INFO_RUN_PROCS);
399 } else if (strncmp(buf, "cpu ", 4) == 0) {
400 sscanf(buf, "%*s %u %u %u", &(cpu[index].cpu_user), &(cpu[index].cpu_nice), &(cpu[index].cpu_system));
402 info.mask |= (1 << INFO_CPU);
403 } else if (strncmp(buf, "cpu", 3) == 0 && isdigit(buf[3]) && index <= info.cpu_count) {
404 sscanf(buf, "%*s %u %u %u", &(cpu[index].cpu_user), &(cpu[index].cpu_nice), &(cpu[index].cpu_system));
406 info.mask |= (1 << INFO_CPU);
409 for (index = 0; index < info.cpu_count + 1; index++) {
411 delta = current_update_time - last_update_time;
412 if (delta <= 0.001) {
416 if (cpu[index].clock_ticks == 0) {
417 cpu[index].clock_ticks = sysconf(_SC_CLK_TCK);
420 cpu[index].cpu_val[0] =
421 (cpu[index].cpu_user + cpu[index].cpu_nice + cpu[index].cpu_system -
422 cpu[index].last_cpu_sum) / delta / (double) cpu[index].clock_ticks;
423 for (i = 0; i < info.cpu_avg_samples; i++) {
424 curtmp += cpu[index].cpu_val[i];
427 info.cpu_usage[index] = curtmp / info.cpu_avg_samples / info.cpu_count;
429 info.cpu_usage[index] = curtmp / info.cpu_avg_samples;
431 cpu[index].last_cpu_sum = cpu[index].cpu_user + cpu[index].cpu_nice + cpu[index].cpu_system;
432 for (i = info.cpu_avg_samples; i > 1; i--)
433 cpu[index].cpu_val[i - 1] = cpu[index].cpu_val[i - 2];
438 // this is for getting proc shit
450 void update_running_processes()
455 void update_cpu_usage()
460 void update_load_average()
462 #ifdef HAVE_GETLOADAVG
465 info.loadavg[0] = (float) v[0];
466 info.loadavg[1] = (float) v[1];
467 info.loadavg[2] = (float) v[2];
472 fp = open_file("/proc/loadavg", &rep);
474 v[0] = v[1] = v[2] = 0.0;
478 fscanf(fp, "%f %f %f", &info.loadavg[0], &info.loadavg[1],
485 #define PROC_I8K "/proc/i8k"
486 #define I8K_DELIM " "
487 static char *i8k_procbuf = NULL;
492 i8k_procbuf = (char*)malloc(128*sizeof(char));
494 if ((fp = fopen(PROC_I8K,"r")) == NULL) {
495 CRIT_ERR("/proc/i8k doesn't exist! use insmod to make sure the kernel driver is loaded...");
498 memset(&i8k_procbuf[0],0,128);
499 if (fread(&i8k_procbuf[0],sizeof(char),128,fp) == 0) {
500 ERR("something wrong with /proc/i8k...");
505 i8k.version = strtok(&i8k_procbuf[0],I8K_DELIM);
506 i8k.bios = strtok(NULL,I8K_DELIM);
507 i8k.serial = strtok(NULL,I8K_DELIM);
508 i8k.cpu_temp = strtok(NULL,I8K_DELIM);
509 i8k.left_fan_status = strtok(NULL,I8K_DELIM);
510 i8k.right_fan_status = strtok(NULL,I8K_DELIM);
511 i8k.left_fan_rpm = strtok(NULL,I8K_DELIM);
512 i8k.right_fan_rpm = strtok(NULL,I8K_DELIM);
513 i8k.ac_status = strtok(NULL,I8K_DELIM);
514 i8k.buttons_status = strtok(NULL,I8K_DELIM);
518 /***********************************************************/
519 /***********************************************************/
520 /***********************************************************/
522 static int no_dots(const struct dirent *d)
524 if (d->d_name[0] == '.')
530 get_first_file_in_a_directory(const char *dir, char *s, int *rep)
532 struct dirent **namelist;
535 n = scandir(dir, &namelist, no_dots, alphasort);
538 ERR("scandir for %s: %s", dir, strerror(errno));
547 strncpy(s, namelist[0]->d_name, 255);
550 for (i = 0; i < n; i++)
558 #define I2C_DIR "/sys/bus/i2c/devices/"
561 open_i2c_sensor(const char *dev, const char *type, int n, int *div,
569 /* if i2c device is NULL or *, get first */
570 if (dev == NULL || strcmp(dev, "*") == 0) {
572 if (!get_first_file_in_a_directory(I2C_DIR, buf, &rep))
577 /* change vol to in */
578 if (strcmp(type, "vol") == 0)
581 if (strcmp(type, "tempf") == 0) {
582 snprintf(path, 255, I2C_DIR "%s/%s%d_input", dev, "temp",
585 snprintf(path, 255, I2C_DIR "%s/%s%d_input", dev, type, n);
587 strcpy(devtype, path);
590 fd = open(path, O_RDONLY);
592 CRIT_ERR("can't open '%s': %s\nplease fix i2c or remove it from Conky", path, strerror(errno));
595 if (strcmp(type, "in") == 0 || strcmp(type, "temp") == 0
596 || strcmp(type, "tempf") == 0)
600 /* fan does not use *_div as a read divisor */
601 if (strcmp("fan", type) == 0)
604 /* test if *_div file exist, open it and use it as divisor */
605 if (strcmp(type, "tempf") == 0) {
606 snprintf(path, 255, I2C_DIR "%s/%s%d_div", "one", "two",
609 snprintf(path, 255, I2C_DIR "%s/%s%d_div", dev, type, n);
612 divfd = open(path, O_RDONLY);
617 divn = read(divfd, divbuf, 63);
618 /* should read until n == 0 but I doubt that kernel will give these
619 * in multiple pieces. :) */
629 double get_i2c_info(int *fd, int div, char *devtype, char *type)
636 lseek(*fd, 0, SEEK_SET);
642 n = read(*fd, buf, 63);
643 /* should read until n == 0 but I doubt that kernel will give these
644 * in multiple pieces. :) */
651 *fd = open(devtype, O_RDONLY);
653 ERR("can't open '%s': %s", devtype, strerror(errno));
655 /* My dirty hack for computing CPU value
656 * Filedil, from forums.gentoo.org
658 /* if (strstr(devtype, "temp1_input") != NULL)
659 return -15.096+1.4893*(val / 1000.0); */
662 /* divide voltage and temperature by 1000 */
663 /* or if any other divisor is given, use that */
664 if (strcmp(type, "tempf") == 0) {
666 return ((val / div + 40) * 9.0 / 5) - 40;
668 return ((val / 1000.0 + 40) * 9.0 / 5) - 40;
670 return ((val + 40) * 9.0 / 5) - 40;
681 #define ADT746X_FAN "/sys/devices/temperatures/cpu_fan_speed"
683 static char *adt746x_fan_state;
685 char *get_adt746x_fan()
690 if (adt746x_fan_state == NULL) {
691 adt746x_fan_state = (char *) malloc(100);
692 assert(adt746x_fan_state != NULL);
695 fp = open_file(ADT746X_FAN, &rep);
697 strcpy(adt746x_fan_state,
698 "No fan found! Hey, you don't have one?");
699 return adt746x_fan_state;
701 fscanf(fp, "%s", adt746x_fan_state);
704 return adt746x_fan_state;
707 #define ADT746X_CPU "/sys/devices/temperatures/cpu_temperature"
709 static char *adt746x_cpu_state;
711 char *get_adt746x_cpu()
716 if (adt746x_cpu_state == NULL) {
717 adt746x_cpu_state = (char *) malloc(100);
718 assert(adt746x_cpu_state != NULL);
721 fp = open_file(ADT746X_CPU, &rep);
722 fscanf(fp, "%2s", adt746x_cpu_state);
725 return adt746x_cpu_state;
728 /* Thanks to "Walt Nelson" <wnelsonjr@comcast.net> */
730 /***********************************************************************/
732 * This file is part of x86info.
733 * (C) 2001 Dave Jones.
735 * Licensed under the terms of the GNU GPL License version 2.
737 * Estimate CPU MHz routine by Andrea Arcangeli <andrea@suse.de>
738 * Small changes by David Sterba <sterd9am@ss1000.ms.mff.cuni.cz>
741 #if defined(__i386) || defined(__x86_64)
742 __inline__ unsigned long long int rdtsc()
744 unsigned long long int x;
745 __asm__ volatile (".byte 0x0f, 0x31":"=A" (x));
748 static char *buffer = NULL;
751 float get_freq_dynamic()
753 #if defined(__i386) || defined(__x86_64)
757 struct timeval tvstart, tvstop;
758 unsigned long long cycles[2]; /* gotta be 64 bit */
759 unsigned int microseconds; /* total time taken */
761 memset(&tz, 0, sizeof(tz));
763 /* get this function in cached memory */
764 gettimeofday(&tvstart, &tz);
766 gettimeofday(&tvstart, &tz);
768 /* we don't trust that this is any specific length of time */
771 gettimeofday(&tvstop, &tz);
772 microseconds = ((tvstop.tv_sec - tvstart.tv_sec) * 1000000) +
773 (tvstop.tv_usec - tvstart.tv_usec);
775 return (cycles[1] - cycles[0]) / microseconds;
781 #define CPUFREQ_CURRENT "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq"
783 static char *frequency;
789 if (frequency == NULL) {
790 frequency = (char *) malloc(100);
791 assert(frequency != NULL);
793 f = fopen(CPUFREQ_CURRENT, "r");
795 /* if there's a cpufreq /sys node, read the current
796 * frequency there from this node; divice by 1000 to
800 if (fgets(s, 1000,f)) {
801 s[strlen(s)-1] = '\0';
802 freq = strtod(s, NULL);
808 f = fopen("/proc/cpuinfo", "r"); //open the CPU information file
811 while (fgets(s, 1000, f) != NULL){ //read the file
812 #if defined(__i386) || defined(__x86_64)
813 if (strncmp(s, "cpu MHz", 5) == 0) { //and search for the cpu mhz
815 if (strncmp(s, "clock", 5) == 0) { // this is different on ppc for some reason
817 strcpy(frequency, strchr(s, ':') + 2); //copy just the number
818 frequency[strlen(frequency) - 1] = '\0'; // strip \n
823 return strtod(frequency, (char **)NULL);
827 #define ACPI_FAN_DIR "/proc/acpi/fan/"
829 static char *acpi_fan_state;
838 if (acpi_fan_state == NULL) {
839 acpi_fan_state = (char *) malloc(100);
840 assert(acpi_fan_state != NULL);
843 /* yeah, slow... :/ */
844 if (!get_first_file_in_a_directory(ACPI_FAN_DIR, buf, &rep))
847 snprintf(buf2, 256, "%s%s/state", ACPI_FAN_DIR, buf);
849 fp = open_file(buf2, &rep);
851 strcpy(acpi_fan_state, "can't open fan's state file");
852 return acpi_fan_state;
854 fscanf(fp, "%*s %99s", acpi_fan_state);
856 return acpi_fan_state;
859 #define ACPI_AC_ADAPTER_DIR "/proc/acpi/ac_adapter/"
861 static char *acpi_ac_adapter_state;
863 char *get_acpi_ac_adapter()
870 if (acpi_ac_adapter_state == NULL) {
871 acpi_ac_adapter_state = (char *) malloc(100);
872 assert(acpi_ac_adapter_state != NULL);
875 /* yeah, slow... :/ */
876 if (!get_first_file_in_a_directory(ACPI_AC_ADAPTER_DIR, buf, &rep))
877 return "no ac_adapters?";
879 snprintf(buf2, 256, "%s%s/state", ACPI_AC_ADAPTER_DIR, buf);
881 fp = open_file(buf2, &rep);
883 strcpy(acpi_ac_adapter_state,
884 "No ac adapter found.... where is it?");
885 return acpi_ac_adapter_state;
887 fscanf(fp, "%*s %99s", acpi_ac_adapter_state);
890 return acpi_ac_adapter_state;
894 /proc/acpi/thermal_zone/THRM/cooling_mode
896 /proc/acpi/thermal_zone/THRM/polling_frequency
898 /proc/acpi/thermal_zone/THRM/state
900 /proc/acpi/thermal_zone/THRM/temperature
902 /proc/acpi/thermal_zone/THRM/trip_points
904 passive: 73 C: tc1=4 tc2=3 tsp=40 devices=0xcdf6e6c0
907 #define ACPI_THERMAL_DIR "/proc/acpi/thermal_zone/"
908 #define ACPI_THERMAL_FORMAT "/proc/acpi/thermal_zone/%s/temperature"
910 int open_acpi_temperature(const char *name)
916 if (name == NULL || strcmp(name, "*") == 0) {
918 if (!get_first_file_in_a_directory
919 (ACPI_THERMAL_DIR, buf, &rep))
924 snprintf(path, 255, ACPI_THERMAL_FORMAT, name);
926 fd = open(path, O_RDONLY);
928 ERR("can't open '%s': %s", path, strerror(errno));
933 static double last_acpi_temp;
934 static double last_acpi_temp_time;
936 double get_acpi_temperature(int fd)
941 /* don't update acpi temperature too often */
942 if (current_update_time - last_acpi_temp_time < 11.32) {
943 return last_acpi_temp;
945 last_acpi_temp_time = current_update_time;
947 /* seek to beginning */
948 lseek(fd, 0, SEEK_SET);
954 n = read(fd, buf, 255);
956 ERR("can't read fd %d: %s", fd, strerror(errno));
959 sscanf(buf, "temperature: %lf", &last_acpi_temp);
963 return last_acpi_temp;
967 hipo@lepakko hipo $ cat /proc/acpi/battery/BAT1/info
969 design capacity: 4400 mAh
970 last full capacity: 4064 mAh
971 battery technology: rechargeable
972 design voltage: 14800 mV
973 design capacity warning: 300 mAh
974 design capacity low: 200 mAh
975 capacity granularity 1: 32 mAh
976 capacity granularity 2: 32 mAh
984 hipo@lepakko conky $ cat /proc/acpi/battery/BAT1/state
987 charging state: unknown
989 remaining capacity: 4064 mAh
990 present voltage: 16608 mV
994 2213<@jupet kellari ö> jupet@lagi-unstable:~$ cat /proc/apm
995 2213<@jupet kellari ö> 1.16 1.2 0x03 0x01 0xff 0x10 -1% -1 ?
996 2213<@jupet kellari ö> (-1 ollee ei akkua kiinni, koska akku on pöydällä)
997 2214<@jupet kellari ö> jupet@lagi-unstable:~$ cat /proc/apm
998 2214<@jupet kellari ö> 1.16 1.2 0x03 0x01 0x03 0x09 98% -1 ?
1000 2238<@jupet kellari ö> 1.16 1.2 0x03 0x00 0x00 0x01 100% -1 ? ilman verkkovirtaa
1001 2239<@jupet kellari ö> 1.16 1.2 0x03 0x01 0x00 0x01 99% -1 ? verkkovirralla
1003 2240<@jupet kellari ö> 1.16 1.2 0x03 0x01 0x03 0x09 100% -1 ? verkkovirralla ja monitori päällä
1004 2241<@jupet kellari ö> 1.16 1.2 0x03 0x00 0x00 0x01 99% -1 ? monitori päällä mutta ilman verkkovirtaa
1007 #define ACPI_BATTERY_BASE_PATH "/proc/acpi/battery"
1008 #define APM_PATH "/proc/apm"
1010 static FILE *acpi_bat_fp;
1011 static FILE *apm_bat_fp;
1013 static int acpi_last_full;
1015 static char last_battery_str[64];
1017 static double last_battery_time;
1019 void get_battery_stuff(char *buf, unsigned int n, const char *bat)
1021 static int rep, rep2;
1022 char acpi_path[128];
1023 snprintf(acpi_path, 127, ACPI_BATTERY_BASE_PATH "/%s/state", bat);
1025 /* don't update battery too often */
1026 if (current_update_time - last_battery_time < 29.5) {
1027 snprintf(buf, n, "%s", last_battery_str);
1030 last_battery_time = current_update_time;
1032 /* first try ACPI */
1034 if (acpi_bat_fp == NULL && apm_bat_fp == NULL)
1035 acpi_bat_fp = open_file(acpi_path, &rep);
1037 if (acpi_bat_fp != NULL) {
1038 int present_rate = -1;
1039 int remaining_capacity = -1;
1040 char charging_state[64];
1042 /* read last full capacity if it's zero */
1043 if (acpi_last_full == 0) {
1048 ACPI_BATTERY_BASE_PATH "/%s/info", bat);
1049 fp = open_file(path, &rep);
1053 if (fgets(b, 256, fp) == NULL)
1057 (b, "last full capacity: %d",
1058 &acpi_last_full) != 0)
1066 fseek(acpi_bat_fp, 0, SEEK_SET);
1068 strcpy(charging_state, "unknown");
1070 while (!feof(acpi_bat_fp)) {
1072 if (fgets(buf, 256, acpi_bat_fp) == NULL)
1075 /* let's just hope units are ok */
1077 sscanf(buf, "charging state: %63s",
1079 else if (buf[0] == 'p')
1080 sscanf(buf, "present rate: %d",
1082 else if (buf[0] == 'r')
1083 sscanf(buf, "remaining capacity: %d",
1084 &remaining_capacity);
1088 if (strcmp(charging_state, "charging") == 0) {
1089 if (acpi_last_full != 0 && present_rate > 0) {
1090 strcpy(last_battery_str, "charging ");
1091 format_seconds(last_battery_str + 9,
1094 remaining_capacity) * 60 *
1096 } else if (acpi_last_full != 0
1097 && present_rate <= 0) {
1098 sprintf(last_battery_str, "charging %d%%",
1099 remaining_capacity * 100 /
1102 strcpy(last_battery_str, "charging");
1106 else if (strcmp(charging_state, "discharging") == 0) {
1107 if (present_rate > 0)
1108 format_seconds(last_battery_str, 63,
1109 (remaining_capacity * 60 *
1110 60) / present_rate);
1112 sprintf(last_battery_str,
1114 remaining_capacity * 100 /
1118 /* thanks to Lukas Zapletal <lzap@seznam.cz> */
1119 else if (strcmp(charging_state, "charged") == 0) {
1120 if (acpi_last_full != 0
1121 && remaining_capacity != acpi_last_full)
1122 sprintf(last_battery_str, "charged %d%%",
1123 remaining_capacity * 100 /
1126 strcpy(last_battery_str, "charged");
1128 /* unknown, probably full / AC */
1130 if (acpi_last_full != 0
1131 && remaining_capacity != acpi_last_full)
1132 sprintf(last_battery_str, "unknown %d%%",
1133 remaining_capacity * 100 /
1136 strcpy(last_battery_str, "AC");
1140 if (apm_bat_fp == NULL)
1141 apm_bat_fp = open_file(APM_PATH, &rep2);
1143 if (apm_bat_fp != NULL) {
1144 int ac, status, flag, life;
1147 "%*s %*s %*x %x %x %x %d%%",
1148 &ac, &status, &flag, &life);
1151 /* could check now that there is ac */
1152 snprintf(last_battery_str, 64, "AC");
1153 } else if (ac && life != 100) { /* could check that status==3 here? */
1154 snprintf(last_battery_str, 64,
1155 "charging %d%%", life);
1157 snprintf(last_battery_str, 64, "%d%%",
1161 /* it seemed to buffer it so file must be closed (or could use syscalls
1162 * directly but I don't feel like coding it now) */
1168 snprintf(buf, n, "%s", last_battery_str);
1173 show_nice_processes = 1;
1174 process_find_top(info.cpu, info.memu);
1179 * The following ifdefs were adapted from gkrellm
1181 #include <linux/major.h>
1183 #if ! defined (MD_MAJOR)
1187 #if !defined(LVM_BLK_MAJOR)
1188 #define LVM_BLK_MAJOR 58
1191 #if !defined(NBD_MAJOR)
1192 #define NBD_MAJOR 43
1195 void update_diskio()
1197 static unsigned int last = UINT_MAX;
1202 unsigned int current = 0;
1203 unsigned int reads, writes = 0;
1207 fp = fopen("/proc/diskstats", "r");
1209 fseek(fp, 0, SEEK_SET);
1212 /* read reads and writes from all disks (minor = 0), including
1213 * cd-roms and floppies, and summ them up
1217 fgets(buf, 512, fp);
1218 col_count = sscanf(buf, "%u %u %*s %*u %*u %u %*u %*u %*u %u",
1219 &major, &minor, &reads, &writes);
1220 /* ignore subdevices (they have only 3 matching entries in their line)
1221 * and virtual devices (LVM, network block devices, RAM disks, Loopback)
1223 * XXX ignore devices which are part of a SW RAID (MD_MAJOR)
1225 if (col_count > 3 &&
1226 major != LVM_BLK_MAJOR && major != NBD_MAJOR &&
1227 major != RAMDISK_MAJOR && major != LOOP_MAJOR) {
1228 current += reads + writes;
1232 /* since the values in /proc/diststats are absolute, we have
1233 * to substract our last reading. The numbers stand for
1234 * "sectors read", and we therefore have to divide by two to
1236 int tot = ((double)(current-last)/2);
1237 if (last > current) {
1238 /* we hit this either if it's the very first time we
1239 * run this, or when /proc/diskstats overflows; while
1240 * 0 is not correct, it's at least not way off */