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 %lu", &info.memmax);
113 } else if (strncmp(buf, "MemFree:", 8) == 0) {
114 sscanf(buf, "%*s %lu", &info.mem);
115 } else if (strncmp(buf, "SwapTotal:", 10) == 0) {
116 sscanf(buf, "%*s %lu", &info.swapmax);
117 } else if (strncmp(buf, "SwapFree:", 9) == 0) {
118 sscanf(buf, "%*s %lu", &info.swap);
119 } else if (strncmp(buf, "Buffers:", 8) == 0) {
120 sscanf(buf, "%*s %lu", &info.buffers);
121 } else if (strncmp(buf, "Cached:", 7) == 0) {
122 sscanf(buf, "%*s %lu", &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(MIN(MAX(l,1),92)) / log(92) * 100);
314 /*** end wireless patch ***/
319 void update_total_processes()
324 #define CPU_SAMPLE_COUNT 15
326 unsigned long cpu_user;
327 unsigned long cpu_system;
328 unsigned long cpu_nice;
330 unsigned long clock_ticks;
331 double cpu_val[CPU_SAMPLE_COUNT];
333 static short cpu_setup = 0;
337 static FILE *stat_fp;
343 stat_fp = open_file("/proc/stat", &rep);
345 fseek(stat_fp, 0, SEEK_SET);
351 while (!feof(stat_fp)) {
352 if (fgets(buf, 255, stat_fp) == NULL)
355 if (strncmp(buf, "cpu", 3) == 0 && isdigit(buf[3])) {
359 info.cpu_usage = malloc((info.cpu_count + 1) * sizeof(float));
363 inline static void update_stat()
365 static struct cpu_info *cpu = NULL;
375 cpu = malloc((info.cpu_count + 1) * sizeof(struct cpu_info));
376 for (index = 0; index < info.cpu_count + 1; ++index) {
377 cpu[index].clock_ticks = 0;
378 cpu[index].last_cpu_sum = 0;
379 for (i = 0; i < CPU_SAMPLE_COUNT; ++i) {
380 cpu[index].cpu_val[i] = 0;
384 if (stat_fp == NULL) {
385 stat_fp = open_file("/proc/stat", &rep);
387 fseek(stat_fp, 0, SEEK_SET);
389 if (stat_fp == NULL) {
393 while (!feof(stat_fp)) {
394 if (fgets(buf, 255, stat_fp) == NULL)
397 if (strncmp(buf, "procs_running ", 14) == 0) {
398 sscanf(buf, "%*s %d", &info.run_procs);
399 info.mask |= (1 << INFO_RUN_PROCS);
400 } else if (strncmp(buf, "cpu ", 4) == 0) {
401 sscanf(buf, "%*s %lu %lu %lu", &(cpu[index].cpu_user), &(cpu[index].cpu_nice), &(cpu[index].cpu_system));
403 info.mask |= (1 << INFO_CPU);
404 } else if (strncmp(buf, "cpu", 3) == 0 && isdigit(buf[3]) && index <= info.cpu_count) {
405 sscanf(buf, "%*s %lu %lu %lu", &(cpu[index].cpu_user), &(cpu[index].cpu_nice), &(cpu[index].cpu_system));
407 info.mask |= (1 << INFO_CPU);
410 for (index = 0; index < info.cpu_count + 1; index++) {
412 delta = current_update_time - last_update_time;
413 if (delta <= 0.001) {
417 if (cpu[index].clock_ticks == 0) {
418 cpu[index].clock_ticks = sysconf(_SC_CLK_TCK);
421 cpu[index].cpu_val[0] =
422 (cpu[index].cpu_user + cpu[index].cpu_nice + cpu[index].cpu_system -
423 cpu[index].last_cpu_sum) / delta / (double) cpu[index].clock_ticks;
424 for (i = 0; i < info.cpu_avg_samples; i++) {
425 curtmp += cpu[index].cpu_val[i];
428 info.cpu_usage[index] = curtmp / info.cpu_avg_samples / info.cpu_count;
430 info.cpu_usage[index] = curtmp / info.cpu_avg_samples;
432 cpu[index].last_cpu_sum = cpu[index].cpu_user + cpu[index].cpu_nice + cpu[index].cpu_system;
433 for (i = info.cpu_avg_samples; i > 1; i--)
434 cpu[index].cpu_val[i - 1] = cpu[index].cpu_val[i - 2];
439 // this is for getting proc shit
451 void update_running_processes()
456 void update_cpu_usage()
461 void update_load_average()
463 #ifdef HAVE_GETLOADAVG
466 info.loadavg[0] = (float) v[0];
467 info.loadavg[1] = (float) v[1];
468 info.loadavg[2] = (float) v[2];
473 fp = open_file("/proc/loadavg", &rep);
475 v[0] = v[1] = v[2] = 0.0;
479 fscanf(fp, "%f %f %f", &info.loadavg[0], &info.loadavg[1],
486 #define PROC_I8K "/proc/i8k"
487 #define I8K_DELIM " "
488 static char *i8k_procbuf = NULL;
493 i8k_procbuf = (char*)malloc(128*sizeof(char));
495 if ((fp = fopen(PROC_I8K,"r")) == NULL) {
496 CRIT_ERR("/proc/i8k doesn't exist! use insmod to make sure the kernel driver is loaded...");
499 memset(&i8k_procbuf[0],0,128);
500 if (fread(&i8k_procbuf[0],sizeof(char),128,fp) == 0) {
501 ERR("something wrong with /proc/i8k...");
506 i8k.version = strtok(&i8k_procbuf[0],I8K_DELIM);
507 i8k.bios = strtok(NULL,I8K_DELIM);
508 i8k.serial = strtok(NULL,I8K_DELIM);
509 i8k.cpu_temp = strtok(NULL,I8K_DELIM);
510 i8k.left_fan_status = strtok(NULL,I8K_DELIM);
511 i8k.right_fan_status = strtok(NULL,I8K_DELIM);
512 i8k.left_fan_rpm = strtok(NULL,I8K_DELIM);
513 i8k.right_fan_rpm = strtok(NULL,I8K_DELIM);
514 i8k.ac_status = strtok(NULL,I8K_DELIM);
515 i8k.buttons_status = strtok(NULL,I8K_DELIM);
519 /***********************************************************/
520 /***********************************************************/
521 /***********************************************************/
523 static int no_dots(const struct dirent *d)
525 if (d->d_name[0] == '.')
531 get_first_file_in_a_directory(const char *dir, char *s, int *rep)
533 struct dirent **namelist;
536 n = scandir(dir, &namelist, no_dots, alphasort);
539 ERR("scandir for %s: %s", dir, strerror(errno));
548 strncpy(s, namelist[0]->d_name, 255);
551 for (i = 0; i < n; i++)
559 #define I2C_DIR "/sys/bus/i2c/devices/"
562 open_i2c_sensor(const char *dev, const char *type, int n, int *div,
570 /* if i2c device is NULL or *, get first */
571 if (dev == NULL || strcmp(dev, "*") == 0) {
573 if (!get_first_file_in_a_directory(I2C_DIR, buf, &rep))
578 /* change vol to in */
579 if (strcmp(type, "vol") == 0)
582 if (strcmp(type, "tempf") == 0) {
583 snprintf(path, 255, I2C_DIR "%s/%s%d_input", dev, "temp", n);
585 snprintf(path, 255, I2C_DIR "%s/%s%d_input", dev, type, n);
587 strncpy(devtype, path, 255);
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 void get_adt746x_fan( char * p_client_buffer, size_t client_buffer_size )
686 char adt746x_fan_state[64];
689 if ( !p_client_buffer || client_buffer_size <= 0 )
692 fp = open_file(ADT746X_FAN, &rep);
695 sprintf(adt746x_fan_state, "adt746x not found");
699 fscanf(fp, "%s", adt746x_fan_state);
703 snprintf( p_client_buffer, client_buffer_size, "%s", adt746x_fan_state );
707 #define ADT746X_CPU "/sys/devices/temperatures/cpu_temperature"
709 void get_adt746x_cpu( char * p_client_buffer, size_t client_buffer_size )
712 char adt746x_cpu_state[64];
715 if ( !p_client_buffer || client_buffer_size <= 0 )
718 fp = open_file(ADT746X_CPU, &rep);
721 sprintf(adt746x_cpu_state, "adt746x not found");
725 fscanf(fp, "%2s", adt746x_cpu_state);
729 snprintf( p_client_buffer, client_buffer_size, "%s", adt746x_cpu_state );
733 /* Thanks to "Walt Nelson" <wnelsonjr@comcast.net> */
735 /***********************************************************************/
737 * This file is part of x86info.
738 * (C) 2001 Dave Jones.
740 * Licensed under the terms of the GNU GPL License version 2.
742 * Estimate CPU MHz routine by Andrea Arcangeli <andrea@suse.de>
743 * Small changes by David Sterba <sterd9am@ss1000.ms.mff.cuni.cz>
746 #if defined(__i386) || defined(__x86_64)
747 __inline__ unsigned long long int rdtsc()
749 unsigned long long int x;
750 __asm__ volatile (".byte 0x0f, 0x31":"=A" (x));
755 /* return system frequency in MHz (use divisor=1) or GHz (use divisor=1000) */
756 void get_freq_dynamic( char * p_client_buffer, size_t client_buffer_size, char * p_format, int divisor )
758 #if defined(__i386) || defined(__x86_64)
760 struct timeval tvstart, tvstop;
761 unsigned long long cycles[2]; /* gotta be 64 bit */
762 unsigned int microseconds; /* total time taken */
764 if ( !p_client_buffer || client_buffer_size <= 0 || !p_format || divisor <= 0 )
767 memset(&tz, 0, sizeof(tz));
769 /* get this function in cached memory */
770 gettimeofday(&tvstart, &tz);
772 gettimeofday(&tvstart, &tz);
774 /* we don't trust that this is any specific length of time */
777 gettimeofday(&tvstop, &tz);
778 microseconds = ((tvstop.tv_sec - tvstart.tv_sec) * 1000000) +
779 (tvstop.tv_usec - tvstart.tv_usec);
781 snprintf( p_client_buffer, client_buffer_size, p_format, (float)((cycles[1] - cycles[0]) / microseconds) / divisor );
784 get_freq( p_client_buffer, client_buffer_size, p_format, divisor );
789 #define CPUFREQ_CURRENT "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq"
791 /* return system frequency in MHz (use divisor=1) or GHz (use divisor=1000) */
792 void get_freq( char * p_client_buffer, size_t client_buffer_size, char * p_format, int divisor )
799 if ( !p_client_buffer || client_buffer_size <= 0 || !p_format || divisor <= 0 )
802 f = fopen(CPUFREQ_CURRENT, "r");
804 /* if there's a cpufreq /sys node, read the current frequency from this node;
805 * divide by 1000 to get Mhz. */
806 if (fgets(s, sizeof(s), f)) {
807 s[strlen(s)-1] = '\0';
808 freq = strtod(s, NULL);
811 snprintf( p_client_buffer, client_buffer_size, p_format, (freq/1000)/divisor );
815 f = fopen("/proc/cpuinfo", "r"); //open the CPU information file
819 while (fgets(s, sizeof(s), f) != NULL){ //read the file
820 #if defined(__i386) || defined(__x86_64)
821 if (strncmp(s, "cpu MHz", 7) == 0) { //and search for the cpu mhz
823 if (strncmp(s, "clock", 5) == 0) { // this is different on ppc for some reason
825 strcpy(frequency, strchr(s, ':') + 2); //copy just the number
826 frequency[strlen(frequency) - 1] = '\0'; // strip \n
827 freq = strtod(frequency, NULL);
833 snprintf( p_client_buffer, client_buffer_size, p_format, (float)freq/divisor );
838 #define ACPI_FAN_DIR "/proc/acpi/fan/"
840 void get_acpi_fan( char * p_client_buffer, size_t client_buffer_size )
847 if ( !p_client_buffer || client_buffer_size <= 0 )
850 /* yeah, slow... :/ */
851 if (!get_first_file_in_a_directory(ACPI_FAN_DIR, buf, &rep))
853 snprintf( p_client_buffer, client_buffer_size, "no fans?" );
857 snprintf(buf2, sizeof(buf2), "%s%s/state", ACPI_FAN_DIR, buf );
859 fp = open_file(buf2, &rep);
861 snprintf( p_client_buffer, client_buffer_size, "can't open fan's state file" );
864 memset(buf,0,sizeof(buf));
865 fscanf(fp, "%*s %99s", buf);
868 snprintf( p_client_buffer, client_buffer_size, "%s", buf );
873 #define ACPI_AC_ADAPTER_DIR "/proc/acpi/ac_adapter/"
875 void get_acpi_ac_adapter( char * p_client_buffer, size_t client_buffer_size )
882 if ( !p_client_buffer || client_buffer_size <= 0 )
885 /* yeah, slow... :/ */
886 if (!get_first_file_in_a_directory(ACPI_AC_ADAPTER_DIR, buf, &rep))
888 snprintf( p_client_buffer, client_buffer_size, "no ac_adapters?" );
892 snprintf(buf2, sizeof(buf2), "%s%s/state", ACPI_AC_ADAPTER_DIR, buf );
895 fp = open_file(buf2, &rep);
897 snprintf( p_client_buffer, client_buffer_size, "No ac adapter found.... where is it?" );
900 memset(buf,0,sizeof(buf));
901 fscanf(fp, "%*s %99s", buf );
904 snprintf( p_client_buffer, client_buffer_size, "%s", buf );
910 /proc/acpi/thermal_zone/THRM/cooling_mode
912 /proc/acpi/thermal_zone/THRM/polling_frequency
914 /proc/acpi/thermal_zone/THRM/state
916 /proc/acpi/thermal_zone/THRM/temperature
918 /proc/acpi/thermal_zone/THRM/trip_points
920 passive: 73 C: tc1=4 tc2=3 tsp=40 devices=0xcdf6e6c0
923 #define ACPI_THERMAL_DIR "/proc/acpi/thermal_zone/"
924 #define ACPI_THERMAL_FORMAT "/proc/acpi/thermal_zone/%s/temperature"
926 int open_acpi_temperature(const char *name)
932 if (name == NULL || strcmp(name, "*") == 0) {
934 if (!get_first_file_in_a_directory
935 (ACPI_THERMAL_DIR, buf, &rep))
940 snprintf(path, 255, ACPI_THERMAL_FORMAT, name);
942 fd = open(path, O_RDONLY);
944 ERR("can't open '%s': %s", path, strerror(errno));
949 static double last_acpi_temp;
950 static double last_acpi_temp_time;
952 double get_acpi_temperature(int fd)
957 /* don't update acpi temperature too often */
958 if (current_update_time - last_acpi_temp_time < 11.32) {
959 return last_acpi_temp;
961 last_acpi_temp_time = current_update_time;
963 /* seek to beginning */
964 lseek(fd, 0, SEEK_SET);
970 n = read(fd, buf, 255);
972 ERR("can't read fd %d: %s", fd, strerror(errno));
975 sscanf(buf, "temperature: %lf", &last_acpi_temp);
979 return last_acpi_temp;
983 hipo@lepakko hipo $ cat /proc/acpi/battery/BAT1/info
985 design capacity: 4400 mAh
986 last full capacity: 4064 mAh
987 battery technology: rechargeable
988 design voltage: 14800 mV
989 design capacity warning: 300 mAh
990 design capacity low: 200 mAh
991 capacity granularity 1: 32 mAh
992 capacity granularity 2: 32 mAh
1000 hipo@lepakko conky $ cat /proc/acpi/battery/BAT1/state
1003 charging state: unknown
1005 remaining capacity: 4064 mAh
1006 present voltage: 16608 mV
1010 2213<@jupet kellari ö> jupet@lagi-unstable:~$ cat /proc/apm
1011 2213<@jupet kellari ö> 1.16 1.2 0x03 0x01 0xff 0x10 -1% -1 ?
1012 2213<@jupet kellari ö> (-1 ollee ei akkua kiinni, koska akku on pöydällä)
1013 2214<@jupet kellari ö> jupet@lagi-unstable:~$ cat /proc/apm
1014 2214<@jupet kellari ö> 1.16 1.2 0x03 0x01 0x03 0x09 98% -1 ?
1016 2238<@jupet kellari ö> 1.16 1.2 0x03 0x00 0x00 0x01 100% -1 ? ilman verkkovirtaa
1017 2239<@jupet kellari ö> 1.16 1.2 0x03 0x01 0x00 0x01 99% -1 ? verkkovirralla
1019 2240<@jupet kellari ö> 1.16 1.2 0x03 0x01 0x03 0x09 100% -1 ? verkkovirralla ja monitori päällä
1020 2241<@jupet kellari ö> 1.16 1.2 0x03 0x00 0x00 0x01 99% -1 ? monitori päällä mutta ilman verkkovirtaa
1023 #define ACPI_BATTERY_BASE_PATH "/proc/acpi/battery"
1024 #define APM_PATH "/proc/apm"
1026 static FILE *acpi_bat_fp;
1027 static FILE *apm_bat_fp;
1029 static int acpi_last_full;
1031 static char last_battery_str[64];
1033 static double last_battery_time;
1035 void get_battery_stuff(char *buf, unsigned int n, const char *bat)
1037 static int rep, rep2;
1038 char acpi_path[128];
1039 snprintf(acpi_path, 127, ACPI_BATTERY_BASE_PATH "/%s/state", bat);
1041 /* don't update battery too often */
1042 if (current_update_time - last_battery_time < 29.5) {
1043 snprintf(buf, n, "%s", last_battery_str);
1046 last_battery_time = current_update_time;
1048 /* first try ACPI */
1050 if (acpi_bat_fp == NULL && apm_bat_fp == NULL)
1051 acpi_bat_fp = open_file(acpi_path, &rep);
1053 if (acpi_bat_fp != NULL) {
1054 int present_rate = -1;
1055 int remaining_capacity = -1;
1056 char charging_state[64];
1058 /* read last full capacity if it's zero */
1059 if (acpi_last_full == 0) {
1064 ACPI_BATTERY_BASE_PATH "/%s/info", bat);
1065 fp = open_file(path, &rep);
1069 if (fgets(b, 256, fp) == NULL)
1073 (b, "last full capacity: %d",
1074 &acpi_last_full) != 0)
1082 fseek(acpi_bat_fp, 0, SEEK_SET);
1084 strcpy(charging_state, "unknown");
1086 while (!feof(acpi_bat_fp)) {
1088 if (fgets(buf, 256, acpi_bat_fp) == NULL)
1091 /* let's just hope units are ok */
1093 sscanf(buf, "charging state: %63s",
1095 else if (buf[0] == 'p')
1096 sscanf(buf, "present rate: %d",
1098 else if (buf[0] == 'r')
1099 sscanf(buf, "remaining capacity: %d",
1100 &remaining_capacity);
1104 if (strcmp(charging_state, "charging") == 0) {
1105 if (acpi_last_full != 0 && present_rate > 0) {
1106 strcpy(last_battery_str, "charging ");
1107 format_seconds(last_battery_str + 9,
1110 remaining_capacity) * 60 *
1112 } else if (acpi_last_full != 0
1113 && present_rate <= 0) {
1114 sprintf(last_battery_str, "charging %d%%",
1115 remaining_capacity * 100 /
1118 strcpy(last_battery_str, "charging");
1122 else if (strcmp(charging_state, "discharging") == 0) {
1123 if (present_rate > 0)
1124 format_seconds(last_battery_str, 63,
1125 (remaining_capacity * 60 *
1126 60) / present_rate);
1128 sprintf(last_battery_str,
1130 remaining_capacity * 100 /
1134 /* thanks to Lukas Zapletal <lzap@seznam.cz> */
1135 else if (strcmp(charging_state, "charged") == 0) {
1136 if (acpi_last_full != 0
1137 && remaining_capacity != acpi_last_full)
1138 sprintf(last_battery_str, "charged %d%%",
1139 remaining_capacity * 100 /
1142 strcpy(last_battery_str, "charged");
1144 /* unknown, probably full / AC */
1146 if (acpi_last_full != 0
1147 && remaining_capacity != acpi_last_full)
1148 sprintf(last_battery_str, "unknown %d%%",
1149 remaining_capacity * 100 /
1152 strcpy(last_battery_str, "AC");
1156 if (apm_bat_fp == NULL)
1157 apm_bat_fp = open_file(APM_PATH, &rep2);
1159 if (apm_bat_fp != NULL) {
1160 int ac, status, flag, life;
1163 "%*s %*s %*x %x %x %x %d%%",
1164 &ac, &status, &flag, &life);
1167 /* could check now that there is ac */
1168 snprintf(last_battery_str, 64, "AC");
1169 } else if (ac && life != 100) { /* could check that status==3 here? */
1170 snprintf(last_battery_str, 64,
1171 "charging %d%%", life);
1173 snprintf(last_battery_str, 64, "%d%%",
1177 /* it seemed to buffer it so file must be closed (or could use syscalls
1178 * directly but I don't feel like coding it now) */
1184 snprintf(buf, n, "%s", last_battery_str);
1189 show_nice_processes = 1;
1190 process_find_top(info.cpu, info.memu);
1191 info.first_process = get_first_process();
1196 * The following ifdefs were adapted from gkrellm
1198 #include <linux/major.h>
1200 #if ! defined (MD_MAJOR)
1204 #if !defined(LVM_BLK_MAJOR)
1205 #define LVM_BLK_MAJOR 58
1208 #if !defined(NBD_MAJOR)
1209 #define NBD_MAJOR 43
1212 void update_diskio()
1214 static unsigned int last = UINT_MAX;
1219 unsigned int current = 0;
1220 unsigned int reads, writes = 0;
1224 fp = fopen("/proc/diskstats", "r");
1226 fseek(fp, 0, SEEK_SET);
1229 /* read reads and writes from all disks (minor = 0), including
1230 * cd-roms and floppies, and summ them up
1234 fgets(buf, 512, fp);
1235 col_count = sscanf(buf, "%u %u %*s %*u %*u %u %*u %*u %*u %u",
1236 &major, &minor, &reads, &writes);
1237 /* ignore subdevices (they have only 3 matching entries in their line)
1238 * and virtual devices (LVM, network block devices, RAM disks, Loopback)
1240 * XXX ignore devices which are part of a SW RAID (MD_MAJOR)
1242 if (col_count > 3 &&
1243 major != LVM_BLK_MAJOR && major != NBD_MAJOR &&
1244 major != RAMDISK_MAJOR && major != LOOP_MAJOR) {
1245 current += reads + writes;
1249 /* since the values in /proc/diststats are absolute, we have
1250 * to substract our last reading. The numbers stand for
1251 * "sectors read", and we therefore have to divide by two to
1253 int tot = ((double)(current-last)/2);
1254 if (last > current) {
1255 /* we hit this either if it's the very first time we
1256 * run this, or when /proc/diskstats overflows; while
1257 * 0 is not correct, it's at least not way off */