diff options
Diffstat (limited to 'mstatus.c')
-rw-r--r-- | mstatus.c | 318 |
1 files changed, 0 insertions, 318 deletions
diff --git a/mstatus.c b/mstatus.c deleted file mode 100644 index 9e68eb3..0000000 --- a/mstatus.c +++ /dev/null @@ -1,318 +0,0 @@ -#define _GNU_SOURCE -#include <sys/types.h> -#include <sys/stat.h> - -#include <ctype.h> -#include <errno.h> -#include <linux/limits.h> -#include <paths.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdnoreturn.h> -#include <signal.h> -#include <string.h> -#include <syslog.h> -#include <unistd.h> - -#ifdef HAS_DWM - #include <X11/Xlib.h> -#endif - -#define CTOI(x) ((x) ^ 48) - -struct Block { - int pos; - char *text; - bool remove; -}; - -bool rflag; -const char *argv0; -struct { - char *str; - size_t len; -} seperator = {.str = " | ", .len = 3}; - -static noreturn void usage(void); -static noreturn void die(const char *); -static void *xrealloc(void *, size_t); -static void xfree(char **); -static void write_status(struct Block); -static bool process(char *, struct Block *); -static void create_fifo(char *); - -#ifdef HAS_DWM -static void daemonize(void); -static void xfork(void); -#endif - -void -usage(void) -{ - fprintf(stderr, "Usage: %s [-r] [-s seperator]\n", argv0); - exit(EXIT_FAILURE); -} - -void -die(const char *s) -{ - char *err = strerror(errno); - syslog(LOG_ERR, "%s: %s", s, err); - fprintf(stderr, "%s: %s: %s\n", argv0, s, err); - exit(EXIT_FAILURE); -} - -#ifdef HAS_DWM -void -xfork(void) -{ - pid_t pid = fork(); - if (pid == -1) - die("fork"); - if (pid != 0) - exit(EXIT_SUCCESS); -} -#endif - -void * -xrealloc(void *ptr, size_t size) -{ - void *ret; - if (!(ret = realloc(ptr, size))) - die("realloc"); - return ret; -} - -void -xfree(char **ptr) -{ - free(*ptr); - *ptr = NULL; -} - -void -write_status(struct Block b) -{ - static struct { - char **blocks; - int count; - size_t length; - } sb; - - if (b.remove) { - if (b.pos > sb.count) - return; - - /* b.remove && !b.pos is a special case to remove everything from the bar */ - if (!b.pos) { - for (int i = 0; i < sb.count; i++) - free(sb.blocks[i]); - sb.count = 0; - sb.blocks = xrealloc(sb.blocks, sizeof(char *)); - goto update_bar; - } - - /* If the block is not NULL we free it */ - if (sb.blocks[--b.pos]) { - sb.length -= strlen(sb.blocks[b.pos]); - xfree(&sb.blocks[b.pos]); - } - - /* If the block is the last one, we resize the bar to remove trailing NULL blocks */ - if (b.pos + 1 == sb.count) { - for (; !sb.blocks[b.pos] && b.pos; b.pos--) - sb.count--; - sb.blocks = xrealloc(sb.blocks, sizeof(char *) * ++b.pos); - } - goto update_bar; - } - - /* If the position exceeds the space allocated, allocate more blocks */ - if (b.pos > sb.count) { - sb.blocks = xrealloc(sb.blocks, sizeof(char *) * b.pos); - /* Make sure to set all the newly allocated blocks to NULL */ - for (int i = sb.count; i < b.pos; i++) - sb.blocks[i] = NULL; - sb.count = b.pos; - } - - /* If the block is NULL we dont need to bother with strlen and free */ - if (sb.blocks[--b.pos]) { - sb.length -= strlen(sb.blocks[b.pos]); - xfree(&sb.blocks[b.pos]); - } - if (!(sb.blocks[b.pos] = strdup(b.text))) - die("strdup"); - sb.length += strlen(b.text); - - /* The buffer to store the text that will be displayed in. It needs space for the text, the - * seperators between the different blocks, the NUL byte at the end, and the right padding - * space. - */ -update_bar:; - char buf[sb.length + (sb.count - 1) * seperator.len + 2]; - memset(buf, '\0', sizeof(buf)); - - /* Double loops so that the seperator isnt printed to the left of the first block */ - int i; - char *bufptr = buf; - for (i = 0; i < sb.count; i++) { - if (sb.blocks[i]) { - bufptr = stpcpy(buf, sb.blocks[i]); - break; - } - } - while (++i < sb.count) { - if (sb.blocks[i]) - bufptr = stpcpy(stpcpy(bufptr, seperator.str), sb.blocks[i]); - } - if (rflag) - strcat(buf, " "); - -#ifdef HAS_DWM - /* Xlib magic to set the DWM status */ - Display *dpy = XOpenDisplay(NULL); - int screen = DefaultScreen(dpy); - Window root = RootWindow(dpy, screen); - (void) XStoreName(dpy, root, buf); - (void) XCloseDisplay(dpy); -#else - puts(buf); -#endif -} - -bool -process(char *line, struct Block *b) -{ - if (*line == '-') { - b->remove = true; - line++; - } else - b->remove = false; - - if (!isdigit(*line)) - b->pos = 1; /* Default position */ - else { - b->pos = 0; - while (isdigit(*line)) - b->pos = b->pos * 10 + CTOI(*line++); - if (!b->pos && !b->remove) - return false; - } - - b->text = line; - return true; -} - -void -create_fifo(char *fifo_path) -{ - char *runtime_dir = getenv("XDG_RUNTIME_DIR"); - if (runtime_dir) { - size_t end = strlen(runtime_dir) - 1; - if (runtime_dir[end] == '/') - runtime_dir[end] = '\0'; - sprintf(fifo_path, "%s/%s.pipe", runtime_dir, argv0); - } else - sprintf(fifo_path, _PATH_VARRUN "user/%d/%s.pipe", getuid(), argv0); - - umask(0); - -create_fifo: - if (mkfifo(fifo_path, DEFFILEMODE) == -1) { - if (errno == EEXIST) { - if (unlink(fifo_path) == -1) - die("unlink"); - goto create_fifo; - } else - die("mkfifo"); - } - - syslog(LOG_INFO, "Created input FIFO '%s'", fifo_path); -} - -#ifdef HAS_DWM -void -daemonize(void) -{ - xfork(); - if (setsid() == -1) - die("setsid"); - - (void) signal(SIGCHLD, SIG_IGN); - xfork(); - - (void) chdir("/"); - (void) close(STDIN_FILENO); - (void) close(STDOUT_FILENO); - (void) close(STDERR_FILENO); - - stdin = fopen(_PATH_DEVNULL, "r"); - stdout = fopen(_PATH_DEVNULL, "w+"); - stderr = fopen(_PATH_DEVNULL, "w+"); - - syslog(LOG_INFO, "Daemonized '%s'", argv0); -} -#endif - -int -main(int argc, char **argv) -{ - argv0 = argv[0]; - - int opt; - while ((opt = getopt(argc, argv, ":rs:")) != -1) { - switch (opt) { - case 'r': - rflag = true; - break; - case 's': - seperator.str = optarg; - seperator.len = strlen(optarg); - break; - default: - usage(); - } - } - - openlog(argv0, LOG_PID | LOG_CONS, -#ifdef HAS_DWM - LOG_DAEMON -#else - LOG_USER -#endif - ); - char fifo_path[PATH_MAX]; - create_fifo(fifo_path); -#ifdef HAS_DWM - daemonize(); -#endif - - char *line = NULL; - size_t len = 0; - while (true) { - FILE *fp; - if (!(fp = fopen(fifo_path, "r"))) - die("fopen"); - - ssize_t nr; - while ((nr = getline(&line, &len, fp)) != -1) { - /* For some reason output with newlines can cause performance issues */ - if (line[--nr] == '\n') - line[nr] = '\0'; - - syslog(LOG_DEBUG, "Recieved command '%s'", line); - - struct Block b; - if (!process(line, &b)) - continue; - write_status(b); - } - if (ferror(fp)) - die("getline"); - - (void) fclose(fp); - } - /* NOTREACHED */ -} |