Skip to content

Instantly share code, notes, and snippets.

@syntactician
Created March 20, 2017 16:52
Show Gist options
  • Save syntactician/b20fb96306166a34be0c95e3816d06c6 to your computer and use it in GitHub Desktop.
Save syntactician/b20fb96306166a34be0c95e3816d06c6 to your computer and use it in GitHub Desktop.
#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