URI:
       Add blind-tee - blind - suckless command-line video editing utility
  HTML git clone git://git.suckless.org/blind
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit d5f9bf804180f50d1a025b3cf70e12238c79cfb3
   DIR parent e55c9ce583efdd740da7458812d3253d9f4895ae
  HTML Author: Mattias Andrée <maandree@kth.se>
       Date:   Thu, 25 May 2017 19:16:08 +0200
       
       Add blind-tee
       
       Signed-off-by: Mattias Andrée <maandree@kth.se>
       
       Diffstat:
         M Makefile                            |       1 +
         M README                              |       3 +++
         M man/blind-from-named.1              |       2 +-
         A man/blind-tee.1                     |      28 ++++++++++++++++++++++++++++
         M man/blind-to-named.1                |       2 +-
         M man/blind.7                         |       5 +++++
         A src/blind-tee.c                     |      52 +++++++++++++++++++++++++++++++
       
       7 files changed, 91 insertions(+), 2 deletions(-)
       ---
   DIR diff --git a/Makefile b/Makefile
       @@ -35,6 +35,7 @@ BIN =\
                blind-skip-pattern\
                blind-split\
                blind-stack\
       +        blind-tee\
                blind-time-blur\
                blind-to-image\
                blind-to-named\
   DIR diff --git a/README b/README
       @@ -114,6 +114,9 @@ UTILITIES
               blind-stack(1)
                      Overlay videos
        
       +       blind-tee(1)
       +              /dev/fd/ aware tee(1) implementation
       +
               blind-time-blur(1)
                      Draw new frames on top of old frames with partial alpha
        
   DIR diff --git a/man/blind-from-named.1 b/man/blind-from-named.1
       @@ -58,7 +58,7 @@ input to the process, like inverse multiplexing.
        .SH SEE ALSO
        .BR blind (7),
        .BR blind-to-named (1),
       -.BR tee (1)
       +.BR blind-tee (1)
        .SH AUTHORS
        Mattias Andrée
        .RI < maandree@kth.se >
   DIR diff --git a/man/blind-tee.1 b/man/blind-tee.1
       @@ -0,0 +1,28 @@
       +.TH BLIND-TEE 1 blind
       +.SH NAME
       +blind-tee - /dev/fd/ aware tee(1) implementation
       +.SH SYNOPSIS
       +.B blind-tee
       +.RI [ file \ ...]
       +.SH DESCRIPTION
       +.B blind-tee
       +reads stdin and writes its input to stdout and to all
       +.IR file s.
       +.P
       +Files are opened in truncate mode, file descriptors
       +specified via their /dev/fd/ path are not reopened
       +but used directly.
       +.SH RATIONALE
       +There are situations where opening files in /dev/fd/
       +creates problems. Popular
       +.BR tee (1),
       +implementations do not treat files in /dev/fd/
       +especially.
       +.SH SEE ALSO
       +.BR blind (7),
       +.BR blind-to-named (1),
       +.BR blind-from-named (1),
       +.BR tee (1)
       +.SH AUTHORS
       +Mattias Andrée
       +.RI < maandree@kth.se >
   DIR diff --git a/man/blind-to-named.1 b/man/blind-to-named.1
       @@ -33,7 +33,7 @@ input to the process, like inverse multiplexing.
        .SH SEE ALSO
        .BR blind (7),
        .BR blind-from-named (1),
       -.BR tee (1)
       +.BR blind-tee (1)
        .SH AUTHORS
        Mattias Andrée
        .RI < maandree@kth.se >
   DIR diff --git a/man/blind.7 b/man/blind.7
       @@ -127,6 +127,11 @@ Split a video, by frame, into multiple videos
        .BR blind-stack (1)
        Overlay videos
        .TP
       +.BR blind-tee (1)
       +/dev/fd/ aware
       +.BR tee (1)
       +implementation
       +.TP
        .BR blind-time-blur (1)
        Draw new frames on top of old frames with partial alpha
        .TP
   DIR diff --git a/src/blind-tee.c b/src/blind-tee.c
       @@ -0,0 +1,52 @@
       +/* See LICENSE file for copyright and license details. */
       +#include "common.h"
       +
       +USAGE("[file ...]")
       +
       +#if !defined(PIPE_BUF)
       +# define PIPE_BUF BUFSIZ
       +#endif
       +
       +int
       +main(int argc, char *argv[])
       +{
       +        char buf[PIPE_BUF];
       +        int *fds = alloca(argc * sizeof(*fds));
       +        size_t i, n = 0, done;
       +        ssize_t r, w, *ps;
       +
       +        UNOFLAGS(0);
       +
       +        fds[n++] = STDOUT_FILENO;
       +        while (argc--)
       +                fds[n++] = eopen(*argv++, O_WRONLY | O_CREAT | O_TRUNC, 0666);
       +
       +        ps = alloca(n * sizeof(*ps));
       +
       +        while (n) {
       +                memset(ps, 0, n * sizeof(*ps));
       +                r = read(STDIN_FILENO, buf, sizeof(buf));
       +                if (r < 0)
       +                        eprintf("read <stdin>:");
       +                if (!r)
       +                        break;
       +                for (done = 0; done < n;) {
       +                        for (i = 0; i < n; i++) {
       +                                if (ps[i] == r)
       +                                        continue;
       +                                w = write(fds[i], buf + ps[i], r - ps[i]);
       +                                if (w < 0) {
       +                                        close(fds[i]);
       +                                        n--;
       +                                        memmove(fds + i, fds + i + 1, (n - i) * sizeof(*fds));
       +                                        memmove(ps  + i, ps  + i + 1, (n - i) * sizeof(*ps));
       +                                }
       +                                ps[i] += w;
       +                                if (ps[i] == r)
       +                                        done++;
       +                        }
       +                }
       +        }
       +
       +        return 0;
       +}