• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
7 USE_TEE(NEWTOY(tee, "ia", TOYFLAG_USR|TOYFLAG_BIN))
8 
9 config 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 
25 GLOBALS(
26   void *outputs;
27   int out;
28 )
29 
30 struct fd_list {
31   struct fd_list *next;
32   int fd;
33 };
34 
35 // Open each output file, saving filehandles to a linked list.
36 
do_tee_open(int fd,char * name)37 static 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 
tee_main(void)47 void 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