toybox/toys/posix/tee.c
<<
>>
Prefs
   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