diff options
| author | Thomas Voss <mail@thomasvoss.com> | 2022-10-12 21:12:03 +0200 | 
|---|---|---|
| committer | Thomas Voss <mail@thomasvoss.com> | 2022-10-12 21:12:03 +0200 | 
| commit | 134c79f3d65928c18826f5ca2aae23130ed038cd (patch) | |
| tree | b1de0603e0a97858d0dea0f41948ec3f0b935576 | |
| parent | 4563949de32e17ab26e4f7d6307cd7521cedfcf9 (diff) | |
Prepare the switch to Go
| -rw-r--r-- | mstatus.1 | 130 | ||||
| -rw-r--r-- | mstatus.c | 318 | 
2 files changed, 0 insertions, 448 deletions
| diff --git a/mstatus.1 b/mstatus.1 deleted file mode 100644 index 672dba1..0000000 --- a/mstatus.1 +++ /dev/null @@ -1,130 +0,0 @@ -.\" vi: tw=80 -.\" -.\" BSD Zero Clause License -.\" -.\" Copyright (c) 2022 Thomas Voss -.\" -.\" Permission to use, copy, modify, and/or distribute this software for any -.\" purpose with or without fee is hereby granted. -.\" -.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -.\" AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -.\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -.\" OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -.\" PERFORMANCE OF THIS SOFTWARE. -.Dd $Mdocdate: September 23 2022 $ -.Dt MSTATUS 1 -.Os -.Sh NAME -.Nm mstatus -.Nd a modular status bar -.Sh SYNOPSIS -.Nm -.Op Fl r -.Op Fl s Ar seperator -.Sh DESCRIPTION -.Nm -is a modular status bar. -The -.Nm -status bar is comprised of a series of blocks which can be programmatically -added, removed, and updated. -These blocks appear side by side on the status bar seperated by the string -.Dq " | " , -although this can be configured with the -.Fl s -flag. -Commands are sent to and from the status bar via a named pipe located at -.Pa $XDG_RUNTIME_DIR/mstatus.pipe -or -.Pa /run/user/$(id -u)/mstatus.pipe -if the -.Ev $XDG_RUNTIME_DIR -environment variable is not set. -.Ss SYNTAX -The syntax used to send commands is extremely simple. -Every command sent follows the form -.Dq (\-?)([0-9]*)(.*) -or in other words, an optional -.Sq \- -followed by an optional unsigned integer, followed by an optional string. -Starting at the beginning, a leading -.Sq \- -tells -.Nm -that you would like to remove a block from the status bar. -If the command does not begin with a -.Sq \- -then -.Nm -will attempt to create/update a block instead. -.Pp -Next, you can optionally provide a number which represents the block you want -to act upon. -As an example, the command -.Dq \-10 -signals that you would like to remove block 10 from the status bar. -The command -.Dq 4 -on the other hand signals that you would like to create/update block 4. -If no block number is specified, then the specified action will be executed on -block 1. -It is important to note that the command -.Dq 0 -will be ignored as there is no block 0, however the command -.Dq \-0 -is special in that it deletes all the blocks from the status bar. -.Pp -Finally, after you have provided the optional -.Sq \- -flag and have selected the block to act upon, you can provide any string which -will be displayed in the selected block. -If the -.Sq \- -flag was specified then this string will be simply ignored. -.Sh OPTIONS -.Bl -tag -width Ds -.It Fl r -Add a single space of padding to the right of the status bar. -.It Fl s Ar seperator -Set the block seperator to the string specified by -.Ar seperator -as opposed to the default of -.Dq " | " . -.El -.Sh EXAMPLES -Display the current time in block 1, and the current date in block 2: -.Pp -.Dl "$ date \(aq+%H:%M\(aq >$XDG_RUNTIME_DIR/mstatus.pipe      # Note the implicit \(aq1\(aq" -.Dl "$ date \(aq+2%d/%m/%Y\(aq >$XDG_RUNTIME_DIR/mstatus.pipe  # Note the leading \(aq2\(aq" -.Pp -Delete the 5th block: -.Pp -.Dl $ echo \(aq-5\(aq >$XDG_RUNTIME_DIR/mstatus.pipe -.Pp -Replace the entire status bar with -.Dq Hello world! : -.Pp -.Dl $ printf \(aq-0\enHello world!\(aq >$XDG_RUNTIME_DIR/mstatus.pipe -.Sh EXIT STATUS -.Ex -std -.Sh NOTES -.Nm -always allocates enough memory to be able to hold as many blocks as the number -of the rightmost block. -This means that if you created a block in slots 1 and 2, memory will be -allocated for 2 blocks, however if you create a block in slots 1, 2, and 300, -then memory will be allocated for 300 blocks. -It is for this reason that you should avoid creating blocks in very high slots -without reason. -Luckily if deleting the block in slot 300 from the above example, the memory -for slots 3 to 300 will all be freed. -.Sh BUGS -As of the initial 1.0 version you cannot have a block which begins with a digit. -.Sh SEE ALSO -.Xr dwm 1 , -.Xr sway 1 -.Sh AUTHORS -.An Thomas Voss Aq Mt thomasvoss@live.com 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 */ -} |