#define _GNU_SOURCE #include #include #include #include #include #include #include #ifndef PRINT #include #endif /* PRINT */ int stop = 0; #ifdef BATTERY char *readfile(char *buf, size_t len, const char *fn) { FILE *f; size_t n; f = fopen(fn, "r"); if (!f) { return NULL; } n = fread(buf, 1, len-1, f); if (ferror(f)) { return NULL; } fclose(f); if (n >= len-1 || n < 1) { return NULL; } buf[n] = '\0'; return buf; } int getnum(const char *fn) { char buf[1024]; if (readfile(buf, sizeof(buf), fn)) { return atoi(buf); } return -1; } #ifdef CHARGING int charging(void) { char buf[1024]; if (readfile(buf, sizeof(buf), STATUS)) { return !strcmp(buf, CHARGING); } return 0; } #endif /* CHARGING */ #endif /* BATTERY */ void handler(int sig) { stop = sig; } int main(void) { #ifdef EXACT_SLEEP struct timespec ts; #endif /* EXACT_SLEEP */ struct tm *tm; time_t now; #ifdef BATTERY long long ccur, cmax, ca=-1, cb=-1, i; #ifdef POWER long long pcur, pa=-1, pb=-1; char name[8 + 6 + 9]; /* bbb.bb% pp.pW hh:mm:ss\0 */ char *bat = name; char *power = name + 8; char *clock = name + 8 + 6; #else /* POWER */ char name[8 + 9]; /* bbb.bb% hh:mm:ss\0 */ char *bat = name; char *clock = name + 8; #endif /* POWER */ char sign = '%'; #else /* BATTERY */ char name[9]; /* hh:mm:ss\0 */ char *clock = name; #endif /* BATTERY */ struct sigaction act; #ifndef PRINT Display *disp; int screen; Window root; char *origname = NULL; #endif /* !PRINT */ act.sa_handler = handler; act.sa_flags = 0; sigemptyset(&act.sa_mask); sigaction(SIGHUP, &act, NULL); sigaction(SIGINT, &act, NULL); sigaction(SIGQUIT, &act, NULL); sigaction(SIGTERM, &act, NULL); #ifndef PRINT if (!(disp = XOpenDisplay(NULL))) { return EXIT_FAILURE; } screen = DefaultScreen(disp); if (!(root = RootWindow(disp, screen))) { return EXIT_FAILURE; } XFetchName(disp, root, &origname); fclose(stdout); fclose(stderr); #endif /* !PRINT */ fclose(stdin); #ifdef BATTERY for (i=0; !stop; ++i) { #else /* BATTERY */ while (!stop) { #endif /* BATTERY */ #ifdef BATTERY if (i % (BAT_REFRESH_SECONDS) == 0) { ccur = getnum(ENERGY_NOW) * MUL; cmax = getnum(ENERGY_FULL); #ifdef CHARGING sign = charging() ? '+' : '%'; #endif /* CHARGING */ if (ccur < 0 || cmax < 1) { ca = cb = -1; } else { ca = ccur * 10000 / cmax; cb = ca % 100; ca /= 100; } #ifdef POWER #ifdef POWER_NOW pcur = getnum(POWER_NOW); #elif defined(CURRENT_NOW) && defined(VOLTAGE_NOW) /* POWER_NOW */ pcur = (long long)getnum(CURRENT_NOW) * (long long)getnum(VOLTAGE_NOW) / 1000000; #else /* POWER_NOW */ #error "Either POWER_NOW or CURRENT_NOW and VOLTAGE_NOW must be defined" #endif /* POWER_NOW*/ if (pcur < 0) { pa = pb = -1; } else { pa = pcur / 100000; pb = pa % 10; pa /= 10; } #endif /* POWER */ } if (ca < 0 || cb < 0) { snprintf(bat, 8, "NO BAT "); } else if (ca < 0 || ca > 999999 || cb < 0 || cb > 99) { snprintf(bat, 8, "INVALID"); } else if (ca > 999) { snprintf(bat, 8, "%6lld%c", ca, sign); } else { snprintf(bat, 8, "%3lld.%02lld%c", ca, cb, sign); } bat[7] = ' '; #ifdef POWER if (pa < 0 || pb < 0) { snprintf(power, 6, "NOPOW"); } else if (pa < 0 || pa > 9999 || pb < 0 || pb > 9) { snprintf(power, 6, "????W"); } else if (pa > 99) { snprintf(power, 6, "%4lldW", pa); } else { snprintf(power, 6, "%2lld.%01lldW", pa, (unsigned long long)pb); } power[5] = ' '; #endif /* POWER */ #endif /* BATTERY */ #ifdef EXACT_SLEEP clock_gettime(CLOCK_REALTIME, &ts); now = ts.tv_sec; #else /* EXACT_SLEEP */ now = time(NULL); #endif /* EXACT_SLEEP */ tm = localtime(&now); strftime(clock, 9, "%H:%M:%S", tm); #ifdef PRINT printf("%s\n", name); fflush(stdout); #else /* PRINT */ XStoreName(disp, root, name); XFlush(disp); #endif /* PRINT */ #ifdef EXACT_SLEEP ts.tv_sec = 0; ts.tv_nsec = 1000000000 - ts.tv_nsec; nanosleep(&ts, NULL); #else /* EXACT_SLEEP */ sleep(1); #endif /* EXACT_SLEEP */ } #ifndef PRINT if (origname) { XStoreName(disp, root, origname); } XCloseDisplay(disp); #endif /* !PRINT */ return EXIT_SUCCESS; }