13 void sleep_nanos(long nanos
) {
17 nanosleep(&rqtp
, NULL
);
20 long get_time_nanos() {
22 gettimeofday(&t
, NULL
);
23 return t
.tv_sec
* 1000000000L + t
.tv_usec
* 1000;
26 char* read_file(char* filename
) {
27 static char buf
[32768];
30 int fd
= open(filename
, 0);
33 ssize_t result
= read(fd
, buf
+pos
, sizeof(buf
)-pos
);
35 fprintf(stderr
, "Failed reading file: %s -- %s\n", strerror(errno
), filename
);
42 if (pos
>= sizeof(buf
)) {
43 fprintf(stderr
, "Failed reading file, too much data: %s\n", filename
);
49 int parse_int(char* s
) {
55 int value
= strtol(s
, NULL
, 10);
57 fprintf(stderr
, "Failed to parse string: %s -- %s\n", strerror(errno
), s
);
64 char* read_next_line(char** s
) {
65 char* end
= index(*s
, '\n');
76 int read_cpu_idle_jiffys() {
77 char* procstat
= read_file("/proc/stat");
78 if (procstat
== NULL
) {
82 char* line
= read_next_line(&procstat
);
88 for (int i
= 0; i
<= 4; ++i
, line
=NULL
) {
89 result
= strtok(line
, " ");
91 return parse_int(result
);
95 char* procstat
= read_file("/proc/stat");
96 if (procstat
== NULL
) {
102 char* line
= read_next_line(&procstat
);
106 if (strncmp("cpu", line
, 3) == 0) {
113 int read_cpu_percent() {
114 int num_cpus
= count_cpus();
116 long tstart
= get_time_nanos();
117 int idle_jiffy1
= read_cpu_idle_jiffys();
118 sleep_nanos(100000000L);
119 int idle_jiffy2
= read_cpu_idle_jiffys();
120 long tend
= get_time_nanos();
122 double duration_sec
= ((double)tend
- (double)tstart
) / 1000000000.0;
123 double idle_jiffys_per_second
= (idle_jiffy2
- idle_jiffy1
) / duration_sec
;
125 double idle_jiffys_per_cpu_second
= idle_jiffys_per_second
/ num_cpus
;
127 // One jiffy is 10ms, so we can get the percentage very easily!
128 return 100 - (int)round(idle_jiffys_per_cpu_second
);
131 int read_mem_percent() {
132 char* meminfo
= read_file("/proc/meminfo");
133 if (meminfo
== NULL
) {
140 while (*meminfo
&& (mem_total
< 0 || mem_free
< 0)) {
141 char* line
= read_next_line(&meminfo
);
146 char* key
= strtok(line
, ": ");
147 char* value_str
= strtok(NULL
, ": ");
149 if (key
== NULL
|| value_str
== NULL
) {
150 fprintf(stderr
, "Failed to parse key/value token in /proc/meminfo\n");
154 if (strcmp(key
, "MemTotal") == 0) {
155 mem_total
= parse_int(value_str
);
156 } else if (strcmp(key
, "MemAvailable") == 0) {
157 mem_free
= parse_int(value_str
);
161 if (mem_total
< 0 || mem_free
< 0) {
162 fprintf(stderr
, "Failed to find MemTotal and MemAvailable in /proc/meminfo\n");
166 int mem_used
= mem_total
- mem_free
;
168 return (int)round((double)mem_used
/ (double)mem_total
* 100);
171 int read_battery_percent() {
172 char* percent_str
= NULL
;
173 if (percent_str
== NULL
) {
174 percent_str
= read_file("/sys/class/power_supply/BAT0/capacity");
176 if (percent_str
== NULL
) {
177 percent_str
= read_file("/sys/class/power_supply/BAT1/capacity");
179 return parse_int(percent_str
);
183 char* name
, char* units
,
185 int red_low
, int red_high
191 char* color
= "black";
192 if (value
>= red_low
&& value
<= red_high
) {
197 "%s <span color='%s'>%d</span>%s ",
198 name
, color
, value
, units
202 int main(int argc
, char** argv
) {
203 char* show_flags
= "cmb";
205 show_flags
= argv
[1];
210 if (strchr(show_flags
, 'c')) {
218 if (strchr(show_flags
, 'm')) {
226 if (strchr(show_flags
, 'b')) {
229 read_battery_percent(),