Created
March 20, 2017 16:52
-
-
Save syntactician/b20fb96306166a34be0c95e3816d06c6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _BSD_SOURCE | |
#include <unistd.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <stdarg.h> | |
#include <string.h> | |
#include <strings.h> | |
#include <sys/time.h> | |
#include <time.h> | |
#include <sys/types.h> | |
#include <sys/wait.h> | |
#include <X11/Xlib.h> | |
#define BASE "/sys/class/power_supply/BAT0" | |
static Display *dpy; | |
char * | |
smprintf(char *fmt, ...) | |
{ | |
va_list fmtargs; | |
char *ret; | |
int len; | |
va_start(fmtargs, fmt); | |
len = vsnprintf(NULL, 0, fmt, fmtargs); | |
va_end(fmtargs); | |
ret = malloc(++len); | |
if (ret == NULL) { | |
perror("malloc"); | |
exit(1); | |
} | |
va_start(fmtargs, fmt); | |
vsnprintf(ret, len, fmt, fmtargs); | |
va_end(fmtargs); | |
return ret; | |
} | |
char * | |
readfile(const char *base, const char *file) | |
{ | |
char *path, line[513]; | |
FILE *fd; | |
memset(line, 0, sizeof(line)); | |
path = smprintf("%s/%s", base, file); | |
fd = fopen(path, "r"); | |
if (fd == NULL) | |
return NULL; | |
free(path); | |
if (fgets(line, sizeof(line)-1, fd) == NULL) | |
return NULL; | |
fclose(fd); | |
return smprintf("%s", line); | |
} | |
char | |
statussymbol(const char *base) | |
{ | |
char *co; | |
co = readfile(base, "status"); | |
if (co == NULL) | |
return 'f'; | |
else if (!strncmp(co, "Charging", 8)) | |
return '+'; | |
else if (!strncmp(co, "Discharging", 11)) | |
return '-'; | |
else | |
return '='; | |
free(co); | |
} | |
/* | |
* Linux seems to change the filenames after suspend/hibernate | |
* according to a random scheme. So just check for both possibilities. | |
*/ | |
char * | |
getbattery(const char *base) | |
{ | |
char *co; | |
int descap, remcap; | |
descap = -1; | |
remcap = -1; | |
co = readfile(base, "present"); | |
if (co == NULL || co[0] != '1') { | |
if (co != NULL) free(co); | |
return smprintf("not present"); | |
} | |
free(co); | |
co = readfile(base, "charge_full"); | |
if (co == NULL) { | |
co = readfile(base, "energy_full"); | |
if (co == NULL) | |
return smprintf(""); | |
} | |
sscanf(co, "%d", &descap); | |
free(co); | |
co = readfile(base, "charge_now"); | |
if (co == NULL) { | |
co = readfile(base, "energy_now"); | |
if (co == NULL) | |
return smprintf(""); | |
} | |
sscanf(co, "%d", &remcap); | |
free(co); | |
if (remcap < 0 || descap < 0) | |
return smprintf("invalid"); | |
return smprintf("%.0f%c", | |
((float)remcap / (float)descap) * 100, | |
statussymbol(base)); | |
} | |
char * | |
mktimes(char *fmt) | |
{ | |
char buf[129]; | |
time_t tim; | |
struct tm *timtm; | |
memset(buf, 0, sizeof(buf)); | |
tim = time(NULL); | |
timtm = localtime(&tim); | |
if (timtm == NULL) { | |
perror("localtime"); | |
exit(1); | |
} | |
if (!strftime(buf, sizeof(buf)-1, fmt, timtm)) { | |
fprintf(stderr, "strftime == 0\n"); | |
exit(1); | |
} | |
return smprintf("%s", buf); | |
} | |
void | |
setstatus(char *str) | |
{ | |
XStoreName(dpy, DefaultRootWindow(dpy), str); | |
XSync(dpy, False); | |
} | |
int | |
main(void) | |
{ | |
char *batt; | |
char *stat; | |
char *time; | |
if (!(dpy = XOpenDisplay(NULL))) { | |
fprintf(stderr, "dwmstatus: cannot open display.\n"); | |
return 1; | |
} | |
for (;;sleep(90)) { | |
batt = getbattery(BASE); | |
time = mktimes("%a %d %b %H:%M"); | |
stat = smprintf("%s %s", time, batt); | |
setstatus(stat); | |
free(batt); | |
free(stat); | |
free(time); | |
} | |
XCloseDisplay(dpy); | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment