wmsl

Block-based window manager status line
git clone https://git.sinitax.com/sinitax/wmsl
Log | Files | Refs | README | LICENSE | sfeed.txt

commit 4b2f75f2a045a29d02f15985a2180fd86b1e4810
parent 65f9404a4938904bb2971987ba1a89ebb1dae4bf
Author: Louis Burda <quent.burda@gmail.com>
Date:   Fri,  1 Jul 2022 21:26:45 +0200

Fixed read for long lines

Diffstat:
Mwmsl.c | 199++++++++++++++++++++++++++++++++++++++++++-------------------------------------
1 file changed, 106 insertions(+), 93 deletions(-)

diff --git a/wmsl.c b/wmsl.c @@ -10,6 +10,7 @@ #include <stdbool.h> #include <stdlib.h> #include <stdio.h> +#include <stdint.h> #define ARRSIZE(x) (sizeof(x)/sizeof(x[0])) #define OUTPUTMAX 256 @@ -28,16 +29,6 @@ struct block { char output[OUTPUTMAX]; }; -static void die(const char *fmtstr, ...); -static void signal_handler(int sig, siginfo_t *info, void *context); -static void concat_status(const char *text, size_t len); -static void update_blocks(void); -static void sleep_till_next(void); -static float get_elapsed(void); -static void set_status_var(const char *str); -static void clean_status(void); -static void debug(const char *fmtstr, ...); - static const char *usage = "USAGE: wmsl [-h] [-v]\n"; static const char *pid_file = "/tmp/.wmsl.pid"; @@ -64,6 +55,43 @@ die(const char *fmtstr, ...) } void +set_status_var(const char *str) +{ + XStoreName(dpy, root, str); + XFlush(dpy); +} + +void +clean_status(int sig) +{ + set_status_var(""); + exit(0); +} + +void +debug(const char *fmtstr, ...) +{ + char buf[12]; + struct tm *tm; + time_t sec; + va_list ap; + int len; + + if (!verbose) + return; + + time(&sec); + tm = localtime(&sec); + + strftime(buf, sizeof(buf), "[%T] ", tm); + fprintf(stderr, "%s", buf); + + va_start(ap, fmtstr); + vfprintf(stderr, fmtstr, ap); + va_end(ap); +} + +void signal_handler(int sig, siginfo_t *info, void *context) { int i, block_id; @@ -96,55 +124,75 @@ concat_status(const char *text, size_t len) int run_block(const char *cmd, pid_t *pid) { - int input[2]; + int output[2]; - if (pipe(input) == -1) + if (pipe(output) == -1) err(EXIT_FAILURE, "pipe"); *pid = fork(); if (*pid < 0) err(EXIT_FAILURE, "fork"); if (*pid != 0) { - close(input[0]); + close(output[1]); } else { - dup2(input[0], 0); - close(input[0]); - close(input[1]); close(0); close(1); - exit(system(cmd)); + dup2(output[1], 1); + close(output[0]); + close(output[1]); + signal(SIGINT, NULL); + signal(SIGTERM, NULL); + execl("/bin/sh", "sh", "-c", cmd, NULL); + abort(); } - return input[1]; + return output[0]; } bool -read_statusline(int fd, char *buf, size_t size) +read_block(int fd, char *buf, ssize_t size) { struct timeval timeout; + struct timespec start, stop; fd_set fdset; int ret, nread; + uint64_t ns; char *tok; - FD_ZERO(&fdset); - FD_SET(fd, &fdset); + clock_gettime(CLOCK_REALTIME, &start); + + ns = 0; + do { + FD_ZERO(&fdset); + FD_SET(fd, &fdset); - timeout.tv_sec = 1; - timeout.tv_usec = 0; + timeout.tv_sec = 0; + timeout.tv_usec = (1000000000 - ns) / 1000; - ret = select(fd + 1, &fdset, NULL, NULL, &timeout); - if (ret <= 0) return false; + ret = select(fd + 1, &fdset, NULL, NULL, &timeout); + if (ret <= 0) break; - nread = read(fd, buf, size); - if (!nread) return false; + clock_gettime(CLOCK_REALTIME, &stop); - if (!(tok = strchr(buf, '\n'))) - return false; - *tok = '\0'; + ns = (stop.tv_sec - start.tv_sec) * 1000000000; + ns += stop.tv_nsec - start.tv_nsec; - return true; + nread = read(fd, buf, size); + if (nread <= 0) break; + + if ((tok = memchr(buf, '\n', nread))) { + *tok = '\0'; + return true; + } + + buf += nread; + size -= nread; + } while (ns < 1000000000); + + return false; } + void update_blocks(void) { @@ -156,9 +204,10 @@ update_blocks(void) memcpy(status_text, prefix, ARRSIZE(prefix) - 1); - /* construct status string */ concat_status(prefix, ARRSIZE(prefix) - 1); - for (status_len = update = i = 0; i < ARRSIZE(blocks); i++) { + + update = false; + for (status_len = i = 0; i < ARRSIZE(blocks); i++) { if ((blocks[i].flags & READY) || blocks[i].sleep_max && blocks[i].sleep_left <= 0.2) { blocks[i].sleep_left = blocks[i].sleep_max; @@ -167,10 +216,11 @@ update_blocks(void) /* get command output */ fd = run_block(blocks[i].command, &child); - if (!read_statusline(fd, tmp_output, OUTPUTMAX)) { - output_len = 0; - } else { + memset(tmp_output, 0, sizeof(tmp_output)); + if (read_block(fd, tmp_output, sizeof(tmp_output) -1)) { output_len = strlen(tmp_output); + } else { + output_len = 0; } if (output_len != strlen(blocks[i].output) @@ -178,7 +228,7 @@ update_blocks(void) memcpy(blocks[i].output, tmp_output, output_len); blocks[i].output[output_len] = '\0'; debug("new output from cmd: %s\n", blocks[i].command); - update = 1; + update = true; } kill(child, SIGKILL); @@ -200,32 +250,6 @@ update_blocks(void) set_status_var(status_text); } -void -sleep_till_next(void) -{ - int i, minsleep; - - last_sleep = 0; /* reset last_sleep in case we return early */ - for (i = 0, minsleep = 0; i < ARRSIZE(blocks); i++) { - if ((blocks[i].flags & READY) || - blocks[i].sleep_max && blocks[i].sleep_left <= 0) - return; - if (!minsleep || blocks[i].sleep_max && blocks[i].sleep_left < minsleep) - minsleep = ceil(blocks[i].sleep_left); - } - - if (minsleep < 1) - minsleep = 1; - - debug("sleeping for %i seconds\n", minsleep); - - alarm(minsleep); - pause(); - - last_sleep = get_elapsed(); - debug("slept for %f seconds\n", last_sleep); -} - float get_elapsed(void) { @@ -247,39 +271,29 @@ get_elapsed(void) } void -set_status_var(const char *str) -{ - XStoreName(dpy, root, str); - XFlush(dpy); -} - -void -clean_status(void) +sleep_till_next(void) { - set_status_var(""); -} + int i, minsleep; -void -debug(const char *fmtstr, ...) -{ - char buf[12]; - struct tm *tm; - time_t sec; - va_list ap; - int len; + last_sleep = 0; /* reset last_sleep in case we return early */ + for (i = 0, minsleep = 0; i < ARRSIZE(blocks); i++) { + if ((blocks[i].flags & READY) || + blocks[i].sleep_max && blocks[i].sleep_left <= 0) + return; + if (!minsleep || blocks[i].sleep_max && blocks[i].sleep_left < minsleep) + minsleep = ceil(blocks[i].sleep_left); + } - if (!verbose) - return; + if (minsleep < 1) + minsleep = 1; - time(&sec); - tm = localtime(&sec); + debug("sleeping for %i seconds\n", minsleep); - strftime(buf, sizeof(buf), "[%T] ", tm); - printf("%s", buf); + alarm(minsleep); + pause(); - va_start(ap, fmtstr); - vprintf(fmtstr, ap); - va_end(ap); + last_sleep = get_elapsed(); + debug("slept for %f seconds\n", last_sleep); } int @@ -317,9 +331,8 @@ main(int argc, const char **argv) if (sigaction(SIGALRM, &sa, NULL) == -1) die("wmsl: Failed to setup signal handler (SIGALRM)\n"); - atexit(clean_status); - signal(SIGINT, exit); - signal(SIGTERM, exit); + signal(SIGINT, clean_status); + signal(SIGTERM, clean_status); /* save pid */ pid = getpid();