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