10f66f451Sopenharmony_ci/* tee.c - cat to multiple outputs.
20f66f451Sopenharmony_ci *
30f66f451Sopenharmony_ci * Copyright 2008 Rob Landley <rob@landley.net>
40f66f451Sopenharmony_ci *
50f66f451Sopenharmony_ci * See http://opengroup.org/onlinepubs/9699919799/utilities/tee.html
60f66f451Sopenharmony_ci
70f66f451Sopenharmony_ciUSE_TEE(NEWTOY(tee, "ia", TOYFLAG_USR|TOYFLAG_BIN))
80f66f451Sopenharmony_ci
90f66f451Sopenharmony_ciconfig TEE
100f66f451Sopenharmony_ci  bool "tee"
110f66f451Sopenharmony_ci  default y
120f66f451Sopenharmony_ci  help
130f66f451Sopenharmony_ci    usage: tee [-ai] [FILE...]
140f66f451Sopenharmony_ci
150f66f451Sopenharmony_ci    Copy stdin to each listed file, and also to stdout.
160f66f451Sopenharmony_ci    Filename "-" is a synonym for stdout.
170f66f451Sopenharmony_ci
180f66f451Sopenharmony_ci    -a	Append to files
190f66f451Sopenharmony_ci    -i	Ignore SIGINT
200f66f451Sopenharmony_ci*/
210f66f451Sopenharmony_ci
220f66f451Sopenharmony_ci#define FOR_tee
230f66f451Sopenharmony_ci#include "toys.h"
240f66f451Sopenharmony_ci
250f66f451Sopenharmony_ciGLOBALS(
260f66f451Sopenharmony_ci  void *outputs;
270f66f451Sopenharmony_ci  int out;
280f66f451Sopenharmony_ci)
290f66f451Sopenharmony_ci
300f66f451Sopenharmony_cistruct fd_list {
310f66f451Sopenharmony_ci  struct fd_list *next;
320f66f451Sopenharmony_ci  int fd;
330f66f451Sopenharmony_ci};
340f66f451Sopenharmony_ci
350f66f451Sopenharmony_ci// Open each output file, saving filehandles to a linked list.
360f66f451Sopenharmony_ci
370f66f451Sopenharmony_cistatic void do_tee_open(int fd, char *name)
380f66f451Sopenharmony_ci{
390f66f451Sopenharmony_ci  struct fd_list *temp;
400f66f451Sopenharmony_ci
410f66f451Sopenharmony_ci  temp = xmalloc(sizeof(struct fd_list));
420f66f451Sopenharmony_ci  temp->next = TT.outputs;
430f66f451Sopenharmony_ci  if (1 == (temp->fd = fd)) TT.out++;
440f66f451Sopenharmony_ci  TT.outputs = temp;
450f66f451Sopenharmony_ci}
460f66f451Sopenharmony_ci
470f66f451Sopenharmony_civoid tee_main(void)
480f66f451Sopenharmony_ci{
490f66f451Sopenharmony_ci  struct fd_list *fdl;
500f66f451Sopenharmony_ci  int len;
510f66f451Sopenharmony_ci
520f66f451Sopenharmony_ci  if (FLAG(i)) xsignal(SIGINT, SIG_IGN);
530f66f451Sopenharmony_ci
540f66f451Sopenharmony_ci  // Open output files (plus stdout if not already in output list)
550f66f451Sopenharmony_ci  loopfiles_rw(toys.optargs,
560f66f451Sopenharmony_ci    O_RDWR|O_CREAT|WARN_ONLY|(FLAG(a)?O_APPEND:O_TRUNC),
570f66f451Sopenharmony_ci    0666, do_tee_open);
580f66f451Sopenharmony_ci  if (!TT.out) do_tee_open(1, 0);
590f66f451Sopenharmony_ci
600f66f451Sopenharmony_ci  // Read data from stdin, write to each output file.
610f66f451Sopenharmony_ci  for (;;) {
620f66f451Sopenharmony_ci    if (1>(len = xread(0, toybuf, sizeof(toybuf)))) break;
630f66f451Sopenharmony_ci    for (fdl = TT.outputs; fdl;fdl = fdl->next)
640f66f451Sopenharmony_ci      if (len != writeall(fdl->fd, toybuf, len)) toys.exitval = 1;
650f66f451Sopenharmony_ci  }
660f66f451Sopenharmony_ci}
67