aboutsummaryrefslogtreecommitdiff
path: root/toys/tee.c
blob: 8c8f3d5c36cb8a62a2e8c1f8b4a0a9734b511894 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/* vi: set sw=4 ts=4:
 *
 * tee.c - cat to multiple outputs.
 *
 * Copyright 2008 Rob Landley <rob@landley.net>
 *
 * See http://www.opengroup.org/onlinepubs/009695399/utilities/tee.html

USE_TEE(NEWTOY(tee, "ia", TOYFLAG_BIN))

config TEE
    bool "tee"
    default y
    help
      usage: tee [-ai] [file...]

      Copy stdin to each listed file, and also to stdout.
      Filename "-" is a synonym for stdout.

      -a	append to files.
      -i	ignore SIGINT.
*/

#include "toys.h"

DEFINE_GLOBALS(
    void *outputs;
)

#define TT this.tee

struct fd_list {
    struct fd_list *next;
    int fd;
};

// Open each output file, saving filehandles to a linked list.

static void do_tee_open(int fd, char *name)
{
    struct fd_list *temp;

    temp = xmalloc(sizeof(struct fd_list));
    temp->next = TT.outputs;
    temp->fd = fd;
    TT.outputs = temp;
}

void tee_main(void)
{
    if (toys.optflags&2) signal(SIGINT, SIG_IGN);

    // Open output files
    loopfiles_rw(toys.optargs,
        O_RDWR|O_CREAT|((toys.optflags&1)?O_APPEND:O_TRUNC), do_tee_open);

    for (;;) {
        struct fd_list *fdl;
        int len;

        // Read data from stdin
        len = xread(0, toybuf, sizeof(toybuf));
        if (len<1) break;

        // Write data to each output file, plus stdout.
        fdl = TT.outputs;
        for (;;) {
            if(len != writeall(fdl ? fdl->fd : 1, toybuf, len)) toys.exitval=1;
            if (!fdl) break;
            fdl = fdl->next;
        }
    }

}