Xinqi Bao's Git

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