tee.c 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  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. USE_TEE(NEWTOY(tee, "ia", TOYFLAG_USR|TOYFLAG_BIN))
  7. config TEE
  8. bool "tee"
  9. default y
  10. help
  11. usage: tee [-ai] [FILE...]
  12. Copy stdin to each listed file, and also to stdout.
  13. Filename "-" is a synonym for stdout.
  14. -a Append to files
  15. -i Ignore SIGINT
  16. */
  17. #define FOR_tee
  18. #include "toys.h"
  19. GLOBALS(
  20. void *outputs;
  21. int out;
  22. )
  23. struct fd_list {
  24. struct fd_list *next;
  25. int fd;
  26. };
  27. // Open each output file, saving filehandles to a linked list.
  28. static void do_tee_open(int fd, char *name)
  29. {
  30. struct fd_list *temp;
  31. temp = xmalloc(sizeof(struct fd_list));
  32. temp->next = TT.outputs;
  33. if (1 == (temp->fd = fd)) TT.out++;
  34. TT.outputs = temp;
  35. }
  36. void tee_main(void)
  37. {
  38. struct fd_list *fdl;
  39. int len;
  40. if (FLAG(i)) xsignal(SIGINT, SIG_IGN);
  41. // Open output files (plus stdout if not already in output list)
  42. loopfiles_rw(toys.optargs,
  43. O_RDWR|O_CREAT|WARN_ONLY|(FLAG(a)?O_APPEND:O_TRUNC),
  44. 0666, do_tee_open);
  45. if (!TT.out) do_tee_open(1, 0);
  46. // Read data from stdin, write to each output file.
  47. for (;;) {
  48. if (1>(len = xread(0, toybuf, sizeof(toybuf)))) break;
  49. for (fdl = TT.outputs; fdl;fdl = fdl->next)
  50. if (len != writeall(fdl->fd, toybuf, len)) toys.exitval = 1;
  51. }
  52. }