commit
f026a2d0c1
@ -0,0 +1,21 @@ |
|||||||
|
CFLAGS = -Wall -Werror -pedantic -Ofast -std=c99
|
||||||
|
LDFLAGS = -L/usr/X11R6/lib -lX11
|
||||||
|
CC = gcc
|
||||||
|
PREFIX = /usr/local
|
||||||
|
MANPREFIX = ${PREFIX}/share/man
|
||||||
|
|
||||||
|
status: status.c |
||||||
|
|
||||||
|
debug: status.c |
||||||
|
${CC} ${LDFLAGS} -O0 -g -o stat_debug $?
|
||||||
|
|
||||||
|
install: status |
||||||
|
mkdir -p ${DESTDIR}${PREFIX}/bin
|
||||||
|
cp -f status ${DESTDIR}${PREFIX}/bin/status
|
||||||
|
chmod 755 ${DESTDIR}${PREFIX}/bin/status
|
||||||
|
|
||||||
|
uninstall: |
||||||
|
rm -f ${DESTDIR}${PREFIX}/bin/status
|
||||||
|
|
||||||
|
clean: |
||||||
|
rm -f status stat_debug
|
@ -0,0 +1,169 @@ |
|||||||
|
#define _POSIX_C_SOURCE 200809L |
||||||
|
#define _DEFAULT_SOURCE |
||||||
|
#include <stdio.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <time.h> |
||||||
|
#include <sys/types.h> |
||||||
|
#include <dirent.h> |
||||||
|
#include <stdarg.h> |
||||||
|
#include <string.h> |
||||||
|
#include <errno.h> |
||||||
|
#include <fcntl.h> |
||||||
|
#include <sys/stat.h> |
||||||
|
#include <unistd.h> |
||||||
|
#include <X11/Xlib.h> |
||||||
|
|
||||||
|
#define ELEMENT_NUMBER 2 |
||||||
|
#define CHARS 64 |
||||||
|
#define SEPARATOR " | " |
||||||
|
#define BAR_LENGTH (CHARS - (ELEMENT_NUMBER - 1) * sizeof(SEPARATOR)) |
||||||
|
#define ELEMENT_SIZE (BAR_LENGTH / ELEMENT_NUMBER) |
||||||
|
/* ANSI colors escape codes */ |
||||||
|
#define ANSI_COLOR_RED "\x1b[31m" |
||||||
|
#define ANSI_COLOR_GREEN "\x1b[32m" |
||||||
|
#define ANSI_COLOR_YELLOW "\x1b[33m" |
||||||
|
#define ANSI_COLOR_BLUE "\x1b[34m" |
||||||
|
#define ANSI_COLOR_MAGENTA "\x1b[35m" |
||||||
|
#define ANSI_COLOR_CYAN "\x1b[36m" |
||||||
|
#define ANSI_COLOR_RESET "\x1b[0m" |
||||||
|
|
||||||
|
const char bat_base_dir[] = "/sys/class/power_supply/"; |
||||||
|
|
||||||
|
struct battery_descriptor { |
||||||
|
int f_cap; /* Capacity file pointer */ |
||||||
|
int f_stat; /* Status file pointer */ |
||||||
|
}; |
||||||
|
|
||||||
|
static const char * get_date (void); |
||||||
|
static const char * get_battery (void); |
||||||
|
static void die (const char *, ...); |
||||||
|
|
||||||
|
int main (void) |
||||||
|
{ |
||||||
|
static int screen; |
||||||
|
static Display *dpy = NULL; |
||||||
|
static Window root; |
||||||
|
static char bar[BAR_LENGTH] = {0}; |
||||||
|
|
||||||
|
dpy = XOpenDisplay(NULL); |
||||||
|
if (!dpy) |
||||||
|
die("cannot open default display"); |
||||||
|
screen = DefaultScreen(dpy); |
||||||
|
root = RootWindow(dpy, screen); |
||||||
|
|
||||||
|
// TODO: do not use sleep instead poll file desciptors for a change
|
||||||
|
for (;;sleep(10)) { |
||||||
|
if (snprintf(bar, BAR_LENGTH, "%s" SEPARATOR "%s", get_battery(), get_date()) > BAR_LENGTH) |
||||||
|
bar[BAR_LENGTH - 1] = '\0'; |
||||||
|
|
||||||
|
XStoreName(dpy, root, bar); |
||||||
|
XSync(dpy, False); |
||||||
|
} |
||||||
|
|
||||||
|
XCloseDisplay(dpy); |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
static const char * get_date (void) |
||||||
|
{ |
||||||
|
static char str[ELEMENT_SIZE] = {0}; |
||||||
|
static time_t rawtime; |
||||||
|
time(&rawtime); |
||||||
|
strftime(str, ELEMENT_SIZE, "%a %d %b %H:%M", localtime(&rawtime)); |
||||||
|
return str; |
||||||
|
} |
||||||
|
|
||||||
|
static const char * get_battery (void) { |
||||||
|
static char str[ELEMENT_SIZE] = {0}; |
||||||
|
static int init = 1; |
||||||
|
static struct battery_descriptor *bat_arr = NULL; |
||||||
|
static int bat_num = 0; |
||||||
|
static char buf[sizeof(bat_base_dir) + 256 + 64]; |
||||||
|
|
||||||
|
if (init) { |
||||||
|
DIR *bdir; |
||||||
|
struct dirent *dent = NULL; |
||||||
|
int tmpf; |
||||||
|
|
||||||
|
if (!(bdir = opendir(bat_base_dir))) |
||||||
|
die("error opening %s", bat_base_dir); |
||||||
|
while (1) { |
||||||
|
errno = 0; |
||||||
|
if (!(dent = readdir(bdir))) { |
||||||
|
if (errno) |
||||||
|
die("error reading %s", bat_base_dir); |
||||||
|
else |
||||||
|
break; |
||||||
|
} |
||||||
|
/* if (dent->d_type != DT_DIR)
|
||||||
|
continue;*/ |
||||||
|
if (!strstr(dent->d_name, "BAT")) |
||||||
|
continue; |
||||||
|
|
||||||
|
bat_arr = realloc(bat_arr, sizeof(struct battery_descriptor) * ++bat_num); |
||||||
|
if(!bat_arr) |
||||||
|
die("bad realloc in get_battery"); |
||||||
|
|
||||||
|
strcpy(buf, bat_base_dir); |
||||||
|
strcat(buf, dent->d_name); |
||||||
|
strcat(buf, "/capacity"); |
||||||
|
if ((tmpf = open(buf, O_RDONLY | O_NONBLOCK)) < 0) |
||||||
|
die("error opening %s", buf); |
||||||
|
bat_arr[bat_num - 1].f_cap = tmpf; |
||||||
|
|
||||||
|
strcpy(buf, bat_base_dir); |
||||||
|
strcat(buf, dent->d_name); |
||||||
|
strcat(buf, "/status"); |
||||||
|
if ((tmpf = open(buf, O_RDONLY | O_NONBLOCK)) < 0) |
||||||
|
die("error opening %s", buf); |
||||||
|
bat_arr[bat_num - 1].f_stat = tmpf; |
||||||
|
} |
||||||
|
closedir(bdir); |
||||||
|
if (!bat_arr) |
||||||
|
die("no batteries were found"); |
||||||
|
init = 0; |
||||||
|
} |
||||||
|
memset(str, 0, ELEMENT_SIZE); |
||||||
|
int cap = 0; |
||||||
|
int level = 0; |
||||||
|
int barsize = 0; |
||||||
|
int charging = 0; |
||||||
|
for (int i = 0; i < bat_num; i++) { |
||||||
|
memset(buf, 0, sizeof(bat_base_dir) + 256 + 64); |
||||||
|
pread(bat_arr[i].f_cap, buf, 64, 0); |
||||||
|
cap = atoi(buf); |
||||||
|
barsize = (ELEMENT_SIZE / bat_num) - 5 - strlen(buf); |
||||||
|
level = (cap / 100.0) * barsize; |
||||||
|
pread(bat_arr[i].f_stat, buf, 64, 0); |
||||||
|
charging = strstr(buf, "Dis") ? 0 : 1; |
||||||
|
|
||||||
|
strcat(str, "["); |
||||||
|
for (int i = 0; i < level; i++) |
||||||
|
strcat(str, charging ? "+" : "="); |
||||||
|
for (int i = 0; i < barsize - level; i++) |
||||||
|
strcat(str, " "); |
||||||
|
snprintf(buf, 64, "] %d%%", cap); |
||||||
|
strcat(str, buf); |
||||||
|
} |
||||||
|
return str; |
||||||
|
} |
||||||
|
|
||||||
|
void die(const char *fmt, ...) |
||||||
|
{ |
||||||
|
va_list ap; |
||||||
|
va_start(ap, fmt); |
||||||
|
|
||||||
|
fputs(ANSI_COLOR_RED, stderr); |
||||||
|
vfprintf(stderr, fmt, ap); |
||||||
|
|
||||||
|
if (fmt[0] && fmt[strlen(fmt) - 1] == ':') { |
||||||
|
fputc(' ', stderr); |
||||||
|
perror(NULL); |
||||||
|
} else { |
||||||
|
fputc('\n', stderr); |
||||||
|
} |
||||||
|
fputs(ANSI_COLOR_RESET, stderr); |
||||||
|
|
||||||
|
va_end(ap); |
||||||
|
exit(errno ? errno : 1); |
||||||
|
} |
Loading…
Reference in new issue