diskspace_timechk.c - sites - public wiki contents of suckless.org
(HTM) git clone git://git.suckless.org/sites
(DIR) Log
(DIR) Files
(DIR) Refs
---
diskspace_timechk.c (7336B)
---
1 #define _BSD_SOURCE
2 #define _GNU_SOURCE
3 #include <unistd.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <stdarg.h>
7 #include <string.h>
8 #include <strings.h>
9 #include <sys/time.h>
10 #include <time.h>
11 #include <sys/types.h>
12 #include <dirent.h>
13 #include <sys/statvfs.h>
14
15 #include <X11/Xlib.h>
16
17 char *tzparis = "Europe/Paris";
18
19 static Display *dpy;
20
21 char *
22 smprintf(char *fmt, ...)
23 {
24 va_list fmtargs;
25 char *buf = NULL;
26
27 va_start(fmtargs, fmt);
28 if (vasprintf(&buf, fmt, fmtargs) == -1){
29 fprintf(stderr, "malloc vasprintf\n");
30 exit(1);
31 }
32 va_end(fmtargs);
33
34 return buf;
35 }
36
37 void
38 settz(char *tzname)
39 {
40 setenv("TZ", tzname, 1);
41 }
42
43 char *
44 mktimes(char *fmt, char *tzname)
45 {
46 char buf[129];
47 time_t tim;
48 struct tm *timtm;
49
50 memset(buf, 0, sizeof(buf));
51 settz(tzname);
52 tim = time(NULL);
53 timtm = localtime(&tim);
54 if (timtm == NULL) {
55 perror("localtime");
56 exit(1);
57 }
58
59 if (!strftime(buf, sizeof(buf)-1, fmt, timtm)) {
60 fprintf(stderr, "strftime == 0\n");
61 exit(1);
62 }
63
64 return smprintf(buf);
65 }
66
67 void
68 setstatus(char *str)
69 {
70 XStoreName(dpy, DefaultRootWindow(dpy), str);
71 XSync(dpy, False);
72 }
73
74 char *
75 loadavg(void)
76 {
77 double avgs[3];
78
79 if (getloadavg(avgs, 3) < 0) {
80 perror("getloadavg");
81 exit(1);
82 }
83
84 return smprintf("%.2f %.2f %.2f", avgs[0], avgs[1], avgs[2]);
85 }
86
87 char *
88 readfile(char *base, char *file)
89 {
90 char *path, line[513];
91 FILE *fd;
92
93 memset(line, 0, sizeof(line));
94
95 path = smprintf("%s/%s", base, file);
96 fd = fopen(path, "r");
97 if (fd == NULL)
98 return NULL;
99 free(path);
100
101 if (fgets(line, sizeof(line)-1, fd) == NULL)
102 return NULL;
103 fclose(fd);
104
105 return smprintf("%s", line);
106 }
107
108 /*
109 * Linux seems to change the filenames after suspend/hibernate
110 * according to a random scheme. So just check for both possibilities.
111 */
112 char *
113 getbattery(char *base)
114 {
115 char *co;
116 int descap, remcap;
117
118 descap = -1;
119 remcap = -1;
120
121 co = readfile(base, "present");
122 if (co == NULL || co[0] != '1') {
123 if (co != NULL) free(co);
124 return smprintf("?");
125 }
126 free(co);
127
128 co = readfile(base, "charge_full_design");
129 if (co == NULL) {
130 co = readfile(base, "energy_full_design");
131 if (co == NULL)
132 return smprintf("");
133 }
134 sscanf(co, "%d", &descap);
135 free(co);
136
137 co = readfile(base, "charge_now");
138 if (co == NULL) {
139 co = readfile(base, "energy_now");
140 if (co == NULL)
141 return smprintf("");
142 }
143 sscanf(co, "%d", &remcap);
144 free(co);
145
146 if (remcap < 0 || descap < 0)
147 return smprintf("invalid");
148
149 return smprintf("%.0f", ((float)remcap / (float)descap) * 100);
150 }
151
152 int
153 parse_netdev(unsigned long long int *receivedabs, unsigned long long int *sentabs)
154 {
155 char *buf;
156 char *eth0start;
157 static int bufsize;
158 FILE *devfd;
159
160 buf = (char *) calloc(255, 1);
161 bufsize = 255;
162 devfd = fopen("/proc/net/dev", "r");
163
164 // ignore the first two lines of the file
165 fgets(buf, bufsize, devfd);
166 fgets(buf, bufsize, devfd);
167
168 while (fgets(buf, bufsize, devfd)) {
169 if ((eth0start = strstr(buf, "wlan0:")) != NULL) {
170
171 // With thanks to the conky project at http://conky.sourceforge.net/
172 sscanf(eth0start + 6, "%llu %*d %*d %*d %*d %*d %*d %*d %llu",\
173 receivedabs, sentabs);
174 fclose(devfd);
175 free(buf);
176 return 0;
177 }
178 }
179 fclose(devfd);
180 free(buf);
181 return 1;
182 }
183
184 char *
185 get_netusage()
186 {
187 unsigned long long int oldrec, oldsent, newrec, newsent;
188 double downspeed, upspeed;
189 char *downspeedstr, *upspeedstr;
190 char *retstr;
191 int retval;
192
193 downspeedstr = (char *) malloc(15);
194 upspeedstr = (char *) malloc(15);
195 retstr = (char *) malloc(42);
196
197 retval = parse_netdev(&oldrec, &oldsent);
198 if (retval) {
199 fprintf(stdout, "Error when parsing /proc/net/dev file.\n");
200 exit(1);
201 }
202
203 sleep(1);
204 retval = parse_netdev(&newrec, &newsent);
205 if (retval) {
206 fprintf(stdout, "Error when parsing /proc/net/dev file.\n");
207 exit(1);
208 }
209
210 downspeed = (newrec - oldrec) / 1024.0;
211 if (downspeed > 1024.0) {
212 downspeed /= 1024.0;
213 sprintf(downspeedstr, "%.3f MB/s", downspeed);
214 } else {
215 sprintf(downspeedstr, "%.2f KB/s", downspeed);
216 }
217
218 upspeed = (newsent - oldsent) / 1024.0;
219 if (upspeed > 1024.0) {
220 upspeed /= 1024.0;
221 sprintf(upspeedstr, "%.3f MB/s", upspeed);
222 } else {
223 sprintf(upspeedstr, "%.2f KB/s", upspeed);
224 }
225 sprintf(retstr, "D: %s U: %s", downspeedstr, upspeedstr);
226
227 free(downspeedstr);
228 free(upspeedstr);
229 return retstr;
230 }
231
232 char *get_nmail(char *directory, char *label)
233 {
234 /* directory : Maildir path
235 * return label : number_of_new_mails
236 */
237
238 int n = 0;
239 DIR* dir = NULL;
240 struct dirent* rf = NULL;
241
242 dir = opendir(directory); /* try to open directory */
243 if (dir == NULL)
244 perror("");
245
246 while ((rf = readdir(dir)) != NULL) /*count number of file*/
247 {
248 if (strcmp(rf->d_name, ".") != 0 &&
249 strcmp(rf->d_name, "..") != 0)
250 n++;
251 }
252 closedir(dir);
253
254 if (n == 0)
255 return smprintf("");
256 else
257 return smprintf("%s%d",label, n);
258
259 }
260
261 int runevery(time_t *ltime, int sec){
262 /* return 1 if sec elapsed since last run
263 * else return 0
264 */
265 time_t now = time(NULL);
266
267 if ( difftime(now, *ltime ) >= sec)
268 {
269 *ltime = now;
270 return(1);
271 }
272 else
273 return(0);
274 }
275
276 char *get_freespace(char *mntpt){
277 struct statvfs data;
278 double total, used = 0;
279
280 if ( (statvfs(mntpt, &data)) < 0){
281 fprintf(stderr, "can't get info on disk.\n");
282 return("?");
283 }
284 total = (data.f_blocks * data.f_frsize);
285 used = (data.f_blocks - data.f_bfree) * data.f_frsize ;
286 return(smprintf("%.0f", (used/total*100)));
287 }
288
289 int
290 main(void)
291 {
292 char *status = NULL;
293 char *avgs = NULL;
294 char *tmprs = NULL;
295 char *bat = NULL;
296 char *netstats = NULL;
297 char *mail_laposte = NULL;
298 char *mail_fac = NULL;
299 char *mail_lavabit = NULL;
300 char *mail_tl = NULL;
301 char *rootfs = NULL;
302 char *homefs = NULL;
303 time_t count5min = 0;
304 time_t count60 = 0;
305
306 if (!(dpy = XOpenDisplay(NULL))) {
307 fprintf(stderr, "dwmstatus: cannot open display.\n");
308 return 1;
309 }
310
311 for (;;sleep(1)) {
312 /* checks every minutes */
313 if ( runevery(&count60, 60) )
314 {
315 free(tmprs);
316 free(bat);
317 free(rootfs);
318 free(homefs);
319 tmprs = mktimes("%d/%m/%y %H:%M", tzparis);
320 bat = getbattery("/sys/class/power_supply/BAT0/");
321 homefs = get_freespace("/home");
322 rootfs = get_freespace("/");
323 }
324 /* checks mail every 5 minutes */
325 if (runevery(&count5min, 300) )
326 {
327 free(mail_laposte);
328 free(mail_fac);
329 free(mail_lavabit);
330 free(mail_tl);
331 mail_laposte = get_nmail("/home/xavier/Maildir/fac/new", " Fac:");
332 mail_fac = get_nmail("/home/xavier/Maildir/lavabit/new", " Lavabit:");
333 mail_lavabit = get_nmail("/home/xavier/Maildir/toilelibre/new", " TL:");
334 mail_tl = get_nmail("/home/xavier/Maildir/laposte/new", " Laposte:");
335 }
336 /* checks every second */
337 avgs = loadavg();
338 netstats = get_netusage();
339
340 status = smprintf("%s%s%s%s | %s | /:%s% /home:%s% | B:%s% | %s | %s",
341 mail_tl, mail_fac, mail_lavabit, mail_laposte,
342 netstats, rootfs, homefs, bat, avgs, tmprs);
343 setstatus(status);
344 free(avgs);
345 free(netstats);
346 free(status);
347 }
348
349 XCloseDisplay(dpy);
350
351 return 0;
352 }
353