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)
190 ns->recv += (r - ns->last_read_recv);
191 ns->last_read_recv = r;
193 if (t < ns->last_read_trans)
196 ns->trans += (t - ns->last_read_trans);
197 ns->last_read_trans = t;
199 /*** ip addr patch ***/
200 i = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
202 conf.ifc_buf = malloc(sizeof(struct ifreq) * 16);
204 conf.ifc_len = sizeof(struct ifreq) * 16;
206 ioctl((long) i, SIOCGIFCONF, &conf);
208 for (k = 0; k < conf.ifc_len / sizeof(struct ifreq); k++) {
210 ns = get_net_stat(((struct ifreq *) conf.
211 ifc_buf)[k].ifr_ifrn.ifrn_name);
213 ((struct ifreq *) conf.ifc_buf)[k].ifr_ifru.
222 /*** end ip addr patch ***/
225 /* calculate speeds */
226 ns->net_rec[0] = (ns->recv - last_recv) / delta;
227 ns->net_trans[0] = (ns->trans - last_trans) / delta;
231 for (i = 0; (unsigned) i < info.net_avg_samples; i++) {
232 curtmp1 += ns->net_rec[i];
233 curtmp2 += ns->net_trans[i];
235 ns->recv_speed = curtmp1 / (double) info.net_avg_samples;
236 ns->trans_speed = curtmp2 / (double) info.net_avg_samples;
237 if (info.net_avg_samples > 1) {
238 for (i = info.net_avg_samples; i > 1; i--) {
239 ns->net_rec[i - 1] = ns->net_rec[i - 2];
240 ns->net_trans[i - 1] =
241 ns->net_trans[i - 2];
249 info.mask |= (1 << INFO_NET);
252 inline void update_wifi_stats()
254 /** wireless stats patch by Bobby Beckmann **/
258 /*open file and ignore first two lines sorry, this code sucks ass right now, i'll clean it up later */
259 if (net_wireless_fp == NULL)
260 net_wireless_fp = open_file("/proc/net/wireless", &rep);
262 fseek(net_wireless_fp, 0, SEEK_SET);
263 if (net_wireless_fp == NULL)
266 fgets(buf, 255, net_wireless_fp); /* garbage */
267 fgets(buf, 255, net_wireless_fp); /* garbage (field names) */
269 /* read each interface */
270 for (i = 0; i < 16; i++) {
275 if (fgets(buf, 255, net_wireless_fp) == NULL)
278 while (isspace((int) *p))
283 while (*p && *p != ':')
290 ns = get_net_stat(s);
292 sscanf(p, "%*d %d. %d. %d", &l, &m, &n);
294 ns->linkstatus = (int) (log(MIN(MAX(l,1),92)) / log(92) * 100);
298 /*** end wireless patch ***/
303 void update_total_processes()
308 struct sysinfo s_info;
310 info.procs = s_info.procs;
318 if (!(fp = open_file("/proc/loadavg", &rep)))
323 fscanf(fp, "%*f %*f %*f %*d/%hd", &info.procs );
326 info.mask |= (1 << INFO_PROCS);
329 #define CPU_SAMPLE_COUNT 15
331 unsigned long long cpu_user;
332 unsigned long long cpu_system;
333 unsigned long long cpu_nice;
334 unsigned long long cpu_idle;
335 unsigned long long cpu_iowait;
336 unsigned long long cpu_irq;
337 unsigned long long cpu_softirq;
338 unsigned long long cpu_steal;
339 unsigned long long cpu_total;
340 unsigned long long cpu_active_total;
341 unsigned long long cpu_last_total;
342 unsigned long long cpu_last_active_total;
343 double cpu_val[CPU_SAMPLE_COUNT];
345 static short cpu_setup = 0;
348 determine if this kernel gives us "extended" statistics information in /proc/stat.
349 Kernels around 2.5 and earlier only reported user, system, nice and idle values in proc stat.
350 Kernels around 2.6 and greater report these PLUS iowait, irq, softirq, and steal
352 void determine_longstat(char * buf) {
353 unsigned long long iowait=0;
354 KFLAG_SETOFF(KFLAG_IS_LONGSTAT);
355 /* scanf will either return -1 or 1 because there is only 1 assignment */
356 if (sscanf(buf, "%*s %*d %*d %*d %*d %llu",&iowait)>0) KFLAG_SETON(KFLAG_IS_LONGSTAT);
364 if (info.cpu_usage) {
369 if (!(stat_fp = open_file("/proc/stat", &rep)))
374 while (!feof(stat_fp)) {
375 if (fgets(buf, 255, stat_fp) == NULL)
378 if (strncmp(buf, "cpu", 3) == 0 && isdigit(buf[3])) {
379 if (info.cpu_count == 0) {
380 determine_longstat(buf);
385 info.cpu_usage = malloc((info.cpu_count + 1) * sizeof(float));
390 #define TMPL_LONGSTAT "%*s %llu %llu %llu %llu %llu %llu %llu %llu"
391 #define TMPL_SHORTSTAT "%*s %llu %llu %llu %llu"
393 inline static void update_stat()
397 static struct cpu_info *cpu = NULL;
402 char * stat_template=NULL;
403 unsigned int malloc_cpu_size=0;
406 /* add check for !info.cpu_usage since that mem is freed on a SIGUSR1 */
407 if (!cpu_setup || !info.cpu_usage) {
412 if (!stat_template) {
413 stat_template = KFLAG_ISSET(KFLAG_IS_LONGSTAT) ? TMPL_LONGSTAT : TMPL_SHORTSTAT ;
417 malloc_cpu_size = (info.cpu_count + 1) * sizeof(struct cpu_info);
418 cpu = malloc(malloc_cpu_size);
419 memset(cpu, 0, malloc_cpu_size);
422 if (!(stat_fp = open_file("/proc/stat", &rep)))
427 memset(info.cpu_usage, 0, info.cpu_count * sizeof (float));
433 while (!feof(stat_fp)) {
434 if (fgets(buf, 255, stat_fp) == NULL)
437 if (strncmp(buf, "procs_running ", 14) == 0) {
438 sscanf(buf, "%*s %hu", &info.run_procs);
439 info.mask |= (1 << INFO_RUN_PROCS);
440 } else if (strncmp(buf, "cpu", 3) == 0) {
441 index = isdigit(buf[3]) ? ((int)buf[3]) - 0x2F : 0;
442 sscanf(buf, stat_template
443 , &(cpu[index].cpu_user)
444 , &(cpu[index].cpu_nice)
445 , &(cpu[index].cpu_system)
446 , &(cpu[index].cpu_idle)
447 , &(cpu[index].cpu_iowait)
448 , &(cpu[index].cpu_irq)
449 , &(cpu[index].cpu_softirq)
450 , &(cpu[index].cpu_steal)
453 cpu[index].cpu_total = cpu[index].cpu_user
454 + cpu[index].cpu_nice
455 + cpu[index].cpu_system
456 + cpu[index].cpu_idle
457 + cpu[index].cpu_iowait
459 + cpu[index].cpu_softirq
460 + cpu[index].cpu_steal
463 cpu[index].cpu_active_total = cpu[index].cpu_total - (cpu[index].cpu_idle + cpu[index].cpu_iowait);
464 info.mask |= (1 << INFO_CPU);
466 double delta = current_update_time - last_update_time;
467 if (delta <= 0.001) break;
469 cpu[index].cpu_val[0] = (cpu[index].cpu_active_total - cpu[index].cpu_last_active_total) /
470 (float )(cpu[index].cpu_total - cpu[index].cpu_last_total);
472 for (i=0; i < info.cpu_avg_samples; i++ ) {
473 curtmp += cpu[index].cpu_val[i];
475 /* TESTING -- I've removed this, because I don't think it is right. You shouldn't divide
476 by the cpu count here ... removing for testing */
478 info.cpu_usage[index] = curtmp / info.cpu_avg_samples / info.cpu_count;
480 info.cpu_usage[index] = curtmp / info.cpu_avg_samples;
482 /* TESTING -- this line replaces the prev. "suspect" if/else */
483 info.cpu_usage[index] = curtmp / info.cpu_avg_samples;
485 cpu[index].cpu_last_total = cpu[index].cpu_total;
486 cpu[index].cpu_last_active_total = cpu[index].cpu_active_total;
487 for (i = info.cpu_avg_samples - 1; i > 0; i--) {
488 cpu[index].cpu_val[i] = cpu[index].cpu_val[i - 1];
496 void update_running_processes()
501 void update_cpu_usage()
506 void update_load_average()
508 #ifdef HAVE_GETLOADAVG
513 info.loadavg[0] = (float) v[0];
514 info.loadavg[1] = (float) v[1];
515 info.loadavg[2] = (float) v[2];
523 if (!(fp = open_file("/proc/loadavg", &rep)))
525 info.loadavg[0] = info.loadavg[1] = info.loadavg[2] = 0.0;
528 fscanf(fp, "%f %f %f", &info.loadavg[0], &info.loadavg[1], &info.loadavg[2]);
531 info.mask |= (1 << INFO_LOADAVG);
534 #define PROC_I8K "/proc/i8k"
535 #define I8K_DELIM " "
536 static char *i8k_procbuf = NULL;
541 i8k_procbuf = (char*)malloc(128*sizeof(char));
543 if ((fp = fopen(PROC_I8K,"r")) == NULL) {
544 CRIT_ERR("/proc/i8k doesn't exist! use insmod to make sure the kernel driver is loaded...");
547 memset(&i8k_procbuf[0],0,128);
548 if (fread(&i8k_procbuf[0],sizeof(char),128,fp) == 0) {
549 ERR("something wrong with /proc/i8k...");
554 i8k.version = strtok(&i8k_procbuf[0],I8K_DELIM);
555 i8k.bios = strtok(NULL,I8K_DELIM);
556 i8k.serial = strtok(NULL,I8K_DELIM);
557 i8k.cpu_temp = strtok(NULL,I8K_DELIM);
558 i8k.left_fan_status = strtok(NULL,I8K_DELIM);
559 i8k.right_fan_status = strtok(NULL,I8K_DELIM);
560 i8k.left_fan_rpm = strtok(NULL,I8K_DELIM);
561 i8k.right_fan_rpm = strtok(NULL,I8K_DELIM);
562 i8k.ac_status = strtok(NULL,I8K_DELIM);
563 i8k.buttons_status = strtok(NULL,I8K_DELIM);
567 /***********************************************************/
568 /***********************************************************/
569 /***********************************************************/
571 static int no_dots(const struct dirent *d)
573 if (d->d_name[0] == '.')
579 get_first_file_in_a_directory(const char *dir, char *s, int *rep)
581 struct dirent **namelist;
584 n = scandir(dir, &namelist, no_dots, alphasort);
587 ERR("scandir for %s: %s", dir, strerror(errno));
596 strncpy(s, namelist[0]->d_name, 255);
599 for (i = 0; i < n; i++)
607 #define I2C_DIR "/sys/bus/i2c/devices/"
610 open_i2c_sensor(const char *dev, const char *type, int n, int *div,
618 /* if i2c device is NULL or *, get first */
619 if (dev == NULL || strcmp(dev, "*") == 0) {
621 if (!get_first_file_in_a_directory(I2C_DIR, buf, &rep))
626 /* change vol to in */
627 if (strcmp(type, "vol") == 0)
630 if (strcmp(type, "tempf") == 0) {
631 snprintf(path, 255, I2C_DIR "%s/%s%d_input", dev, "temp", n);
633 snprintf(path, 255, I2C_DIR "%s/%s%d_input", dev, type, n);
635 strncpy(devtype, path, 255);
638 fd = open(path, O_RDONLY);
640 CRIT_ERR("can't open '%s': %s\nplease fix i2c or remove it from Conky", path, strerror(errno));
643 if (strcmp(type, "in") == 0 || strcmp(type, "temp") == 0
644 || strcmp(type, "tempf") == 0)
648 /* fan does not use *_div as a read divisor */
649 if (strcmp("fan", type) == 0)
652 /* test if *_div file exist, open it and use it as divisor */
653 if (strcmp(type, "tempf") == 0) {
654 snprintf(path, 255, I2C_DIR "%s/%s%d_div", "one", "two",
657 snprintf(path, 255, I2C_DIR "%s/%s%d_div", dev, type, n);
660 divfd = open(path, O_RDONLY);
665 divn = read(divfd, divbuf, 63);
666 /* should read until n == 0 but I doubt that kernel will give these
667 * in multiple pieces. :) */
677 double get_i2c_info(int *fd, int div, char *devtype, char *type)
684 lseek(*fd, 0, SEEK_SET);
690 n = read(*fd, buf, 63);
691 /* should read until n == 0 but I doubt that kernel will give these
692 * in multiple pieces. :) */
699 *fd = open(devtype, O_RDONLY);
701 ERR("can't open '%s': %s", devtype, strerror(errno));
703 /* My dirty hack for computing CPU value
704 * Filedil, from forums.gentoo.org
706 /* if (strstr(devtype, "temp1_input") != NULL)
707 return -15.096+1.4893*(val / 1000.0); */
710 /* divide voltage and temperature by 1000 */
711 /* or if any other divisor is given, use that */
712 if (strcmp(type, "tempf") == 0) {
714 return ((val / div + 40) * 9.0 / 5) - 40;
716 return ((val / 1000.0 + 40) * 9.0 / 5) - 40;
718 return ((val + 40) * 9.0 / 5) - 40;
729 /* Prior to kernel version 2.6.12, the CPU fan speed was available
730 * in ADT746X_FAN_OLD, whereas later kernel versions provide this
731 * information in ADT746X_FAN.
733 #define ADT746X_FAN "/sys/devices/temperatures/sensor1_fan_speed"
734 #define ADT746X_FAN_OLD "/sys/devices/temperatures/cpu_fan_speed"
736 void get_adt746x_fan( char * p_client_buffer, size_t client_buffer_size )
739 char adt746x_fan_state[64];
742 if ( !p_client_buffer || client_buffer_size <= 0 )
745 if ((fp = open_file(ADT746X_FAN, &rep)) == NULL
746 && (fp = open_file(ADT746X_FAN_OLD, &rep)) == NULL)
749 sprintf(adt746x_fan_state, "adt746x not found");
753 fgets(adt746x_fan_state, sizeof(adt746x_fan_state), fp);
754 adt746x_fan_state[strlen(adt746x_fan_state) - 1] = 0;
758 snprintf( p_client_buffer, client_buffer_size, "%s", adt746x_fan_state );
762 /* Prior to kernel version 2.6.12, the CPU temperature was found
763 * in ADT746X_CPU_OLD, whereas later kernel versions provide this
764 * information in ADT746X_CPU.
766 #define ADT746X_CPU "/sys/devices/temperatures/sensor1_temperature"
767 #define ADT746X_CPU_OLD "/sys/devices/temperatures/cpu_temperature"
769 void get_adt746x_cpu( char * p_client_buffer, size_t client_buffer_size )
772 char adt746x_cpu_state[64];
775 if ( !p_client_buffer || client_buffer_size <= 0 )
778 if ((fp = open_file(ADT746X_CPU, &rep)) == NULL
779 && (fp = open_file(ADT746X_CPU_OLD, &rep)) == NULL)
781 sprintf(adt746x_cpu_state, "adt746x not found");
785 fscanf(fp, "%2s", adt746x_cpu_state);
789 snprintf( p_client_buffer, client_buffer_size, "%s", adt746x_cpu_state );
793 /* Thanks to "Walt Nelson" <wnelsonjr@comcast.net> */
795 /***********************************************************************/
797 * This file is part of x86info.
798 * (C) 2001 Dave Jones.
800 * Licensed under the terms of the GNU GPL License version 2.
802 * Estimate CPU MHz routine by Andrea Arcangeli <andrea@suse.de>
803 * Small changes by David Sterba <sterd9am@ss1000.ms.mff.cuni.cz>
806 #if defined(__i386) || defined(__x86_64)
807 __inline__ unsigned long long int rdtsc()
809 unsigned long long int x;
810 __asm__ volatile (".byte 0x0f, 0x31":"=A" (x));
815 /* return system frequency in MHz (use divisor=1) or GHz (use divisor=1000) */
816 void get_freq_dynamic( char * p_client_buffer, size_t client_buffer_size, char * p_format, int divisor )
818 #if defined(__i386) || defined(__x86_64)
820 struct timeval tvstart, tvstop;
821 unsigned long long cycles[2]; /* gotta be 64 bit */
822 unsigned int microseconds; /* total time taken */
824 if ( !p_client_buffer || client_buffer_size <= 0 || !p_format || divisor <= 0 )
827 memset(&tz, 0, sizeof(tz));
829 /* get this function in cached memory */
830 gettimeofday(&tvstart, &tz);
832 gettimeofday(&tvstart, &tz);
834 /* we don't trust that this is any specific length of time */
837 gettimeofday(&tvstop, &tz);
838 microseconds = ((tvstop.tv_sec - tvstart.tv_sec) * 1000000) +
839 (tvstop.tv_usec - tvstart.tv_usec);
841 snprintf( p_client_buffer, client_buffer_size, p_format, (float)((cycles[1] - cycles[0]) / microseconds) / divisor );
844 /* FIXME: hardwired: get freq for first cpu!
845 this whole function needs to be rethought and redone for
846 multi-cpu/multi-core/multi-threaded environments and
847 arbitrary combinations thereof
849 get_freq( p_client_buffer, client_buffer_size, p_format, divisor, 1 );
855 #define CPUFREQ_PREFIX "/sys/devices/system/cpu"
856 #define CPUFREQ_POSTFIX "cpufreq/scaling_cur_freq"
858 /* return system frequency in MHz (use divisor=1) or GHz (use divisor=1000) */
859 char get_freq( char * p_client_buffer, size_t client_buffer_size, char * p_format, int divisor, unsigned int cpu )
867 if ( !p_client_buffer || client_buffer_size <= 0 || !p_format || divisor <= 0 )
872 char current_freq_file[128];
873 snprintf(current_freq_file, 127, "%s/cpu%d/%s",CPUFREQ_PREFIX, cpu-1, CPUFREQ_POSTFIX);
874 f = fopen(current_freq_file, "r");
877 /* if there's a cpufreq /sys node, read the current frequency from this node;
878 * divide by 1000 to get Mhz. */
879 if (fgets(s, sizeof(s), f)) {
880 s[strlen(s)-1] = '\0';
881 freq = strtod(s, NULL);
884 snprintf( p_client_buffer, client_buffer_size, p_format, (freq/1000)/divisor );
889 f = open_file("/proc/cpuinfo", &rep); //open the CPU information file
891 perror("Conky: Failed to access '/proc/cpuinfo' at get_freq()");
895 while (fgets(s, sizeof(s), f) != NULL){ //read the file
897 #if defined(__i386) || defined(__x86_64)
898 if (strncmp(s, "cpu MHz", 7) == 0 && cpu == 0) { //and search for the cpu mhz
901 if (strncmp(s, "cycle frequency [Hz]", 20) == 0 && cpu == 0) { // different on alpha
903 if (strncmp(s, "clock", 5) == 0 && cpu == 0) { // this is different on ppc for some reason
904 #endif // defined(__alpha)
905 #endif // defined(__i386) || defined(__x86_64)
907 strcpy(frequency, strchr(s, ':') + 2); //copy just the number
909 frequency[strlen(frequency) - 6] = '\0';// strip " est.\n"
910 freq = strtod(frequency, NULL)/1000000; // kernel reports in Hz
912 frequency[strlen(frequency) - 1] = '\0'; // strip \n
913 freq = strtod(frequency, NULL);
917 if (strncmp(s, "processor", 9) == 0) {
925 snprintf( p_client_buffer, client_buffer_size, p_format, (float)freq/divisor );
929 #define CPUFREQ_VOLTAGE "cpufreq/scaling_voltages"
931 /* return cpu voltage in mV (use divisor=1) or V (use divisor=1000) */
932 char get_voltage( char * p_client_buffer, size_t client_buffer_size, char * p_format, int divisor, unsigned int cpu )
934 /* /sys/devices/system/cpu/cpu0/cpufreq/scaling_voltages looks
946 /* Peter Tarjan (ptarjan@citromail.hu) */
951 char current_freq_file[128];
955 /* build the voltage file name */
957 snprintf(current_freq_file, 127, "%s/cpu%d/%s",
958 CPUFREQ_PREFIX, cpu, CPUFREQ_POSTFIX);
960 if ( !p_client_buffer || client_buffer_size <= 0 || !p_format || divisor <= 0 )
963 /* read the current cpu frequency from the /sys node */
964 f = fopen(current_freq_file, "r");
966 if (fgets(s, sizeof(s), f)) {
967 s[strlen(s)-1] = '\0';
968 freq = strtod(s, NULL);
972 fprintf(stderr, "Conky: Failed to access '%s' at ", current_freq_file);
973 perror("get_voltage()");
980 snprintf(current_freq_file, 127, "%s/cpu%d/%s",
981 CPUFREQ_PREFIX, cpu, CPUFREQ_VOLTAGE);
983 /* use the current cpu frequency to find the corresponding voltage */
984 f = fopen(current_freq_file, "r");
989 if (fgets(line, 255, f) == NULL) break;
990 sscanf(line, "%d %d", &freq_comp, &voltage);
991 if(freq_comp == freq) break;
995 fprintf(stderr, "Conky: Failed to access '%s' at ", current_freq_file);
996 perror("get_voltage()");
1002 snprintf( p_client_buffer, client_buffer_size, p_format, (float)voltage/divisor );
1007 #define ACPI_FAN_DIR "/proc/acpi/fan/"
1009 void get_acpi_fan( char * p_client_buffer, size_t client_buffer_size )
1016 if ( !p_client_buffer || client_buffer_size <= 0 )
1019 /* yeah, slow... :/ */
1020 if (!get_first_file_in_a_directory(ACPI_FAN_DIR, buf, &rep))
1022 snprintf( p_client_buffer, client_buffer_size, "no fans?" );
1026 snprintf(buf2, sizeof(buf2), "%s%s/state", ACPI_FAN_DIR, buf );
1028 fp = open_file(buf2, &rep);
1030 snprintf( p_client_buffer, client_buffer_size, "can't open fan's state file" );
1033 memset(buf,0,sizeof(buf));
1034 fscanf(fp, "%*s %99s", buf);
1037 snprintf( p_client_buffer, client_buffer_size, "%s", buf );
1042 #define ACPI_AC_ADAPTER_DIR "/proc/acpi/ac_adapter/"
1044 void get_acpi_ac_adapter( char * p_client_buffer, size_t client_buffer_size )
1051 if ( !p_client_buffer || client_buffer_size <= 0 )
1054 /* yeah, slow... :/ */
1055 if (!get_first_file_in_a_directory(ACPI_AC_ADAPTER_DIR, buf, &rep))
1057 snprintf( p_client_buffer, client_buffer_size, "no ac_adapters?" );
1061 snprintf(buf2, sizeof(buf2), "%s%s/state", ACPI_AC_ADAPTER_DIR, buf );
1064 fp = open_file(buf2, &rep);
1066 snprintf( p_client_buffer, client_buffer_size, "No ac adapter found.... where is it?" );
1069 memset(buf,0,sizeof(buf));
1070 fscanf(fp, "%*s %99s", buf );
1073 snprintf( p_client_buffer, client_buffer_size, "%s", buf );
1079 /proc/acpi/thermal_zone/THRM/cooling_mode
1080 cooling mode: active
1081 /proc/acpi/thermal_zone/THRM/polling_frequency
1083 /proc/acpi/thermal_zone/THRM/state
1085 /proc/acpi/thermal_zone/THRM/temperature
1087 /proc/acpi/thermal_zone/THRM/trip_points
1089 passive: 73 C: tc1=4 tc2=3 tsp=40 devices=0xcdf6e6c0
1092 #define ACPI_THERMAL_DIR "/proc/acpi/thermal_zone/"
1093 #define ACPI_THERMAL_FORMAT "/proc/acpi/thermal_zone/%s/temperature"
1095 int open_acpi_temperature(const char *name)
1101 if (name == NULL || strcmp(name, "*") == 0) {
1103 if (!get_first_file_in_a_directory
1104 (ACPI_THERMAL_DIR, buf, &rep))
1109 snprintf(path, 255, ACPI_THERMAL_FORMAT, name);
1111 fd = open(path, O_RDONLY);
1113 ERR("can't open '%s': %s", path, strerror(errno));
1118 static double last_acpi_temp;
1119 static double last_acpi_temp_time;
1121 double get_acpi_temperature(int fd)
1126 /* don't update acpi temperature too often */
1127 if (current_update_time - last_acpi_temp_time < 11.32) {
1128 return last_acpi_temp;
1130 last_acpi_temp_time = current_update_time;
1132 /* seek to beginning */
1133 lseek(fd, 0, SEEK_SET);
1139 n = read(fd, buf, 255);
1141 ERR("can't read fd %d: %s", fd, strerror(errno));
1144 sscanf(buf, "temperature: %lf", &last_acpi_temp);
1148 return last_acpi_temp;
1152 hipo@lepakko hipo $ cat /proc/acpi/battery/BAT1/info
1154 design capacity: 4400 mAh
1155 last full capacity: 4064 mAh
1156 battery technology: rechargeable
1157 design voltage: 14800 mV
1158 design capacity warning: 300 mAh
1159 design capacity low: 200 mAh
1160 capacity granularity 1: 32 mAh
1161 capacity granularity 2: 32 mAh
1163 serial number: 16922
1169 hipo@lepakko conky $ cat /proc/acpi/battery/BAT1/state
1172 charging state: unknown
1174 remaining capacity: 4064 mAh
1175 present voltage: 16608 mV
1179 2213<@jupet kellari ö> jupet@lagi-unstable:~$ cat /proc/apm
1180 2213<@jupet kellari ö> 1.16 1.2 0x03 0x01 0xff 0x10 -1% -1 ?
1181 2213<@jupet kellari ö> (-1 ollee ei akkua kiinni, koska akku on pöydällä)
1182 2214<@jupet kellari ö> jupet@lagi-unstable:~$ cat /proc/apm
1183 2214<@jupet kellari ö> 1.16 1.2 0x03 0x01 0x03 0x09 98% -1 ?
1185 2238<@jupet kellari ö> 1.16 1.2 0x03 0x00 0x00 0x01 100% -1 ? ilman verkkovirtaa
1186 2239<@jupet kellari ö> 1.16 1.2 0x03 0x01 0x00 0x01 99% -1 ? verkkovirralla
1188 2240<@jupet kellari ö> 1.16 1.2 0x03 0x01 0x03 0x09 100% -1 ? verkkovirralla ja monitori päällä
1189 2241<@jupet kellari ö> 1.16 1.2 0x03 0x00 0x00 0x01 99% -1 ? monitori päällä mutta ilman verkkovirtaa
1192 #define ACPI_BATTERY_BASE_PATH "/proc/acpi/battery"
1193 #define APM_PATH "/proc/apm"
1195 static FILE *acpi_bat_fp;
1196 static FILE *apm_bat_fp;
1198 static int acpi_last_full;
1199 static int acpi_design_capacity;
1201 static char last_battery_str[64]; /* e.g. "charging 75%" */
1202 static char last_battery_time_str[64]; /* e.g. "3h 15m" */
1204 static double last_battery_time;
1206 static int last_battery_perct;
1207 static double last_battery_perct_time;
1209 void get_battery_stuff(char *buf, unsigned int n, const char *bat, int item)
1211 static int rep = 0, rep2 = 0;
1212 char acpi_path[128];
1213 snprintf(acpi_path, 127, ACPI_BATTERY_BASE_PATH "/%s/state", bat);
1215 /* don't update battery too often */
1216 if (current_update_time - last_battery_time < 29.5)
1217 goto set_return_value;
1219 last_battery_time = current_update_time;
1221 memset (last_battery_str, 0, sizeof (last_battery_str));
1222 memset (last_battery_time_str, 0, sizeof (last_battery_time_str));
1224 /* first try ACPI */
1226 if (acpi_bat_fp == NULL && apm_bat_fp == NULL)
1227 acpi_bat_fp = open_file(acpi_path, &rep);
1229 if (acpi_bat_fp != NULL) {
1230 int present_rate = -1;
1231 int remaining_capacity = -1;
1232 char charging_state[64];
1235 /* read last full capacity if it's zero */
1236 if (acpi_last_full == 0) {
1241 ACPI_BATTERY_BASE_PATH "/%s/info", bat);
1242 fp = open_file(path, &rep);
1246 if (fgets(b, 256, fp) == NULL)
1248 if (sscanf(b, "last full capacity: %d", &acpi_last_full) != 0) {
1257 fseek(acpi_bat_fp, 0, SEEK_SET);
1259 strcpy(charging_state, "unknown");
1261 while (!feof(acpi_bat_fp)) {
1263 if (fgets(buf, 256, acpi_bat_fp) == NULL)
1266 /* let's just hope units are ok */
1267 if (strncmp (buf, "present:", 8) == 0)
1268 sscanf(buf, "present: %4s", present);
1269 else if (strncmp (buf, "charging state:", 15) == 0)
1270 sscanf(buf, "charging state: %63s", charging_state);
1271 else if (strncmp (buf, "present rate:", 13) == 0)
1272 sscanf(buf, "present rate: %d", &present_rate);
1273 else if (strncmp(buf, "remaining capacity:", 19) == 0)
1274 sscanf(buf, "remaining capacity: %d", &remaining_capacity);
1277 /* Hellf[i]re notes that remaining capacity can exceed acpi_last_full */
1278 if (remaining_capacity > acpi_last_full)
1279 acpi_last_full = remaining_capacity; /* normalize to 100% */
1282 if (strcmp(present, "no") == 0) {
1283 strncpy(last_battery_str, "not present", 64);
1286 else if (strcmp(charging_state, "charging") == 0) {
1287 if (acpi_last_full != 0 && present_rate > 0) {
1288 /* e.g. charging 75% */
1289 snprintf(last_battery_str, sizeof(last_battery_str)-1, "charging %i%%",
1290 (int) ((remaining_capacity * 100) / acpi_last_full));
1292 format_seconds(last_battery_time_str, sizeof(last_battery_time_str)-1,
1293 (long) (((acpi_last_full - remaining_capacity) * 3600) /
1295 } else if (acpi_last_full != 0 && present_rate <= 0) {
1296 snprintf(last_battery_str, sizeof(last_battery_str)-1, "charging %d%%",
1297 (int) ((remaining_capacity * 100) / acpi_last_full));
1299 strncpy(last_battery_str, "charging", sizeof(last_battery_str)-1);
1303 else if (strncmp(charging_state, "discharging", 64) == 0) {
1304 if (present_rate > 0) {
1305 /* e.g. discharging 35% */
1306 snprintf(last_battery_str, sizeof(last_battery_str)-1, "discharging %i%%",
1307 (int) ((remaining_capacity * 100) / acpi_last_full));
1309 format_seconds(last_battery_time_str, sizeof(last_battery_time_str)-1,
1310 (long) ((remaining_capacity * 3600) / present_rate));
1311 } else if (present_rate == 0) { /* Thanks to Nexox for this one */
1312 snprintf(last_battery_str, sizeof(last_battery_str)-1, "full");
1314 snprintf(last_battery_str, sizeof(last_battery_str)-1,
1316 (int) ((remaining_capacity * 100) / acpi_last_full));
1320 /* thanks to Lukas Zapletal <lzap@seznam.cz> */
1321 else if (strncmp(charging_state, "charged", 64) == 0) {
1322 strcpy(last_battery_str, "charged");
1324 /* unknown, probably full / AC */
1326 if (acpi_last_full != 0
1327 && remaining_capacity != acpi_last_full)
1328 snprintf(last_battery_str, 64, "unknown %d%%",
1329 (int) ((remaining_capacity * 100) / acpi_last_full));
1331 strncpy(last_battery_str, "AC", 64);
1335 if (apm_bat_fp == NULL)
1336 apm_bat_fp = open_file(APM_PATH, &rep2);
1338 if (apm_bat_fp != NULL) {
1339 int ac, status, flag, life;
1342 "%*s %*s %*x %x %x %x %d%%",
1343 &ac, &status, &flag, &life);
1346 /* could check now that there is ac */
1347 snprintf(last_battery_str, 64, "AC");
1348 } else if (ac && life != 100) { /* could check that status==3 here? */
1349 snprintf(last_battery_str, 64,
1350 "charging %d%%", life);
1352 snprintf(last_battery_str, 64, "%d%%",
1356 /* it seemed to buffer it so file must be closed (or could use syscalls
1357 * directly but I don't feel like coding it now) */
1365 case BATTERY_STATUS:
1367 snprintf(buf, n, "%s", last_battery_str);
1372 snprintf(buf, n, "%s", last_battery_time_str);
1381 int get_battery_perct(const char *bat)
1384 char acpi_path[128];
1385 snprintf(acpi_path, 127, ACPI_BATTERY_BASE_PATH "/%s/state", bat);
1387 /* don't update battery too often */
1388 if (current_update_time - last_battery_perct_time < 30) {
1389 return last_battery_perct;
1391 last_battery_perct_time = current_update_time;
1393 /* Only check for ACPI */
1395 if (acpi_bat_fp == NULL && apm_bat_fp == NULL)
1396 acpi_bat_fp = open_file(acpi_path, &rep);
1398 int remaining_capacity = -1;
1399 if (acpi_bat_fp != NULL) {
1400 /* read last full capacity if it's zero */
1401 if (acpi_design_capacity == 0) {
1406 ACPI_BATTERY_BASE_PATH "/%s/info", bat);
1407 fp = open_file(path, &rep);
1411 if (fgets(b, 256, fp) == NULL)
1413 if (sscanf(b, "design capacity: %d", &acpi_design_capacity) != 0) {
1421 fseek(acpi_bat_fp, 0, SEEK_SET);
1423 while (!feof(acpi_bat_fp)) {
1425 if (fgets(buf, 256, acpi_bat_fp) == NULL)
1429 sscanf(buf, "remaining capacity: %d",
1430 &remaining_capacity);
1433 if(remaining_capacity < 0)
1435 /* compute the battery percentage */
1436 last_battery_perct =
1437 (int) (((float)remaining_capacity/acpi_design_capacity) * 100);
1438 return last_battery_perct;
1441 int get_battery_perct_bar(const char *bar)
1443 get_battery_perct(bar);
1444 return (int) (last_battery_perct * 2.56 - 1);
1449 /* On Apple powerbook and ibook:
1450 $ cat /proc/pmu/battery_0
1457 $ cat /proc/pmu/info
1458 PMU driver version : 2
1459 PMU firmware version : 0c
1464 /* defines as in <linux/pmu.h> */
1465 #define PMU_BATT_PRESENT 0x00000001
1466 #define PMU_BATT_CHARGING 0x00000002
1468 static FILE* pmu_battery_fp;
1469 static FILE* pmu_info_fp;
1470 static char pb_battery_info[3][32];
1471 static double pb_battery_info_update;
1473 #define PMU_PATH "/proc/pmu"
1474 void get_powerbook_batt_info(char *buf, size_t n, int i)
1477 const char* batt_path = PMU_PATH "/battery_0";
1478 const char* info_path = PMU_PATH "/info";
1479 int flags, charge, max_charge, ac = -1;
1482 /* don't update battery too often */
1483 if (current_update_time - pb_battery_info_update < 29.5) {
1484 snprintf(buf, n, "%s", pb_battery_info[i]);
1487 pb_battery_info_update = current_update_time;
1489 if (pmu_battery_fp == NULL)
1490 pmu_battery_fp = open_file(batt_path, &rep);
1492 if (pmu_battery_fp != NULL) {
1493 rewind(pmu_battery_fp);
1494 while (!feof(pmu_battery_fp)) {
1496 if (fgets(buf, sizeof(buf), pmu_battery_fp) == NULL)
1500 sscanf(buf, "flags : %8x", &flags);
1501 else if (buf[0] == 'c' && buf[1] == 'h')
1502 sscanf(buf, "charge : %d", &charge);
1503 else if (buf[0] == 'm')
1504 sscanf(buf, "max_charge : %d", &max_charge);
1505 else if (buf[0] == 't')
1506 sscanf(buf, "time rem. : %ld", &time);
1509 if (pmu_info_fp == NULL)
1510 pmu_info_fp = open_file(info_path, &rep);
1512 if (pmu_info_fp != NULL) {
1513 rewind(pmu_info_fp);
1514 while (!feof(pmu_info_fp)) {
1516 if (fgets(buf, sizeof(buf), pmu_info_fp) == NULL)
1519 sscanf(buf, "AC Power : %d", &ac);
1522 /* update status string */
1523 if ((ac && !(flags & PMU_BATT_PRESENT)))
1524 strcpy(pb_battery_info[PB_BATT_STATUS], "AC");
1525 else if (ac && (flags & PMU_BATT_PRESENT)
1526 && !(flags & PMU_BATT_CHARGING))
1527 strcpy(pb_battery_info[PB_BATT_STATUS], "charged");
1528 else if ((flags & PMU_BATT_PRESENT)
1529 && (flags & PMU_BATT_CHARGING))
1530 strcpy(pb_battery_info[PB_BATT_STATUS], "charging");
1532 strcpy(pb_battery_info[PB_BATT_STATUS], "discharging");
1534 /* update percentage string */
1536 pb_battery_info[PB_BATT_PERCENT][0] = 0;
1538 snprintf(pb_battery_info[PB_BATT_PERCENT],
1539 sizeof(pb_battery_info[PB_BATT_PERCENT]),
1540 "%d%%", (charge * 100)/max_charge);
1542 /* update time string */
1543 if (time == 0) /* fully charged or battery not present */
1544 pb_battery_info[PB_BATT_TIME][0] = 0;
1545 else if (time < 60*60) /* don't show secs */
1546 format_seconds_short(pb_battery_info[PB_BATT_TIME],
1547 sizeof(pb_battery_info[PB_BATT_TIME]), time);
1549 format_seconds(pb_battery_info[PB_BATT_TIME],
1550 sizeof(pb_battery_info[PB_BATT_TIME]), time);
1552 snprintf(buf, n, "%s", pb_battery_info[i]);
1557 show_nice_processes = 1;
1558 process_find_top(info.cpu, info.memu);
1559 info.first_process = get_first_process();
1564 * The following ifdefs were adapted from gkrellm
1566 #include <linux/major.h>
1568 #if ! defined (MD_MAJOR)
1572 #if !defined(LVM_BLK_MAJOR)
1573 #define LVM_BLK_MAJOR 58
1576 #if !defined(NBD_MAJOR)
1577 #define NBD_MAJOR 43
1580 void update_diskio()
1582 static unsigned int last = UINT_MAX;
1583 static unsigned int last_read = UINT_MAX;
1584 static unsigned int last_write = UINT_MAX;
1590 unsigned int current = 0;
1591 unsigned int current_read = 0;
1592 unsigned int current_write = 0;
1593 unsigned int reads, writes = 0;
1596 if (!(fp =open_file("/proc/diskstats", &rep))) {
1601 /* read reads and writes from all disks (minor = 0), including
1602 * cd-roms and floppies, and summ them up
1605 fgets(buf, 512, fp);
1606 col_count = sscanf(buf, "%u %u %*s %*u %*u %u %*u %*u %*u %u",
1607 &major, &minor, &reads, &writes);
1608 /* ignore subdevices (they have only 3 matching entries in their line)
1609 * and virtual devices (LVM, network block devices, RAM disks, Loopback)
1611 * XXX ignore devices which are part of a SW RAID (MD_MAJOR)
1613 if (col_count > 3 &&
1614 major != LVM_BLK_MAJOR && major != NBD_MAJOR &&
1615 major != RAMDISK_MAJOR && major != LOOP_MAJOR) {
1616 current += reads + writes;
1617 current_read += reads;
1618 current_write += writes;
1622 /* since the values in /proc/diststats are absolute, we have
1623 * to substract our last reading. The numbers stand for
1624 * "sectors read", and we therefore have to divide by two to
1626 int tot = ((double)(current-last)/2);
1627 int tot_read = ((double)(current_read-last_read)/2);
1628 int tot_write = ((double)(current_write-last_write)/2);
1630 if (last_read > current_read)
1632 if (last_write > current_write)
1635 if (last > current) {
1636 /* we hit this either if it's the very first time we
1637 * run this, or when /proc/diskstats overflows; while
1638 * 0 is not correct, it's at least not way off */
1642 last_read = current_read;
1643 last_write = current_write;
1646 diskio_read_value = tot_read;
1647 diskio_write_value = tot_write;
1652 /* Here come the IBM ACPI-specific things. For reference, see
1653 http://ibm-acpi.sourceforge.net/README
1654 If IBM ACPI is installed, /proc/acpi/ibm contains the following files:
1670 The content of these files is described in detail in the aforementioned
1671 README - some of them also in the following functions accessing them.
1672 Peter Tarjan (ptarjan@citromail.hu)
1675 #define IBM_ACPI_DIR "/proc/acpi/ibm"
1677 void get_ibm_acpi_fan( char * p_client_buffer, size_t client_buffer_size )
1679 /* get fan speed on IBM/Lenovo laptops running the ibm acpi.
1680 /proc/acpi/ibm/fan looks like this (3 lines):
1683 commands: enable, disable
1684 Peter Tarjan (ptarjan@citromail.hu)
1687 if ( !p_client_buffer || client_buffer_size <= 0 )
1691 unsigned int speed=0;
1693 snprintf(fan, 127, "%s/fan",IBM_ACPI_DIR);
1695 fp = fopen(fan, "r");
1701 if (fgets(line, 255, fp) == NULL) break;
1702 if (sscanf(line, "speed: %d", &speed)) break;
1707 CRIT_ERR("can't open '%s': %s\nYou are not using the IBM ACPI. Remove ibm* from your Conky config file.", fan, strerror(errno));
1711 snprintf( p_client_buffer, client_buffer_size, "%d", speed );
1716 static double last_ibm_acpi_temp_time;
1717 void get_ibm_acpi_temps()
1719 /* get the measured temperatures from the temperature sensors
1720 on IBM/Lenovo laptops running the ibm acpi.
1721 There are 8 values in /proc/acpi/ibm/thermal, and according to
1722 http://ibm-acpi.sourceforge.net/README
1723 these mean the following (at least on an IBM R51...)
1724 0: CPU (also on the T series laptops)
1725 1: Mini PCI Module (?)
1727 3: GPU (also on the T series laptops)
1732 I'm not too sure about those with the question mark, but the values I'm
1733 reading from *my* thermal file (on a T42p) look realistic for the
1734 hdd and the battery.
1735 #5 and #7 are always -128.
1736 /proc/acpi/ibm/thermal looks like this (1 line):
1737 temperatures: 41 43 31 46 33 -128 29 -128
1738 Peter Tarjan (ptarjan@citromail.hu)
1741 /* don't update too often */
1742 if (current_update_time - last_ibm_acpi_temp_time < 10.00)
1746 last_ibm_acpi_temp_time = current_update_time;
1748 /* if ( !p_client_buffer || client_buffer_size <= 0 )
1754 snprintf(thermal, 127, "%s/thermal",IBM_ACPI_DIR);
1755 fp = fopen(thermal, "r");
1762 if (fgets(line, 255, fp) == NULL) break;
1763 if (sscanf(line, "temperatures: %d %d %d %d %d %d %d %d",
1764 &ibm_acpi.temps[0], &ibm_acpi.temps[1],
1765 &ibm_acpi.temps[2], &ibm_acpi.temps[3],
1766 &ibm_acpi.temps[4], &ibm_acpi.temps[5],
1767 &ibm_acpi.temps[6], &ibm_acpi.temps[7])) break;
1772 CRIT_ERR("can't open '%s': %s\nYou are not using the IBM ACPI. Remove ibm* from your Conky config file.", thermal, strerror(errno));
1780 void get_ibm_acpi_volume( char * p_client_buffer, size_t client_buffer_size )
1783 /* get volume (0-14) on IBM/Lenovo laptops running the ibm acpi.
1784 "Volume" here is none of the mixer volumes, but a "master of masters"
1785 volume adjusted by the IBM volume keys.
1786 /proc/acpi/ibm/fan looks like this (4 lines):
1789 commands: up, down, mute
1790 commands: level <level> (<level> is 0-15)
1791 Peter Tarjan (ptarjan@citromail.hu)
1794 if ( !p_client_buffer || client_buffer_size <= 0 )
1800 snprintf(volume, 127, "%s/volume",IBM_ACPI_DIR);
1801 unsigned int vol=-1;
1804 fp = fopen(volume, "r");
1810 if (fgets(line, 255, fp) == NULL) break;
1811 if (sscanf(line, "level: %d", &vol)) continue;
1812 if (sscanf(line, "mute: %s", mute)) break;
1817 CRIT_ERR("can't open '%s': %s\nYou are not using the IBM ACPI. Remove ibm* from your Conky config file.", volume, strerror(errno));
1822 if (strcmp(mute, "on")==0)
1824 snprintf( p_client_buffer, client_buffer_size, "%s", "mute" );
1829 snprintf( p_client_buffer, client_buffer_size, "%d", vol );
1835 /*static FILE *fp=NULL;*/
1837 void get_ibm_acpi_brightness(char * p_client_buffer, size_t client_buffer_size)
1839 /* get LCD brightness on IBM/Lenovo laptops running the ibm acpi.
1840 /proc/acpi/ibm/brightness looks like this (3 lines):
1843 commands: level <level> (<level> is 0-7)
1844 Peter Tarjan (ptarjan@citromail.hu)
1847 if ( !p_client_buffer || client_buffer_size <= 0 )
1851 unsigned int brightness=0;
1853 snprintf(filename, 127, "%s/brightness",IBM_ACPI_DIR);
1855 fp = fopen(filename, "r");
1861 if (fgets(line, 255, fp) == NULL) break;
1862 if (sscanf(line, "level: %d", &brightness)) break;
1867 CRIT_ERR("can't open '%s': %s\nYou are not using the IBM ACPI. Remove ibm* from your Conky config file.", filename, strerror(errno));
1872 snprintf( p_client_buffer, client_buffer_size, "%d", brightness );
1877 void update_entropy (void)
1880 const char *entropy_avail = "/proc/sys/kernel/random/entropy_avail";
1881 const char *entropy_poolsize = "/proc/sys/kernel/random/poolsize";
1884 info.entropy.entropy_avail=0;
1885 info.entropy.poolsize=0;
1887 if ((fp1 = open_file (entropy_avail, &rep))==NULL)
1890 if ((fp2 = open_file (entropy_poolsize, &rep))==NULL)
1896 fscanf (fp1, "%u", &info.entropy.entropy_avail);
1897 fscanf (fp2, "%u", &info.entropy.poolsize);
1902 info.mask |= (1 << INFO_ENTROPY);