2 * Contains linux specific code
16 #include <sys/types.h>
17 #include <sys/sysinfo.h>
19 #ifndef HAVE_CLOCK_GETTIME
24 // #include <assert.h>
28 #include <sys/ioctl.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <linux/sockios.h>
35 #define SHORTSTAT_TEMPL "%*s %llu %llu %llu"
36 #define LONGSTAT_TEMPL "%*s %llu %llu %llu "
38 static int show_nice_processes;
40 /* this flags tells the linux routines to use the /proc system
41 * where possible, even if other api's are available, e.g. sysinfo()
42 * or getloadavg(). the reason for this is to allow for /proc-based
43 * distributed monitoring. using a flag in this manner creates less
46 static int prefer_proc = 0;
57 struct sysinfo s_info;
59 info.uptime = (double) s_info.uptime;
67 if (!(fp = open_file("/proc/uptime", &rep)))
72 fscanf(fp, "%lf", &info.uptime);
75 info.mask |= (1 << INFO_UPTIME);
78 /* these things are also in sysinfo except Buffers:, that's why I'm reading
88 info.mem = info.memmax = info.swap = info.swapmax = info.bufmem =
89 info.buffers = info.cached = 0;
91 if (!(meminfo_fp = open_file("/proc/meminfo", &rep)))
94 while (!feof(meminfo_fp)) {
95 if (fgets(buf, 255, meminfo_fp) == NULL)
98 if (strncmp(buf, "MemTotal:", 9) == 0) {
99 sscanf(buf, "%*s %Lu", &info.memmax);
100 } else if (strncmp(buf, "MemFree:", 8) == 0) {
101 sscanf(buf, "%*s %Lu", &info.mem);
102 } else if (strncmp(buf, "SwapTotal:", 10) == 0) {
103 sscanf(buf, "%*s %Lu", &info.swapmax);
104 } else if (strncmp(buf, "SwapFree:", 9) == 0) {
105 sscanf(buf, "%*s %Lu", &info.swap);
106 } else if (strncmp(buf, "Buffers:", 8) == 0) {
107 sscanf(buf, "%*s %Lu", &info.buffers);
108 } else if (strncmp(buf, "Cached:", 7) == 0) {
109 sscanf(buf, "%*s %Lu", &info.cached);
113 info.mem = info.memmax - info.mem;
114 info.swap = info.swapmax - info.swap;
116 info.bufmem = info.cached + info.buffers;
118 info.mask |= (1 << INFO_MEM) | (1 << INFO_BUFFERS);
123 static FILE *net_wireless_fp;
125 inline void update_net_stats()
129 // FIXME: arbitrary size chosen to keep code simple.
131 unsigned int curtmp1, curtmp2;
138 delta = current_update_time - last_update_time;
142 /* open file and ignore first two lines */
143 if (!(net_dev_fp = open_file("/proc/net/dev", &rep)))
149 fgets(buf, 255, net_dev_fp); /* garbage */
150 fgets(buf, 255, net_dev_fp); /* garbage (field names) */
152 /* read each interface */
153 for (i2 = 0; i2 < 16; i2++) {
156 long long r, t, last_recv, last_trans;
158 if (fgets(buf, 255, net_dev_fp) == NULL) {
162 while (isspace((int) *p))
167 while (*p && *p != ':')
174 ns = get_net_stat(s);
176 memset(&(ns->addr.sa_data), 0, 14);
177 last_recv = ns->recv;
178 last_trans = ns->trans;
181 /* bytes packets errs drop fifo frame compressed multicast|bytes ... */
182 "%Ld %*d %*d %*d %*d %*d %*d %*d %Ld",
185 /* if recv or trans is less than last time, an overflow happened */
187 if (r < ns->last_read_recv)
189 ((long long) 4294967295U -
190 ns->last_read_recv) + r;
192 ns->recv += (r - ns->last_read_recv);
193 ns->last_read_recv = r;
195 if (t < ns->last_read_trans)
197 ((long long) 4294967295U -
198 ns->last_read_trans) + t;
200 ns->trans += (t - ns->last_read_trans);
201 ns->last_read_trans = t;
203 /*** ip addr patch ***/
204 i = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
206 conf.ifc_buf = malloc(sizeof(struct ifreq) * 16);
208 conf.ifc_len = sizeof(struct ifreq) * 16;
210 ioctl((long) i, SIOCGIFCONF, &conf);
212 for (k = 0; k < conf.ifc_len / sizeof(struct ifreq); k++) {
214 ns = get_net_stat(((struct ifreq *) conf.
215 ifc_buf)[k].ifr_ifrn.ifrn_name);
217 ((struct ifreq *) conf.ifc_buf)[k].ifr_ifru.
226 /*** end ip addr patch ***/
229 /* calculate speeds */
230 ns->net_rec[0] = (ns->recv - last_recv) / delta;
231 ns->net_trans[0] = (ns->trans - last_trans) / delta;
235 for (i = 0; (unsigned) i < info.net_avg_samples; i++) {
236 curtmp1 += ns->net_rec[i];
237 curtmp2 += ns->net_trans[i];
239 ns->recv_speed = curtmp1 / (double) info.net_avg_samples;
240 ns->trans_speed = curtmp2 / (double) info.net_avg_samples;
241 if (info.net_avg_samples > 1) {
242 for (i = info.net_avg_samples; i > 1; i--) {
243 ns->net_rec[i - 1] = ns->net_rec[i - 2];
244 ns->net_trans[i - 1] =
245 ns->net_trans[i - 2];
253 info.mask |= (1 << INFO_NET);
256 inline void update_wifi_stats()
258 /** wireless stats patch by Bobby Beckmann **/
262 /*open file and ignore first two lines sorry, this code sucks ass right now, i'll clean it up later */
263 if (net_wireless_fp == NULL)
264 net_wireless_fp = open_file("/proc/net/wireless", &rep);
266 fseek(net_wireless_fp, 0, SEEK_SET);
267 if (net_wireless_fp == NULL)
270 fgets(buf, 255, net_wireless_fp); /* garbage */
271 fgets(buf, 255, net_wireless_fp); /* garbage (field names) */
273 /* read each interface */
274 for (i = 0; i < 16; i++) {
279 if (fgets(buf, 255, net_wireless_fp) == NULL)
282 while (isspace((int) *p))
287 while (*p && *p != ':')
294 ns = get_net_stat(s);
296 sscanf(p, "%*d %d. %d. %d", &l, &m, &n);
298 ns->linkstatus = (int) (log(MIN(MAX(l,1),92)) / log(92) * 100);
302 /*** end wireless patch ***/
307 void update_total_processes()
312 struct sysinfo s_info;
314 info.procs = s_info.procs;
322 if (!(fp = open_file("/proc/loadavg", &rep)))
327 fscanf(fp, "%*f %*f %*f %*d/%hd", &info.procs );
330 info.mask |= (1 << INFO_PROCS);
333 #define CPU_SAMPLE_COUNT 15
335 unsigned long long cpu_user;
336 unsigned long long cpu_system;
337 unsigned long long cpu_nice;
338 unsigned long long cpu_idle;
339 unsigned long long cpu_iowait;
340 unsigned long long cpu_irq;
341 unsigned long long cpu_softirq;
342 unsigned long long cpu_steal;
343 unsigned long long cpu_total;
344 unsigned long long cpu_active_total;
345 unsigned long long cpu_last_total;
346 unsigned long long cpu_last_active_total;
347 double cpu_val[CPU_SAMPLE_COUNT];
349 static short cpu_setup = 0;
352 determine if this kernel gives us "extended" statistics information in /proc/stat.
353 Kernels around 2.5 and earlier only reported user, system, nice and idle values in proc stat.
354 Kernels around 2.6 and greater report these PLUS iowait, irq, softirq, and steal
356 void determine_longstat(char * buf) {
357 unsigned long long iowait=0;
358 KFLAG_SETOFF(KFLAG_IS_LONGSTAT);
359 /* scanf will either return -1 or 1 because there is only 1 assignment */
360 if (sscanf(buf, "%*s %*d %*d %*d %*d %llu",&iowait)>0) KFLAG_SETON(KFLAG_IS_LONGSTAT);
368 if (info.cpu_usage) {
373 if (!(stat_fp = open_file("/proc/stat", &rep)))
378 while (!feof(stat_fp)) {
379 if (fgets(buf, 255, stat_fp) == NULL)
382 if (strncmp(buf, "cpu", 3) == 0 && isdigit(buf[3])) {
383 if (info.cpu_count == 0) {
384 determine_longstat(buf);
389 info.cpu_usage = malloc((info.cpu_count + 1) * sizeof(float));
394 #define TMPL_LONGSTAT "%*s %llu %llu %llu %llu %llu %llu %llu %llu"
395 #define TMPL_SHORTSTAT "%*s %llu %llu %llu %llu"
397 inline static void update_stat()
401 static struct cpu_info *cpu = NULL;
406 char * stat_template=NULL;
407 unsigned int malloc_cpu_size=0;
410 /* add check for !info.cpu_usage since that mem is freed on a SIGUSR1 */
411 if (!cpu_setup || !info.cpu_usage) {
416 if (!stat_template) {
417 stat_template = KFLAG_ISSET(KFLAG_IS_LONGSTAT) ? TMPL_LONGSTAT : TMPL_SHORTSTAT ;
421 malloc_cpu_size = (info.cpu_count + 1) * sizeof(struct cpu_info);
422 cpu = malloc(malloc_cpu_size);
423 memset(cpu, 0, malloc_cpu_size);
426 if (!(stat_fp = open_file("/proc/stat", &rep)))
431 memset(info.cpu_usage, 0, info.cpu_count * sizeof (float));
437 while (!feof(stat_fp)) {
438 if (fgets(buf, 255, stat_fp) == NULL)
441 if (strncmp(buf, "procs_running ", 14) == 0) {
442 sscanf(buf, "%*s %hu", &info.run_procs);
443 info.mask |= (1 << INFO_RUN_PROCS);
444 } else if (strncmp(buf, "cpu", 3) == 0) {
445 index = isdigit(buf[3]) ? ((int)buf[3]) - 0x2F : 0;
446 sscanf(buf, stat_template
447 , &(cpu[index].cpu_user)
448 , &(cpu[index].cpu_nice)
449 , &(cpu[index].cpu_system)
450 , &(cpu[index].cpu_idle)
451 , &(cpu[index].cpu_iowait)
452 , &(cpu[index].cpu_irq)
453 , &(cpu[index].cpu_softirq)
454 , &(cpu[index].cpu_steal)
457 cpu[index].cpu_total = cpu[index].cpu_user
458 + cpu[index].cpu_nice
459 + cpu[index].cpu_system
460 + cpu[index].cpu_idle
461 + cpu[index].cpu_iowait
463 + cpu[index].cpu_softirq
464 + cpu[index].cpu_steal
467 cpu[index].cpu_active_total = cpu[index].cpu_total - (cpu[index].cpu_idle + cpu[index].cpu_iowait);
468 info.mask |= (1 << INFO_CPU);
470 double delta = current_update_time - last_update_time;
471 if (delta <= 0.001) break;
473 cpu[index].cpu_val[0] = (cpu[index].cpu_active_total - cpu[index].cpu_last_active_total) /
474 (float )(cpu[index].cpu_total - cpu[index].cpu_last_total);
476 for (i=0; i < info.cpu_avg_samples; i++ ) {
477 curtmp += cpu[index].cpu_val[i];
479 /* TESTING -- I've removed this, because I don't think it is right. You shouldn't divide
480 by the cpu count here ... removing for testing */
482 info.cpu_usage[index] = curtmp / info.cpu_avg_samples / info.cpu_count;
484 info.cpu_usage[index] = curtmp / info.cpu_avg_samples;
486 /* TESTING -- this line replaces the prev. "suspect" if/else */
487 info.cpu_usage[index] = curtmp / info.cpu_avg_samples;
489 cpu[index].cpu_last_total = cpu[index].cpu_total;
490 cpu[index].cpu_last_active_total = cpu[index].cpu_active_total;
491 for (i = info.cpu_avg_samples - 1; i > 0; i--) {
492 cpu[index].cpu_val[i] = cpu[index].cpu_val[i - 1];
500 void update_running_processes()
505 void update_cpu_usage()
510 void update_load_average()
512 #ifdef HAVE_GETLOADAVG
517 info.loadavg[0] = (float) v[0];
518 info.loadavg[1] = (float) v[1];
519 info.loadavg[2] = (float) v[2];
527 if (!(fp = open_file("/proc/loadavg", &rep)))
529 info.loadavg[0] = info.loadavg[1] = info.loadavg[2] = 0.0;
532 fscanf(fp, "%f %f %f", &info.loadavg[0], &info.loadavg[1], &info.loadavg[2]);
535 info.mask |= (1 << INFO_LOADAVG);
538 #define PROC_I8K "/proc/i8k"
539 #define I8K_DELIM " "
540 static char *i8k_procbuf = NULL;
545 i8k_procbuf = (char*)malloc(128*sizeof(char));
547 if ((fp = fopen(PROC_I8K,"r")) == NULL) {
548 CRIT_ERR("/proc/i8k doesn't exist! use insmod to make sure the kernel driver is loaded...");
551 memset(&i8k_procbuf[0],0,128);
552 if (fread(&i8k_procbuf[0],sizeof(char),128,fp) == 0) {
553 ERR("something wrong with /proc/i8k...");
558 i8k.version = strtok(&i8k_procbuf[0],I8K_DELIM);
559 i8k.bios = strtok(NULL,I8K_DELIM);
560 i8k.serial = strtok(NULL,I8K_DELIM);
561 i8k.cpu_temp = strtok(NULL,I8K_DELIM);
562 i8k.left_fan_status = strtok(NULL,I8K_DELIM);
563 i8k.right_fan_status = strtok(NULL,I8K_DELIM);
564 i8k.left_fan_rpm = strtok(NULL,I8K_DELIM);
565 i8k.right_fan_rpm = strtok(NULL,I8K_DELIM);
566 i8k.ac_status = strtok(NULL,I8K_DELIM);
567 i8k.buttons_status = strtok(NULL,I8K_DELIM);
571 /***********************************************************/
572 /***********************************************************/
573 /***********************************************************/
575 static int no_dots(const struct dirent *d)
577 if (d->d_name[0] == '.')
583 get_first_file_in_a_directory(const char *dir, char *s, int *rep)
585 struct dirent **namelist;
588 n = scandir(dir, &namelist, no_dots, alphasort);
591 ERR("scandir for %s: %s", dir, strerror(errno));
600 strncpy(s, namelist[0]->d_name, 255);
603 for (i = 0; i < n; i++)
611 #define I2C_DIR "/sys/bus/i2c/devices/"
614 open_i2c_sensor(const char *dev, const char *type, int n, int *div,
622 /* if i2c device is NULL or *, get first */
623 if (dev == NULL || strcmp(dev, "*") == 0) {
625 if (!get_first_file_in_a_directory(I2C_DIR, buf, &rep))
630 /* change vol to in */
631 if (strcmp(type, "vol") == 0)
634 if (strcmp(type, "tempf") == 0) {
635 snprintf(path, 255, I2C_DIR "%s/%s%d_input", dev, "temp", n);
637 snprintf(path, 255, I2C_DIR "%s/%s%d_input", dev, type, n);
639 strncpy(devtype, path, 255);
642 fd = open(path, O_RDONLY);
644 CRIT_ERR("can't open '%s': %s\nplease fix i2c or remove it from Conky", path, strerror(errno));
647 if (strcmp(type, "in") == 0 || strcmp(type, "temp") == 0
648 || strcmp(type, "tempf") == 0)
652 /* fan does not use *_div as a read divisor */
653 if (strcmp("fan", type) == 0)
656 /* test if *_div file exist, open it and use it as divisor */
657 if (strcmp(type, "tempf") == 0) {
658 snprintf(path, 255, I2C_DIR "%s/%s%d_div", "one", "two",
661 snprintf(path, 255, I2C_DIR "%s/%s%d_div", dev, type, n);
664 divfd = open(path, O_RDONLY);
669 divn = read(divfd, divbuf, 63);
670 /* should read until n == 0 but I doubt that kernel will give these
671 * in multiple pieces. :) */
681 double get_i2c_info(int *fd, int div, char *devtype, char *type)
688 lseek(*fd, 0, SEEK_SET);
694 n = read(*fd, buf, 63);
695 /* should read until n == 0 but I doubt that kernel will give these
696 * in multiple pieces. :) */
703 *fd = open(devtype, O_RDONLY);
705 ERR("can't open '%s': %s", devtype, strerror(errno));
707 /* My dirty hack for computing CPU value
708 * Filedil, from forums.gentoo.org
710 /* if (strstr(devtype, "temp1_input") != NULL)
711 return -15.096+1.4893*(val / 1000.0); */
714 /* divide voltage and temperature by 1000 */
715 /* or if any other divisor is given, use that */
716 if (strcmp(type, "tempf") == 0) {
718 return ((val / div + 40) * 9.0 / 5) - 40;
720 return ((val / 1000.0 + 40) * 9.0 / 5) - 40;
722 return ((val + 40) * 9.0 / 5) - 40;
733 /* Prior to kernel version 2.6.12, the CPU fan speed was available
734 * in ADT746X_FAN_OLD, whereas later kernel versions provide this
735 * information in ADT746X_FAN.
737 #define ADT746X_FAN "/sys/devices/temperatures/sensor1_fan_speed"
738 #define ADT746X_FAN_OLD "/sys/devices/temperatures/cpu_fan_speed"
740 void get_adt746x_fan( char * p_client_buffer, size_t client_buffer_size )
743 char adt746x_fan_state[64];
746 if ( !p_client_buffer || client_buffer_size <= 0 )
749 if ((fp = open_file(ADT746X_FAN, &rep)) == NULL
750 && (fp = open_file(ADT746X_FAN_OLD, &rep)) == NULL)
753 sprintf(adt746x_fan_state, "adt746x not found");
757 fgets(adt746x_fan_state, sizeof(adt746x_fan_state), fp);
758 adt746x_fan_state[strlen(adt746x_fan_state) - 1] = 0;
762 snprintf( p_client_buffer, client_buffer_size, "%s", adt746x_fan_state );
766 /* Prior to kernel version 2.6.12, the CPU temperature was found
767 * in ADT746X_CPU_OLD, whereas later kernel versions provide this
768 * information in ADT746X_CPU.
770 #define ADT746X_CPU "/sys/devices/temperatures/sensor1_temperature"
771 #define ADT746X_CPU_OLD "/sys/devices/temperatures/cpu_temperature"
773 void get_adt746x_cpu( char * p_client_buffer, size_t client_buffer_size )
776 char adt746x_cpu_state[64];
779 if ( !p_client_buffer || client_buffer_size <= 0 )
782 if ((fp = open_file(ADT746X_CPU, &rep)) == NULL
783 && (fp = open_file(ADT746X_CPU_OLD, &rep)) == NULL)
785 sprintf(adt746x_cpu_state, "adt746x not found");
789 fscanf(fp, "%2s", adt746x_cpu_state);
793 snprintf( p_client_buffer, client_buffer_size, "%s", adt746x_cpu_state );
797 /* Thanks to "Walt Nelson" <wnelsonjr@comcast.net> */
799 /***********************************************************************/
801 * This file is part of x86info.
802 * (C) 2001 Dave Jones.
804 * Licensed under the terms of the GNU GPL License version 2.
806 * Estimate CPU MHz routine by Andrea Arcangeli <andrea@suse.de>
807 * Small changes by David Sterba <sterd9am@ss1000.ms.mff.cuni.cz>
810 #if defined(__i386) || defined(__x86_64)
811 __inline__ unsigned long long int rdtsc()
813 unsigned long long int x;
814 __asm__ volatile (".byte 0x0f, 0x31":"=A" (x));
819 /* return system frequency in MHz (use divisor=1) or GHz (use divisor=1000) */
820 void get_freq_dynamic( char * p_client_buffer, size_t client_buffer_size, char * p_format, int divisor )
822 #if defined(__i386) || defined(__x86_64)
824 struct timeval tvstart, tvstop;
825 unsigned long long cycles[2]; /* gotta be 64 bit */
826 unsigned int microseconds; /* total time taken */
828 if ( !p_client_buffer || client_buffer_size <= 0 || !p_format || divisor <= 0 )
831 memset(&tz, 0, sizeof(tz));
833 /* get this function in cached memory */
834 gettimeofday(&tvstart, &tz);
836 gettimeofday(&tvstart, &tz);
838 /* we don't trust that this is any specific length of time */
841 gettimeofday(&tvstop, &tz);
842 microseconds = ((tvstop.tv_sec - tvstart.tv_sec) * 1000000) +
843 (tvstop.tv_usec - tvstart.tv_usec);
845 snprintf( p_client_buffer, client_buffer_size, p_format, (float)((cycles[1] - cycles[0]) / microseconds) / divisor );
848 /* FIXME: hardwired: get freq for first cpu!
849 this whole function needs to be rethought and redone for
850 multi-cpu/multi-core/multi-threaded environments and
851 arbitrary combinations thereof
853 get_freq( p_client_buffer, client_buffer_size, p_format, divisor, 1 );
859 #define CPUFREQ_PREFIX "/sys/devices/system/cpu"
860 #define CPUFREQ_POSTFIX "cpufreq/scaling_cur_freq"
862 /* return system frequency in MHz (use divisor=1) or GHz (use divisor=1000) */
863 char get_freq( char * p_client_buffer, size_t client_buffer_size, char * p_format, int divisor, unsigned int cpu )
871 if ( !p_client_buffer || client_buffer_size <= 0 || !p_format || divisor <= 0 )
876 char current_freq_file[128];
877 snprintf(current_freq_file, 127, "%s/cpu%d/%s",CPUFREQ_PREFIX, cpu-1, CPUFREQ_POSTFIX);
878 f = fopen(current_freq_file, "r");
881 /* if there's a cpufreq /sys node, read the current frequency from this node;
882 * divide by 1000 to get Mhz. */
883 if (fgets(s, sizeof(s), f)) {
884 s[strlen(s)-1] = '\0';
885 freq = strtod(s, NULL);
888 snprintf( p_client_buffer, client_buffer_size, p_format, (freq/1000)/divisor );
893 f = open_file("/proc/cpuinfo", &rep); //open the CPU information file
895 perror("Conky: Failed to access '/proc/cpuinfo' at get_freq()");
899 while (fgets(s, sizeof(s), f) != NULL){ //read the file
901 #if defined(__i386) || defined(__x86_64)
902 if (strncmp(s, "cpu MHz", 7) == 0 && cpu == 0) { //and search for the cpu mhz
905 if (strncmp(s, "cycle frequency [Hz]", 20) == 0 && cpu == 0) { // different on alpha
907 if (strncmp(s, "clock", 5) == 0 && cpu == 0) { // this is different on ppc for some reason
908 #endif // defined(__alpha)
909 #endif // defined(__i386) || defined(__x86_64)
911 strcpy(frequency, strchr(s, ':') + 2); //copy just the number
913 frequency[strlen(frequency) - 6] = '\0';// strip " est.\n"
914 freq = strtod(frequency, NULL)/1000000; // kernel reports in Hz
916 frequency[strlen(frequency) - 1] = '\0'; // strip \n
917 freq = strtod(frequency, NULL);
921 if (strncmp(s, "processor", 9) == 0) {
929 snprintf( p_client_buffer, client_buffer_size, p_format, (float)freq/divisor );
933 #define CPUFREQ_VOLTAGE "cpufreq/scaling_voltages"
935 /* return cpu voltage in mV (use divisor=1) or V (use divisor=1000) */
936 char get_voltage( char * p_client_buffer, size_t client_buffer_size, char * p_format, int divisor, unsigned int cpu )
938 /* /sys/devices/system/cpu/cpu0/cpufreq/scaling_voltages looks
950 /* Peter Tarjan (ptarjan@citromail.hu) */
955 char current_freq_file[128];
959 /* build the voltage file name */
961 snprintf(current_freq_file, 127, "%s/cpu%d/%s",
962 CPUFREQ_PREFIX, cpu, CPUFREQ_POSTFIX);
964 if ( !p_client_buffer || client_buffer_size <= 0 || !p_format || divisor <= 0 )
967 /* read the current cpu frequency from the /sys node */
968 f = fopen(current_freq_file, "r");
970 if (fgets(s, sizeof(s), f)) {
971 s[strlen(s)-1] = '\0';
972 freq = strtod(s, NULL);
976 fprintf(stderr, "Conky: Failed to access '%s' at ", current_freq_file);
977 perror("get_voltage()");
984 snprintf(current_freq_file, 127, "%s/cpu%d/%s",
985 CPUFREQ_PREFIX, cpu, CPUFREQ_VOLTAGE);
987 /* use the current cpu frequency to find the corresponding voltage */
988 f = fopen(current_freq_file, "r");
993 if (fgets(line, 255, f) == NULL) break;
994 sscanf(line, "%d %d", &freq_comp, &voltage);
995 if(freq_comp == freq) break;
999 fprintf(stderr, "Conky: Failed to access '%s' at ", current_freq_file);
1000 perror("get_voltage()");
1006 snprintf( p_client_buffer, client_buffer_size, p_format, (float)voltage/divisor );
1011 #define ACPI_FAN_DIR "/proc/acpi/fan/"
1013 void get_acpi_fan( char * p_client_buffer, size_t client_buffer_size )
1020 if ( !p_client_buffer || client_buffer_size <= 0 )
1023 /* yeah, slow... :/ */
1024 if (!get_first_file_in_a_directory(ACPI_FAN_DIR, buf, &rep))
1026 snprintf( p_client_buffer, client_buffer_size, "no fans?" );
1030 snprintf(buf2, sizeof(buf2), "%s%s/state", ACPI_FAN_DIR, buf );
1032 fp = open_file(buf2, &rep);
1034 snprintf( p_client_buffer, client_buffer_size, "can't open fan's state file" );
1037 memset(buf,0,sizeof(buf));
1038 fscanf(fp, "%*s %99s", buf);
1041 snprintf( p_client_buffer, client_buffer_size, "%s", buf );
1046 #define ACPI_AC_ADAPTER_DIR "/proc/acpi/ac_adapter/"
1048 void get_acpi_ac_adapter( char * p_client_buffer, size_t client_buffer_size )
1055 if ( !p_client_buffer || client_buffer_size <= 0 )
1058 /* yeah, slow... :/ */
1059 if (!get_first_file_in_a_directory(ACPI_AC_ADAPTER_DIR, buf, &rep))
1061 snprintf( p_client_buffer, client_buffer_size, "no ac_adapters?" );
1065 snprintf(buf2, sizeof(buf2), "%s%s/state", ACPI_AC_ADAPTER_DIR, buf );
1068 fp = open_file(buf2, &rep);
1070 snprintf( p_client_buffer, client_buffer_size, "No ac adapter found.... where is it?" );
1073 memset(buf,0,sizeof(buf));
1074 fscanf(fp, "%*s %99s", buf );
1077 snprintf( p_client_buffer, client_buffer_size, "%s", buf );
1083 /proc/acpi/thermal_zone/THRM/cooling_mode
1084 cooling mode: active
1085 /proc/acpi/thermal_zone/THRM/polling_frequency
1087 /proc/acpi/thermal_zone/THRM/state
1089 /proc/acpi/thermal_zone/THRM/temperature
1091 /proc/acpi/thermal_zone/THRM/trip_points
1093 passive: 73 C: tc1=4 tc2=3 tsp=40 devices=0xcdf6e6c0
1096 #define ACPI_THERMAL_DIR "/proc/acpi/thermal_zone/"
1097 #define ACPI_THERMAL_FORMAT "/proc/acpi/thermal_zone/%s/temperature"
1099 int open_acpi_temperature(const char *name)
1105 if (name == NULL || strcmp(name, "*") == 0) {
1107 if (!get_first_file_in_a_directory
1108 (ACPI_THERMAL_DIR, buf, &rep))
1113 snprintf(path, 255, ACPI_THERMAL_FORMAT, name);
1115 fd = open(path, O_RDONLY);
1117 ERR("can't open '%s': %s", path, strerror(errno));
1122 static double last_acpi_temp;
1123 static double last_acpi_temp_time;
1125 double get_acpi_temperature(int fd)
1130 /* don't update acpi temperature too often */
1131 if (current_update_time - last_acpi_temp_time < 11.32) {
1132 return last_acpi_temp;
1134 last_acpi_temp_time = current_update_time;
1136 /* seek to beginning */
1137 lseek(fd, 0, SEEK_SET);
1143 n = read(fd, buf, 255);
1145 ERR("can't read fd %d: %s", fd, strerror(errno));
1148 sscanf(buf, "temperature: %lf", &last_acpi_temp);
1152 return last_acpi_temp;
1156 hipo@lepakko hipo $ cat /proc/acpi/battery/BAT1/info
1158 design capacity: 4400 mAh
1159 last full capacity: 4064 mAh
1160 battery technology: rechargeable
1161 design voltage: 14800 mV
1162 design capacity warning: 300 mAh
1163 design capacity low: 200 mAh
1164 capacity granularity 1: 32 mAh
1165 capacity granularity 2: 32 mAh
1167 serial number: 16922
1173 hipo@lepakko conky $ cat /proc/acpi/battery/BAT1/state
1176 charging state: unknown
1178 remaining capacity: 4064 mAh
1179 present voltage: 16608 mV
1183 2213<@jupet kellari ö> jupet@lagi-unstable:~$ cat /proc/apm
1184 2213<@jupet kellari ö> 1.16 1.2 0x03 0x01 0xff 0x10 -1% -1 ?
1185 2213<@jupet kellari ö> (-1 ollee ei akkua kiinni, koska akku on pöydällä)
1186 2214<@jupet kellari ö> jupet@lagi-unstable:~$ cat /proc/apm
1187 2214<@jupet kellari ö> 1.16 1.2 0x03 0x01 0x03 0x09 98% -1 ?
1189 2238<@jupet kellari ö> 1.16 1.2 0x03 0x00 0x00 0x01 100% -1 ? ilman verkkovirtaa
1190 2239<@jupet kellari ö> 1.16 1.2 0x03 0x01 0x00 0x01 99% -1 ? verkkovirralla
1192 2240<@jupet kellari ö> 1.16 1.2 0x03 0x01 0x03 0x09 100% -1 ? verkkovirralla ja monitori päällä
1193 2241<@jupet kellari ö> 1.16 1.2 0x03 0x00 0x00 0x01 99% -1 ? monitori päällä mutta ilman verkkovirtaa
1196 #define ACPI_BATTERY_BASE_PATH "/proc/acpi/battery"
1197 #define APM_PATH "/proc/apm"
1199 static FILE *acpi_bat_fp;
1200 static FILE *apm_bat_fp;
1202 static int acpi_last_full;
1203 static int acpi_design_capacity;
1205 static char last_battery_str[64]; /* e.g. "charging 75%" */
1206 static char last_battery_time_str[64]; /* e.g. "3h 15m" */
1208 static double last_battery_time;
1210 static int last_battery_perct;
1211 static double last_battery_perct_time;
1213 void get_battery_stuff(char *buf, unsigned int n, const char *bat, int item)
1215 static int rep = 0, rep2 = 0;
1216 char acpi_path[128];
1217 snprintf(acpi_path, 127, ACPI_BATTERY_BASE_PATH "/%s/state", bat);
1219 /* don't update battery too often */
1220 if (current_update_time - last_battery_time < 29.5)
1221 goto set_return_value;
1223 last_battery_time = current_update_time;
1225 memset (last_battery_str, 0, sizeof (last_battery_str));
1226 memset (last_battery_time_str, 0, sizeof (last_battery_time_str));
1228 /* first try ACPI */
1230 if (acpi_bat_fp == NULL && apm_bat_fp == NULL)
1231 acpi_bat_fp = open_file(acpi_path, &rep);
1233 if (acpi_bat_fp != NULL) {
1234 int present_rate = -1;
1235 int remaining_capacity = -1;
1236 char charging_state[64];
1239 /* read last full capacity if it's zero */
1240 if (acpi_last_full == 0) {
1245 ACPI_BATTERY_BASE_PATH "/%s/info", bat);
1246 fp = open_file(path, &rep);
1250 if (fgets(b, 256, fp) == NULL)
1252 if (sscanf(b, "last full capacity: %d", &acpi_last_full) != 0) {
1261 fseek(acpi_bat_fp, 0, SEEK_SET);
1263 strcpy(charging_state, "unknown");
1265 while (!feof(acpi_bat_fp)) {
1267 if (fgets(buf, 256, acpi_bat_fp) == NULL)
1270 /* let's just hope units are ok */
1271 if (strncmp (buf, "present:", 8) == 0)
1272 sscanf(buf, "present: %4s", present);
1273 else if (strncmp (buf, "charging state:", 15) == 0)
1274 sscanf(buf, "charging state: %63s", charging_state);
1275 else if (strncmp (buf, "present rate:", 13) == 0)
1276 sscanf(buf, "present rate: %d", &present_rate);
1277 else if (strncmp(buf, "remaining capacity:", 19) == 0)
1278 sscanf(buf, "remaining capacity: %d", &remaining_capacity);
1281 /* Hellf[i]re notes that remaining capacity can exceed acpi_last_full */
1282 if (remaining_capacity > acpi_last_full)
1283 acpi_last_full = remaining_capacity; /* normalize to 100% */
1286 if (strcmp(present, "no") == 0) {
1287 strncpy(last_battery_str, "not present", 64);
1290 else if (strcmp(charging_state, "charging") == 0) {
1291 if (acpi_last_full != 0 && present_rate > 0) {
1292 /* e.g. charging 75% */
1293 snprintf(last_battery_str, sizeof(last_battery_str)-1, "charging %i%%",
1294 (int) ((remaining_capacity * 100) / acpi_last_full));
1296 format_seconds(last_battery_time_str, sizeof(last_battery_time_str)-1,
1297 (long) (((acpi_last_full - remaining_capacity) * 3600) /
1299 } else if (acpi_last_full != 0 && present_rate <= 0) {
1300 snprintf(last_battery_str, sizeof(last_battery_str)-1, "charging %d%%",
1301 (int) ((remaining_capacity * 100) / acpi_last_full));
1303 strncpy(last_battery_str, "charging", sizeof(last_battery_str)-1);
1307 else if (strncmp(charging_state, "discharging", 64) == 0) {
1308 if (present_rate > 0) {
1309 /* e.g. discharging 35% */
1310 snprintf(last_battery_str, sizeof(last_battery_str)-1, "discharging %i%%",
1311 (int) ((remaining_capacity * 100) / acpi_last_full));
1313 format_seconds(last_battery_time_str, sizeof(last_battery_time_str)-1,
1314 (long) ((remaining_capacity * 3600) / present_rate));
1315 } else if (present_rate == 0) { /* Thanks to Nexox for this one */
1316 snprintf(last_battery_str, sizeof(last_battery_str)-1, "full");
1318 snprintf(last_battery_str, sizeof(last_battery_str)-1,
1320 (int) ((remaining_capacity * 100) / acpi_last_full));
1324 /* thanks to Lukas Zapletal <lzap@seznam.cz> */
1325 else if (strncmp(charging_state, "charged", 64) == 0) {
1326 strcpy(last_battery_str, "charged");
1328 /* unknown, probably full / AC */
1330 if (acpi_last_full != 0
1331 && remaining_capacity != acpi_last_full)
1332 snprintf(last_battery_str, 64, "unknown %d%%",
1333 (int) ((remaining_capacity * 100) / acpi_last_full));
1335 strncpy(last_battery_str, "AC", 64);
1339 if (apm_bat_fp == NULL)
1340 apm_bat_fp = open_file(APM_PATH, &rep2);
1342 if (apm_bat_fp != NULL) {
1343 int ac, status, flag, life;
1346 "%*s %*s %*x %x %x %x %d%%",
1347 &ac, &status, &flag, &life);
1350 /* could check now that there is ac */
1351 snprintf(last_battery_str, 64, "AC");
1352 } else if (ac && life != 100) { /* could check that status==3 here? */
1353 snprintf(last_battery_str, 64,
1354 "charging %d%%", life);
1356 snprintf(last_battery_str, 64, "%d%%",
1360 /* it seemed to buffer it so file must be closed (or could use syscalls
1361 * directly but I don't feel like coding it now) */
1369 case BATTERY_STATUS:
1371 snprintf(buf, n, "%s", last_battery_str);
1376 snprintf(buf, n, "%s", last_battery_time_str);
1385 int get_battery_perct(const char *bat)
1388 char acpi_path[128];
1389 snprintf(acpi_path, 127, ACPI_BATTERY_BASE_PATH "/%s/state", bat);
1391 /* don't update battery too often */
1392 if (current_update_time - last_battery_perct_time < 30) {
1393 return last_battery_perct;
1395 last_battery_perct_time = current_update_time;
1397 /* Only check for ACPI */
1399 if (acpi_bat_fp == NULL && apm_bat_fp == NULL)
1400 acpi_bat_fp = open_file(acpi_path, &rep);
1402 int remaining_capacity = -1;
1403 if (acpi_bat_fp != NULL) {
1404 /* read last full capacity if it's zero */
1405 if (acpi_design_capacity == 0) {
1410 ACPI_BATTERY_BASE_PATH "/%s/info", bat);
1411 fp = open_file(path, &rep);
1415 if (fgets(b, 256, fp) == NULL)
1417 if (sscanf(b, "design capacity: %d", &acpi_design_capacity) != 0) {
1425 fseek(acpi_bat_fp, 0, SEEK_SET);
1427 while (!feof(acpi_bat_fp)) {
1429 if (fgets(buf, 256, acpi_bat_fp) == NULL)
1433 sscanf(buf, "remaining capacity: %d",
1434 &remaining_capacity);
1437 if(remaining_capacity < 0)
1439 /* compute the battery percentage */
1440 last_battery_perct =
1441 (int) (((float)remaining_capacity/acpi_design_capacity) * 100);
1442 return last_battery_perct;
1445 int get_battery_perct_bar(const char *bar)
1447 get_battery_perct(bar);
1448 return (int) (last_battery_perct * 2.56 - 1);
1453 /* On Apple powerbook and ibook:
1454 $ cat /proc/pmu/battery_0
1461 $ cat /proc/pmu/info
1462 PMU driver version : 2
1463 PMU firmware version : 0c
1468 /* defines as in <linux/pmu.h> */
1469 #define PMU_BATT_PRESENT 0x00000001
1470 #define PMU_BATT_CHARGING 0x00000002
1472 static FILE* pmu_battery_fp;
1473 static FILE* pmu_info_fp;
1474 static char pb_battery_info[3][32];
1475 static double pb_battery_info_update;
1477 #define PMU_PATH "/proc/pmu"
1478 void get_powerbook_batt_info(char *buf, size_t n, int i)
1481 const char* batt_path = PMU_PATH "/battery_0";
1482 const char* info_path = PMU_PATH "/info";
1483 int flags, charge, max_charge, ac = -1;
1486 /* don't update battery too often */
1487 if (current_update_time - pb_battery_info_update < 29.5) {
1488 snprintf(buf, n, "%s", pb_battery_info[i]);
1491 pb_battery_info_update = current_update_time;
1493 if (pmu_battery_fp == NULL)
1494 pmu_battery_fp = open_file(batt_path, &rep);
1496 if (pmu_battery_fp != NULL) {
1497 rewind(pmu_battery_fp);
1498 while (!feof(pmu_battery_fp)) {
1500 if (fgets(buf, sizeof(buf), pmu_battery_fp) == NULL)
1504 sscanf(buf, "flags : %8x", &flags);
1505 else if (buf[0] == 'c' && buf[1] == 'h')
1506 sscanf(buf, "charge : %d", &charge);
1507 else if (buf[0] == 'm')
1508 sscanf(buf, "max_charge : %d", &max_charge);
1509 else if (buf[0] == 't')
1510 sscanf(buf, "time rem. : %ld", &time);
1513 if (pmu_info_fp == NULL)
1514 pmu_info_fp = open_file(info_path, &rep);
1516 if (pmu_info_fp != NULL) {
1517 rewind(pmu_info_fp);
1518 while (!feof(pmu_info_fp)) {
1520 if (fgets(buf, sizeof(buf), pmu_info_fp) == NULL)
1523 sscanf(buf, "AC Power : %d", &ac);
1526 /* update status string */
1527 if ((ac && !(flags & PMU_BATT_PRESENT)))
1528 strcpy(pb_battery_info[PB_BATT_STATUS], "AC");
1529 else if (ac && (flags & PMU_BATT_PRESENT)
1530 && !(flags & PMU_BATT_CHARGING))
1531 strcpy(pb_battery_info[PB_BATT_STATUS], "charged");
1532 else if ((flags & PMU_BATT_PRESENT)
1533 && (flags & PMU_BATT_CHARGING))
1534 strcpy(pb_battery_info[PB_BATT_STATUS], "charging");
1536 strcpy(pb_battery_info[PB_BATT_STATUS], "discharging");
1538 /* update percentage string */
1540 pb_battery_info[PB_BATT_PERCENT][0] = 0;
1542 snprintf(pb_battery_info[PB_BATT_PERCENT],
1543 sizeof(pb_battery_info[PB_BATT_PERCENT]),
1544 "%d%%", (charge * 100)/max_charge);
1546 /* update time string */
1547 if (time == 0) /* fully charged or battery not present */
1548 pb_battery_info[PB_BATT_TIME][0] = 0;
1549 else if (time < 60*60) /* don't show secs */
1550 format_seconds_short(pb_battery_info[PB_BATT_TIME],
1551 sizeof(pb_battery_info[PB_BATT_TIME]), time);
1553 format_seconds(pb_battery_info[PB_BATT_TIME],
1554 sizeof(pb_battery_info[PB_BATT_TIME]), time);
1556 snprintf(buf, n, "%s", pb_battery_info[i]);
1561 show_nice_processes = 1;
1562 process_find_top(info.cpu, info.memu);
1563 info.first_process = get_first_process();
1568 * The following ifdefs were adapted from gkrellm
1570 #include <linux/major.h>
1572 #if ! defined (MD_MAJOR)
1576 #if !defined(LVM_BLK_MAJOR)
1577 #define LVM_BLK_MAJOR 58
1580 #if !defined(NBD_MAJOR)
1581 #define NBD_MAJOR 43
1584 void update_diskio()
1586 static unsigned int last = UINT_MAX;
1587 static unsigned int last_read = UINT_MAX;
1588 static unsigned int last_write = UINT_MAX;
1594 unsigned int current = 0;
1595 unsigned int current_read = 0;
1596 unsigned int current_write = 0;
1597 unsigned int reads, writes = 0;
1600 if (!(fp =open_file("/proc/diskstats", &rep))) {
1605 /* read reads and writes from all disks (minor = 0), including
1606 * cd-roms and floppies, and summ them up
1609 fgets(buf, 512, fp);
1610 col_count = sscanf(buf, "%u %u %*s %*u %*u %u %*u %*u %*u %u",
1611 &major, &minor, &reads, &writes);
1612 /* ignore subdevices (they have only 3 matching entries in their line)
1613 * and virtual devices (LVM, network block devices, RAM disks, Loopback)
1615 * XXX ignore devices which are part of a SW RAID (MD_MAJOR)
1617 if (col_count > 3 &&
1618 major != LVM_BLK_MAJOR && major != NBD_MAJOR &&
1619 major != RAMDISK_MAJOR && major != LOOP_MAJOR) {
1620 current += reads + writes;
1621 current_read += reads;
1622 current_write += writes;
1626 /* since the values in /proc/diststats are absolute, we have
1627 * to substract our last reading. The numbers stand for
1628 * "sectors read", and we therefore have to divide by two to
1630 int tot = ((double)(current-last)/2);
1631 int tot_read = ((double)(current_read-last_read)/2);
1632 int tot_write = ((double)(current_write-last_write)/2);
1634 if (last_read > current_read)
1636 if (last_write > current_write)
1639 if (last > current) {
1640 /* we hit this either if it's the very first time we
1641 * run this, or when /proc/diskstats overflows; while
1642 * 0 is not correct, it's at least not way off */
1646 last_read = current_read;
1647 last_write = current_write;
1650 diskio_read_value = tot_read;
1651 diskio_write_value = tot_write;
1656 /* Here come the IBM ACPI-specific things. For reference, see
1657 http://ibm-acpi.sourceforge.net/README
1658 If IBM ACPI is installed, /proc/acpi/ibm contains the following files:
1674 The content of these files is described in detail in the aforementioned
1675 README - some of them also in the following functions accessing them.
1676 Peter Tarjan (ptarjan@citromail.hu)
1679 #define IBM_ACPI_DIR "/proc/acpi/ibm"
1681 void get_ibm_acpi_fan( char * p_client_buffer, size_t client_buffer_size )
1683 /* get fan speed on IBM/Lenovo laptops running the ibm acpi.
1684 /proc/acpi/ibm/fan looks like this (3 lines):
1687 commands: enable, disable
1688 Peter Tarjan (ptarjan@citromail.hu)
1691 if ( !p_client_buffer || client_buffer_size <= 0 )
1695 unsigned int speed=0;
1697 snprintf(fan, 127, "%s/fan",IBM_ACPI_DIR);
1699 fp = fopen(fan, "r");
1705 if (fgets(line, 255, fp) == NULL) break;
1706 if (sscanf(line, "speed: %d", &speed)) break;
1711 CRIT_ERR("can't open '%s': %s\nYou are not using the IBM ACPI. Remove ibm* from your Conky config file.", fan, strerror(errno));
1715 snprintf( p_client_buffer, client_buffer_size, "%d", speed );
1720 static double last_ibm_acpi_temp_time;
1721 void get_ibm_acpi_temps()
1723 /* get the measured temperatures from the temperature sensors
1724 on IBM/Lenovo laptops running the ibm acpi.
1725 There are 8 values in /proc/acpi/ibm/thermal, and according to
1726 http://ibm-acpi.sourceforge.net/README
1727 these mean the following (at least on an IBM R51...)
1728 0: CPU (also on the T series laptops)
1729 1: Mini PCI Module (?)
1731 3: GPU (also on the T series laptops)
1736 I'm not too sure about those with the question mark, but the values I'm
1737 reading from *my* thermal file (on a T42p) look realistic for the
1738 hdd and the battery.
1739 #5 and #7 are always -128.
1740 /proc/acpi/ibm/thermal looks like this (1 line):
1741 temperatures: 41 43 31 46 33 -128 29 -128
1742 Peter Tarjan (ptarjan@citromail.hu)
1745 /* don't update too often */
1746 if (current_update_time - last_ibm_acpi_temp_time < 10.00)
1750 last_ibm_acpi_temp_time = current_update_time;
1752 /* if ( !p_client_buffer || client_buffer_size <= 0 )
1758 snprintf(thermal, 127, "%s/thermal",IBM_ACPI_DIR);
1759 fp = fopen(thermal, "r");
1766 if (fgets(line, 255, fp) == NULL) break;
1767 if (sscanf(line, "temperatures: %d %d %d %d %d %d %d %d",
1768 &ibm_acpi.temps[0], &ibm_acpi.temps[1],
1769 &ibm_acpi.temps[2], &ibm_acpi.temps[3],
1770 &ibm_acpi.temps[4], &ibm_acpi.temps[5],
1771 &ibm_acpi.temps[6], &ibm_acpi.temps[7])) break;
1776 CRIT_ERR("can't open '%s': %s\nYou are not using the IBM ACPI. Remove ibm* from your Conky config file.", thermal, strerror(errno));
1784 void get_ibm_acpi_volume( char * p_client_buffer, size_t client_buffer_size )
1787 /* get volume (0-14) on IBM/Lenovo laptops running the ibm acpi.
1788 "Volume" here is none of the mixer volumes, but a "master of masters"
1789 volume adjusted by the IBM volume keys.
1790 /proc/acpi/ibm/fan looks like this (4 lines):
1793 commands: up, down, mute
1794 commands: level <level> (<level> is 0-15)
1795 Peter Tarjan (ptarjan@citromail.hu)
1798 if ( !p_client_buffer || client_buffer_size <= 0 )
1804 snprintf(volume, 127, "%s/volume",IBM_ACPI_DIR);
1805 unsigned int vol=-1;
1808 fp = fopen(volume, "r");
1814 if (fgets(line, 255, fp) == NULL) break;
1815 if (sscanf(line, "level: %d", &vol)) continue;
1816 if (sscanf(line, "mute: %s", mute)) break;
1821 CRIT_ERR("can't open '%s': %s\nYou are not using the IBM ACPI. Remove ibm* from your Conky config file.", volume, strerror(errno));
1826 if (strcmp(mute, "on")==0)
1828 snprintf( p_client_buffer, client_buffer_size, "%s", "mute" );
1833 snprintf( p_client_buffer, client_buffer_size, "%d", vol );
1839 /*static FILE *fp=NULL;*/
1841 void get_ibm_acpi_brightness(char * p_client_buffer, size_t client_buffer_size)
1843 /* get LCD brightness on IBM/Lenovo laptops running the ibm acpi.
1844 /proc/acpi/ibm/brightness looks like this (3 lines):
1847 commands: level <level> (<level> is 0-7)
1848 Peter Tarjan (ptarjan@citromail.hu)
1851 if ( !p_client_buffer || client_buffer_size <= 0 )
1855 unsigned int brightness=0;
1857 snprintf(filename, 127, "%s/brightness",IBM_ACPI_DIR);
1859 fp = fopen(filename, "r");
1865 if (fgets(line, 255, fp) == NULL) break;
1866 if (sscanf(line, "level: %d", &brightness)) break;
1871 CRIT_ERR("can't open '%s': %s\nYou are not using the IBM ACPI. Remove ibm* from your Conky config file.", filename, strerror(errno));
1876 snprintf( p_client_buffer, client_buffer_size, "%d", brightness );
1881 void update_entropy (void)
1884 const char *entropy_avail = "/proc/sys/kernel/random/entropy_avail";
1885 const char *entropy_poolsize = "/proc/sys/kernel/random/poolsize";
1888 info.entropy.entropy_avail=0;
1889 info.entropy.poolsize=0;
1891 if ((fp1 = open_file (entropy_avail, &rep))==NULL)
1894 if ((fp2 = open_file (entropy_poolsize, &rep))==NULL)
1900 fscanf (fp1, "%u", &info.entropy.entropy_avail);
1901 fscanf (fp2, "%u", &info.entropy.poolsize);
1906 info.mask |= (1 << INFO_ENTROPY);