Xinqi Bao's Git

added entropy
[slstatus.git] / slstatus.c
1 /* See LICENSE file for copyright and license details. */
2
3 /* global libraries */
4 #include <alsa/asoundlib.h>
5 #include <fcntl.h>
6 #include <locale.h>
7 #include <stdarg.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <sys/statvfs.h>
14 #include <time.h>
15 #include <unistd.h>
16 #include <X11/Xlib.h>
17
18 /* local headers */
19 #include "slstatus.h"
20 #include "config.h"
21
22 /* set statusbar */
23 void
24 setstatus(const char *str)
25 {
26 /* set WM_NAME via X11 */
27 XStoreName(dpy, DefaultRootWindow(dpy), str);
28 XSync(dpy, False);
29 }
30
31 /* smprintf function */
32 char *
33 smprintf(const char *fmt, ...)
34 {
35 va_list fmtargs;
36 char *ret = NULL;
37
38 va_start(fmtargs, fmt);
39 if (vasprintf(&ret, fmt, fmtargs) < 0)
40 return NULL;
41 va_end(fmtargs);
42
43 return ret;
44 }
45
46 /* battery percentage */
47 char *
48 battery_perc(const char *battery)
49 {
50 int now, full, perc;
51 char batterynowfile[64] = "";
52 char batteryfullfile[64] = "";
53 FILE *fp;
54
55 /* generate battery nowfile path */
56 strcat(batterynowfile, batterypath);
57 strcat(batterynowfile, battery);
58 strcat(batterynowfile, "/");
59 strcat(batterynowfile, batterynow);
60
61 /* generate battery fullfile path */
62 strcat(batteryfullfile, batterypath);
63 strcat(batteryfullfile, battery);
64 strcat(batteryfullfile, "/");
65 strcat(batteryfullfile, batteryfull);
66
67 /* open battery now file */
68 if (!(fp = fopen(batterynowfile, "r"))) {
69 fprintf(stderr, "Error opening battery file.%s",batterynowfile);
70 return smprintf("n/a");
71 }
72
73 /* read value */
74 fscanf(fp, "%i", &now);
75
76 /* close battery now file */
77 fclose(fp);
78
79 /* open battery full file */
80 if (!(fp = fopen(batteryfullfile, "r"))) {
81 fprintf(stderr, "Error opening battery file.");
82 return smprintf("n/a");
83 }
84
85 /* read value */
86 fscanf(fp, "%i", &full);
87
88 /* close battery full file */
89 fclose(fp);
90
91 /* calculate percent */
92 perc = now / (full / 100);
93
94 /* return perc as string */
95 return smprintf("%d%%", perc);
96 }
97
98 /* cpu percentage */
99 char *
100 cpu_perc(const char *null)
101 {
102 int perc;
103 long double a[4], b[4];
104 FILE *fp;
105
106 /* open stat file */
107 if (!(fp = fopen("/proc/stat","r"))) {
108 fprintf(stderr, "Error opening stat file.");
109 return smprintf("n/a");
110 }
111
112 /* read values */
113 fscanf(fp, "%*s %Lf %Lf %Lf %Lf", &a[0], &a[1], &a[2], &a[3]);
114
115 /* close stat file */
116 fclose(fp);
117
118 /* wait a second (for avg values) */
119 sleep(1);
120
121 /* open stat file */
122 if (!(fp = fopen("/proc/stat","r"))) {
123 fprintf(stderr, "Error opening stat file.");
124 return smprintf("n/a");
125 }
126
127 /* read values */
128 fscanf(fp, "%*s %Lf %Lf %Lf %Lf", &b[0], &b[1], &b[2], &b[3]);
129
130 /* close stat file */
131 fclose(fp);
132
133 /* calculate avg in this second */
134 perc = 100 * ((b[0]+b[1]+b[2]) - (a[0]+a[1]+a[2])) / ((b[0]+b[1]+b[2]+b[3]) - (a[0]+a[1]+a[2]+a[3]));
135
136 /* return perc as string */
137 return smprintf("%d%%", perc);
138 }
139
140 /* date and time */
141 char *
142 datetime(const char *timeformat)
143 {
144 time_t tm;
145 size_t bufsize = 64;
146 char *buf = malloc(bufsize);
147
148 /* get time in format */
149 time(&tm);
150 setlocale(LC_TIME, "");
151 if(!strftime(buf, bufsize, timeformat, localtime(&tm))) {
152 setlocale(LC_TIME, "C");
153 fprintf(stderr, "Strftime failed.\n");
154 return smprintf("n/a");
155 }
156
157 setlocale(LC_TIME, "C");
158 /* return time */
159 char *ret = smprintf("%s", buf);
160 free(buf);
161 return ret;
162 }
163
164 /* disk usage percentage */
165 char *
166 disk_perc(const char *mountpoint)
167 {
168 int perc = 0;
169 struct statvfs fs;
170
171 /* try to open mountpoint */
172 if (statvfs(mountpoint, &fs) < 0) {
173 fprintf(stderr, "Could not get filesystem info.\n");
174 return smprintf("n/a");
175 }
176
177 /* calculate percent */
178 perc = 100 * (1.0f - ((float)fs.f_bavail / (float)fs.f_blocks));
179
180 /* return perc */
181 return smprintf("%d%%", perc);
182 }
183
184 /* entropy available */
185 char *
186 entropy(const char *null)
187 {
188 int entropy = 0;
189 FILE *fp;
190
191 /* open entropy file */
192 if (!(fp = fopen("/proc/sys/kernel/random/entropy_avail", "r"))) {
193 fprintf(stderr, "Could not open entropy file.\n");
194 return smprintf("n/a");
195 }
196
197 /* extract entropy */
198 fscanf(fp, "%d", &entropy);
199
200 /* close entropy file */
201 fclose(fp);
202
203 /* return entropy */
204 return smprintf("%d", entropy);
205 }
206
207 /* ram percentage */
208 char *
209 ram_perc(const char *null)
210 {
211 int perc;
212 long total, free, buffers, cached;
213 FILE *fp;
214
215 /* open meminfo file */
216 if (!(fp = fopen("/proc/meminfo", "r"))) {
217 fprintf(stderr, "Error opening meminfo file.");
218 return smprintf("n/a");
219 }
220
221 /* read the values */
222 fscanf(fp, "MemTotal: %ld kB\n", &total);
223 fscanf(fp, "MemFree: %ld kB\n", &free);
224 fscanf(fp, "MemAvailable: %ld kB\nBuffers: %ld kB\n", &buffers, &buffers);
225 fscanf(fp, "Cached: %ld kB\n", &cached);
226
227 /* close meminfo file */
228 fclose(fp);
229
230 /* calculate percentage */
231 perc = 100 * ((total - free) - (buffers + cached)) / total;
232
233 /* return perc as string */
234 return smprintf("%d%%", perc);
235 }
236
237 /* temperature */
238 char *
239 temp(const char *file)
240 {
241 int temperature;
242 FILE *fp;
243
244 /* open temperature file */
245 if (!(fp = fopen(file, "r"))) {
246 fprintf(stderr, "Could not open temperature file.\n");
247 return smprintf("n/a");
248 }
249
250 /* extract temperature */
251 fscanf(fp, "%d", &temperature);
252
253 /* close temperature file */
254 fclose(fp);
255
256 /* return temperature in degrees */
257 return smprintf("%d°C", temperature / 1000);
258 }
259
260
261 /* alsa volume percentage */
262 char *
263 vol_perc(const char *soundcard)
264 {
265 int mute = 0;
266 long vol = 0, max = 0, min = 0;
267
268 /* get volume from alsa */
269 snd_mixer_t *handle;
270 snd_mixer_elem_t *pcm_mixer, *mas_mixer;
271 snd_mixer_selem_id_t *vol_info, *mute_info;
272 snd_mixer_open(&handle, 0);
273 snd_mixer_attach(handle, soundcard);
274 snd_mixer_selem_register(handle, NULL, NULL);
275 snd_mixer_load(handle);
276 snd_mixer_selem_id_malloc(&vol_info);
277 snd_mixer_selem_id_malloc(&mute_info);
278 snd_mixer_selem_id_set_name(vol_info, channel);
279 snd_mixer_selem_id_set_name(mute_info, channel);
280 pcm_mixer = snd_mixer_find_selem(handle, vol_info);
281 mas_mixer = snd_mixer_find_selem(handle, mute_info);
282 snd_mixer_selem_get_playback_volume_range((snd_mixer_elem_t *)pcm_mixer, &min, &max);
283 snd_mixer_selem_get_playback_volume((snd_mixer_elem_t *)pcm_mixer, SND_MIXER_SCHN_MONO, &vol);
284 snd_mixer_selem_get_playback_switch(mas_mixer, SND_MIXER_SCHN_MONO, &mute);
285 if (vol_info)
286 snd_mixer_selem_id_free(vol_info);
287 if (mute_info)
288 snd_mixer_selem_id_free(mute_info);
289 if (handle)
290 snd_mixer_close(handle);
291
292 /* return the string (mute) */
293 if (!mute)
294 return smprintf("mute");
295 else
296 return smprintf("%d%%", (vol * 100) / max);
297 }
298
299 /* wifi percentage */
300 char *
301 wifi_perc(const char *wificard)
302 {
303 int bufsize = 255;
304 int strength;
305 char buf[bufsize];
306 char *datastart;
307 char path[64];
308 char status[5];
309 char needle[sizeof wificard + 1];
310 FILE *fp;
311
312 /* generate the path name */
313 memset(path, 0, sizeof path);
314 strcat(path, "/sys/class/net/");
315 strcat(path, wificard);
316 strcat(path, "/operstate");
317
318 /* open wifi file */
319 if(!(fp = fopen(path, "r"))) {
320 fprintf(stderr, "Error opening wifi operstate file.");
321 return smprintf("n/a");
322 }
323
324 /* read the status */
325 fgets(status, 5, fp);
326
327 /* close wifi file */
328 fclose(fp);
329
330 /* check if interface down */
331 if(strcmp(status, "up\n") != 0){
332 return smprintf("n/a");
333 }
334
335 /* open wifi file */
336 if (!(fp = fopen("/proc/net/wireless", "r"))) {
337 fprintf(stderr, "Error opening wireless file.");
338 return smprintf("n/a");
339 }
340
341 /* extract the signal strength */
342 strcpy(needle, wificard);
343 strcat(needle, ":");
344 fgets(buf, bufsize, fp);
345 fgets(buf, bufsize, fp);
346 fgets(buf, bufsize, fp);
347 if ((datastart = strstr(buf, needle)) != NULL) {
348 datastart = strstr(buf, ":");
349 sscanf(datastart + 1, " %*d %d %*d %*d %*d %*d %*d %*d %*d %*d", &strength);
350 }
351
352 /* close wifi file */
353 fclose(fp);
354
355 /* return strength in percent */
356 return smprintf("%d%%", strength);
357 }
358
359 /* main function */
360 int
361 main()
362 {
363 char status_string[1024];
364 struct arg argument;
365
366 /* try to open display */
367 if (!(dpy = XOpenDisplay(0x0))) {
368 fprintf(stderr, "Cannot open display!\n");
369 exit(1);
370 }
371
372 /* return status every interval */
373 for (;;) {
374 /* clear the string */
375 memset(status_string, 0, sizeof(status_string));
376
377 /* generate status_string */
378 for (size_t i = 0; i < sizeof(args) / sizeof(args[0]); ++i) {
379 argument = args[i];
380 char *res = argument.func(argument.args);
381 char *element = smprintf(argument.format, res);
382 strcat(status_string, element);
383 free(res);
384 free(element);
385 }
386
387 /* return the statusbar */
388 setstatus(status_string);
389
390 /* wait, "update_interval - 1" because of get_cpu_usage() which uses 1 second */
391 sleep(update_interval -1);
392 }
393
394 /* close display */
395 XCloseDisplay(dpy);
396
397 /* exit successfully */
398 return 0;
399 }