aboutsummaryrefslogtreecommitdiff
path: root/toys/posix/tee.c
blob: 88f73618c3218e12db7ecaffd5fee7d843ddf8a0 (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
/* tee.c - cat to multiple outputs.
 *
 * Copyright 2008 Rob Landley <rob@landley.net>
 *
 * See http://opengroup.org/onlinepubs/9699919799/utilities/tee.html

USE_TEE(NEWTOY(tee, "ia", TOYFLAG_USR|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
*/

#define FOR_tee
#include "toys.h"

GLOBALS(
  void *outputs;
  int out;
)

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;
  if (1 == (temp->fd = fd)) TT.out++;
  TT.outputs = temp;
}

void tee_main(void)
{
  struct fd_list *fdl;
  int len;

  if (FLAG(i)) xsignal(SIGINT, SIG_IGN);

  // Open output files (plus stdout if not already in output list)
  loopfiles_rw(toys.optargs,
    O_RDWR|O_CREAT|WARN_ONLY|(FLAG(a)?O_APPEND:O_TRUNC),
    0666, do_tee_open);
  if (!TT.out) do_tee_open(1, 0);

  // Read data from stdin, write to each output file.
  for (;;) {
    if (1>(len = xread(0, toybuf, sizeof(toybuf)))) break;
    for (fdl = TT.outputs; fdl;fdl = fdl->next)
      if (len != writeall(fdl->fd, toybuf, len)) toys.exitval = 1;
  }
}