#define _BSD_SOURCE #include #include #include #include #include #include #include #include #include #include #include #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; }