Home | History | Annotate | Download | only in posix
      1 /* tee.c - cat to multiple outputs.
      2  *
      3  * Copyright 2008 Rob Landley <rob (at) 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 )
     28 
     29 struct fd_list {
     30   struct fd_list *next;
     31   int fd;
     32 };
     33 
     34 // Open each output file, saving filehandles to a linked list.
     35 
     36 static void do_tee_open(int fd, char *name)
     37 {
     38   struct fd_list *temp;
     39 
     40   temp = xmalloc(sizeof(struct fd_list));
     41   temp->next = TT.outputs;
     42   temp->fd = fd;
     43   TT.outputs = temp;
     44 }
     45 
     46 void tee_main(void)
     47 {
     48   if (toys.optflags & FLAG_i) xsignal(SIGINT, SIG_IGN);
     49 
     50   // Open output files
     51   loopfiles_rw(toys.optargs,
     52     O_RDWR|O_CREAT|WARN_ONLY|((toys.optflags & FLAG_a)?O_APPEND:O_TRUNC),
     53     0666, do_tee_open);
     54 
     55   for (;;) {
     56     struct fd_list *fdl;
     57     int len;
     58 
     59     // Read data from stdin
     60     len = xread(0, toybuf, sizeof(toybuf));
     61     if (len<1) break;
     62 
     63     // Write data to each output file, plus stdout.
     64     fdl = TT.outputs;
     65     for (;;) {
     66       if(len != writeall(fdl ? fdl->fd : 1, toybuf, len)) toys.exitval=1;
     67       if (!fdl) break;
     68       fdl = fdl->next;
     69     }
     70   }
     71 }
     72