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