rework read/write fd code, sleep when there are too much timeouts - sob - simple output bar
 (HTM) git clone git://git.codemadness.org/sob
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 3bf4efd89a43d94ad46bdda31137a3bc9404ed8c
 (DIR) parent 32e1b3714fc4c84188673f668fca121b7c9e9256
 (HTM) 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:
         M sob.c                               |     114 +++++++++++++++++++++-----------
       
       1 file changed, 76 insertions(+), 38 deletions(-)
       ---
 (DIR) 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);
                                }
                        }
                }