sob

Simple output bar
git clone https://git.sinitax.com/codemadness/sob
Log | Files | Refs | README | LICENSE | Upstream | sfeed.txt

commit 3bf4efd89a43d94ad46bdda31137a3bc9404ed8c
parent 32e1b3714fc4c84188673f668fca121b7c9e9256
Author: Hiltjo Posthuma <hiltjo@codemadness.org>
Date:   Fri, 24 Oct 2014 21:35:06 +0000

rework read/write fd code, sleep when there are too much timeouts

Diffstat:
Msob.c | 114+++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
1 file changed, 76 insertions(+), 38 deletions(-)

diff --git a/sob.c b/sob.c @@ -11,6 +11,7 @@ #include <sys/select.h> #include <unistd.h> #include <termios.h> +#include <time.h> #include <wchar.h> #include "arg.h" @@ -60,8 +61,8 @@ static int line_promptlen(void); static int line_pipeto(char **); static int line_wordpipeto(char **); -static int pipe_readline(int, int, char *, - void (*)(const char *, size_t, size_t)); +static int pipe_read(int, int, char *, + void (*)(const char *, size_t, size_t)); static int pipe_cmd(char *[], char *, void (*)(const char *, size_t, size_t)); @@ -75,6 +76,9 @@ static void setup(void); static void sighandler(int); static void usage(void); +static int readfd(int, char *, size_t); +static int writefd(int, char *, size_t); + static size_t colw(const char *, size_t); static int nonspace(int c); static size_t utf8len(const char *); @@ -547,7 +551,47 @@ line_copywordcursor(char *buf, size_t bufsiz) } static int -pipe_readline(int fd_in, int fd_out, char *writestr, +readfd(int fd, char *buf, size_t len) { + size_t r, i = 0; + + while(len > 0) { + if((r = read(fd, &buf[i], len)) == -1) { + if(errno == EINTR) + continue; + if(errno == EWOULDBLOCK) + return i; + return -1; + } else if(r == 0) { + return i; + } + i += r; + len -= r; + } + return i; +} + +static int +writefd(int fd, char *buf, size_t len) { + size_t w, i = 0; + + while(len > 0) { + if((w = write(fd, &buf[i], len)) == -1) { + if(errno == EINTR) + continue; + if(errno == EWOULDBLOCK) + return i; + return -1; + } else if(w == 0) { + return i; + } + i += w; + len -= w; + } + return i; +} + +static int +pipe_read(int fd_in, int fd_out, char *writestr, void (*f)(const char *, size_t, size_t)) { char buf[PIPE_BUF]; @@ -576,35 +620,28 @@ pipe_readline(int fd_in, int fd_out, char *writestr, else if(!r) /* timeout */ continue; - if(haswritten) { - if(FD_ISSET(fd_in, &fdr)) { - while(1) { - if((r = read(fd_in, buf, sizeof(buf))) == -1) { - if(errno == EINTR) - continue; - goto fini; - } else { - buf[r] = '\0'; - total += r; - if(f) - f(buf, r, total); - if(!r) { - status = 0; - goto fini; - } - } - } - } - } else { - if(FD_ISSET(fd_out, &fdw)) { - /* write error */ - if((w = write(fd_out, writestr, strlen(writestr))) == -1) + if(FD_ISSET(fd_in, &fdr) && haswritten) { + while(1) { + if((r = readfd(fd_in, buf, sizeof(buf))) <= 0) goto fini; - close(fd_out); /* sends EOF */ - fd_out = -1; - haswritten = 1; + if(!r) { + status = 0; + goto fini; + } + if(f) { + buf[r] = '\0'; + total += r; + f(buf, r, total); + } } } + if(FD_ISSET(fd_out, &fdw)) { + if((w = writefd(fd_out, writestr, strlen(writestr))) == -1) + goto fini; + close(fd_out); /* sends EOF */ + fd_out = -1; + haswritten = 1; + } } fini: if(fd_in != -1) @@ -656,7 +693,7 @@ pipe_cmd(char *cmd[], char *writestr, void (*f)(const char *, size_t, size_t)) sa.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sa, NULL); - if(pipe_readline(cp[0], pc[1], writestr, f) == -1) + if(pipe_read(cp[0], pc[1], writestr, f) == -1) return -1; } return 0; @@ -812,6 +849,7 @@ static int run(void) { struct timeval tv; + struct timespec ts; fd_set fdr; int r, status = -1; unsigned char buf[BUFSIZ]; @@ -828,22 +866,22 @@ run(void) tv.tv_sec = 0; tv.tv_usec = 32000; /* 32 ms */ - errno = 0; if((r = select(STDIN_FILENO + 1, &fdr, NULL, NULL, &tv)) == -1) { if(errno != EINTR) - goto fini; /* E_INTR can happen on SIGWINCH */ + goto fini; /* E_INTR can happen on a signal like SIGWINCH */ } else if(!r) { continue; /* timeout */ } - if(FD_ISSET(STDIN_FILENO, &fdr)) { - errno = 0; - if((r = read(STDIN_FILENO, buf, sizeof(buf))) == -1) { - if(errno != EAGAIN && errno != EWOULDBLOCK) - goto fini; - } else if(r > 0) { + if((r = readfd(STDIN_FILENO, (char *)buf, sizeof(buf))) == -1) + goto fini; + if(r > 0) { buf[r] = '\0'; handleinput(buf, r); + } else if(r == 0) { + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * 1000; + nanosleep(&ts, NULL); } } }