xref: /third_party/toybox/toys/posix/tee.c (revision 0f66f451)
1/* tee.c - cat to multiple outputs.
2 *
3 * Copyright 2008 Rob Landley <rob@landley.net>
4 *
5 * See http://opengroup.org/onlinepubs/9699919799/utilities/tee.html
6
7USE_TEE(NEWTOY(tee, "ia", TOYFLAG_USR|TOYFLAG_BIN))
8
9config TEE
10  bool "tee"
11  default y
12  help
13    usage: tee [-ai] [FILE...]
14
15    Copy stdin to each listed file, and also to stdout.
16    Filename "-" is a synonym for stdout.
17
18    -a	Append to files
19    -i	Ignore SIGINT
20*/
21
22#define FOR_tee
23#include "toys.h"
24
25GLOBALS(
26  void *outputs;
27  int out;
28)
29
30struct fd_list {
31  struct fd_list *next;
32  int fd;
33};
34
35// Open each output file, saving filehandles to a linked list.
36
37static void do_tee_open(int fd, char *name)
38{
39  struct fd_list *temp;
40
41  temp = xmalloc(sizeof(struct fd_list));
42  temp->next = TT.outputs;
43  if (1 == (temp->fd = fd)) TT.out++;
44  TT.outputs = temp;
45}
46
47void tee_main(void)
48{
49  struct fd_list *fdl;
50  int len;
51
52  if (FLAG(i)) xsignal(SIGINT, SIG_IGN);
53
54  // Open output files (plus stdout if not already in output list)
55  loopfiles_rw(toys.optargs,
56    O_RDWR|O_CREAT|WARN_ONLY|(FLAG(a)?O_APPEND:O_TRUNC),
57    0666, do_tee_open);
58  if (!TT.out) do_tee_open(1, 0);
59
60  // Read data from stdin, write to each output file.
61  for (;;) {
62    if (1>(len = xread(0, toybuf, sizeof(toybuf)))) break;
63    for (fdl = TT.outputs; fdl;fdl = fdl->next)
64      if (len != writeall(fdl->fd, toybuf, len)) toys.exitval = 1;
65  }
66}
67