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:
M | wmsl.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();