Created
April 9, 2012 14:17
-
-
Save c00kiemon5ter/2343738 to your computer and use it in GitHub Desktop.
mparser - a simple parser for monsterwm's output
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Makefile for mparser - see UNLICENSE for nonlicense and noncopyright information | |
VERSION = cookies-git | |
NAME = mparser | |
PREFIX ?= /usr/local | |
BINDIR ?= ${PREFIX}/bin | |
INCS = -I. -I/usr/include | |
LIBS = -L/usr/lib -lc | |
CFLAGS = -std=c99 -pedantic -Wall -Wextra -Os ${INCS} -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" | |
LDFLAGS = -s ${LIBS} | |
CC = cc | |
EXEC = ${NAME} | |
SRC = ${NAME}.c | |
OBJ = ${SRC:.c=.o} | |
all: options ${NAME} | |
options: | |
@echo ${NAME} build options: | |
@echo "CFLAGS = ${CFLAGS}" | |
@echo "LDFLAGS = ${LDFLAGS}" | |
@echo "CC = ${CC}" | |
.c.o: | |
@echo CC $< | |
@${CC} -c ${CFLAGS} $< | |
.o: | |
@echo CC -o $@ | |
@${CC} -o $@ $< ${LDFLAGS} | |
clean: | |
@echo cleaning | |
@rm -fv ${NAME} ${OBJ} ${NAME}-${VERSION}.tar.gz | |
install: all | |
@echo installing executable file to ${DESTDIR}${PREFIX}/bin | |
@install -Dm755 ${NAME} ${DESTDIR}${PREFIX}/bin/${NAME} | |
uninstall: | |
@echo removing executable file from ${DESTDIR}${PREFIX}/bin | |
@rm -f ${DESTDIR}${PREFIX}/bin/${NAME} | |
.PHONY: all options clean install uninstall |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* a parser for monsterwm output */ | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#include <unistd.h> | |
#include <limits.h> | |
#include <errno.h> | |
#include <err.h> | |
#include <regex.h> | |
#define URGENT "" | |
#define SEPARATOR "::" | |
#define DESKFMT "[ %s %d ] %s " | |
#define OUTFMT "&L%s &R%s\n" | |
static const char* commands[] = { | |
"statusbar", | |
"date +\"%F %R\"", | |
}; | |
static const char* desktops[] = { | |
"web", "dev", "foo", "irc", | |
}; | |
static const char* layouts[] = { | |
"[T]", /* tile */ | |
"[M]", /* monocle */ | |
"[B]", /* bstack */ | |
"[G]", /* grid */ | |
"[F]", /* fibonacci */ | |
}; | |
#define USAGE "usage: mparser [-h] /path/to/fifo" | |
#define FIFO "/tmp/monsterwm.fifo" | |
#define LENGTH(x) (sizeof(x)/sizeof(*x)) | |
#ifndef PATH_MAX | |
#define PATH_MAX 2048 | |
#endif | |
#ifndef LINE_MAX | |
#define LINE_MAX 1024 | |
#endif | |
int main(int argc, char *argv[]) { | |
char fifopath[PATH_MAX]; | |
int fifofd; | |
char *line = calloc(1, LINE_MAX); | |
int len = -1; | |
/* parse arguments */ | |
if (argc == 2) | |
if (strncmp(argv[1], "-h", 3) == 0) | |
errx(EXIT_SUCCESS, "%s", USAGE); | |
else | |
strncpy(fifopath, argv[1], sizeof(fifopath)); | |
else if (argc > 2) | |
errx(EXIT_FAILURE, "%s", USAGE); | |
else | |
strncpy(fifopath, FIFO, sizeof(fifopath)); | |
/* create and open fifo */ | |
//if (open(fifopath, O_RDONLY) != -1 && errno != ENOENT) | |
// unlink(fifopath); | |
if (mkfifo(fifopath, 0600) == -1 && errno != EEXIST) | |
err(EXIT_FAILURE, "cannot create fifo: %s", fifopath); | |
if ((fifofd = open(fifopath, O_RDONLY)) == -1) | |
err(EXIT_FAILURE, "cannot open fifo from path: %s", fifopath); | |
/* create regex to match line */ | |
regex_t re; | |
char *pattern = "^([0-9]+:[0-9]+:[0-9]+:[01]:[01] ?)+"; | |
if (regcomp(&re, pattern, REG_EXTENDED) != 0) | |
err(EXIT_FAILURE, "failed to compile pattern: %s", pattern); | |
/* wait for data */ | |
while ((len = read(fifofd, line, LINE_MAX)) >= 0) { | |
if (len == 0) { | |
close(fifofd); | |
if ((fifofd = open(fifopath, O_RDONLY)) == -1) | |
err(EXIT_FAILURE, "cannot open fifo from path: %s", fifopath); | |
continue; | |
} | |
/* check if line is valid -- weak regex here */ | |
if (regexec(&re, line, 0, NULL, 0) != 0) | |
goto clean; | |
/* parse line and format desktop info */ | |
int d, w, m, c, u; | |
char output[LINE_MAX], mode[128]; | |
for (char deskout[LINE_MAX], *desk = strtok(line, " "); | |
desk != NULL && sscanf(desk, "%d:%d:%d:%d:%d", &d, &w, &m, &c, &u) == 5; | |
desk = strtok(NULL, " ")) { | |
snprintf(deskout, sizeof(deskout), DESKFMT, desktops[d], w, SEPARATOR); | |
if (c) strncpy(mode, layouts[m], sizeof(mode)); | |
strncat(output, deskout, sizeof(output)); | |
} | |
/* run the commands and collect output */ | |
FILE *stream; | |
char cmdout[LINE_MAX]; | |
cmdout[0] = '\0'; | |
for (unsigned int cmd = 0; cmd < LENGTH(commands); cmd++) { | |
char *cmdline = NULL; | |
size_t len = 0; | |
if ((stream = popen(commands[cmd], "r")) == NULL) | |
warn("failed to execute command: %s", commands[cmd]); | |
if (getline(&cmdline, &len, stream) == -1) | |
warn("failed to get output for command: %s", commands[cmd]); | |
pclose(stream); | |
cmdline[strlen(cmdline) - 1] = '\0'; | |
strncat(cmdout, cmdline, sizeof(cmdout)); | |
free(cmdline); | |
} | |
/* print data */ | |
strncat(output, mode, sizeof(output)); | |
fprintf(stdout, OUTFMT, output, cmdout); | |
fflush(stdout); | |
/* clear buffer */ | |
clean: | |
memset(line, 0x00, sizeof(line)); | |
memset(output, 0x00, sizeof(output)); | |
memset(cmdout, 0x00, sizeof(cmdout)); | |
} | |
/* cleanup */ | |
regfree(&re); | |
free(line); | |
line = NULL; | |
close(fifofd); | |
/* all was good :] */ | |
return EXIT_SUCCESS; | |
} |
Author
c00kiemon5ter
commented
Apr 9, 2012
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment