truncate: always set mode when opening file to avoid fortify errors
[oweals/busybox.git] / coreutils / tee.c
index 13fb4a3c18735abb2b12675abc200e5a28e8b84e..48cc0508fced0d498a6b09fadcd54fa14adf4836 100644 (file)
@@ -4,14 +4,25 @@
  *
  * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
  *
- * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  */
 
 /* BB_AUDIT SUSv3 compliant */
 /* http://www.opengroup.org/onlinepubs/007904975/utilities/tee.html */
 
+//usage:#define tee_trivial_usage
+//usage:       "[-ai] [FILE]..."
+//usage:#define tee_full_usage "\n\n"
+//usage:       "Copy stdin to each FILE, and also to stdout\n"
+//usage:     "\n       -a      Append to the given FILEs, don't overwrite"
+//usage:     "\n       -i      Ignore interrupt signals (SIGINT)"
+//usage:
+//usage:#define tee_example_usage
+//usage:       "$ echo \"Hello\" | tee /tmp/foo\n"
+//usage:       "$ cat /tmp/foo\n"
+//usage:       "Hello\n"
+
 #include "libbb.h"
-#include <signal.h>
 
 int tee_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int tee_main(int argc, char **argv)
@@ -36,28 +47,33 @@ int tee_main(int argc, char **argv)
        mode += (retval & 2);   /* Since 'a' is the 2nd option... */
 
        if (retval & 1) {
-               signal(SIGINT, SIG_IGN); /* TODO - switch to sigaction. */
+               signal(SIGINT, SIG_IGN); /* TODO - switch to sigaction. (why?) */
        }
        retval = EXIT_SUCCESS;
        /* gnu tee ignores SIGPIPE in case one of the output files is a pipe
         * that doesn't consume all its input.  Good idea... */
-       signal(SIGPIPE, SIG_IGN);       /* TODO - switch to sigaction. */
+       signal(SIGPIPE, SIG_IGN);
 
-       /* Allocate an array of FILE *'s, with one extra for a sentinal. */
+       /* Allocate an array of FILE *'s, with one extra for a sentinel. */
        fp = files = xzalloc(sizeof(FILE *) * (argc + 2));
        np = names = argv - 1;
 
        files[0] = stdout;
        goto GOT_NEW_FILE;
        do {
-               *fp = fopen_or_warn(*argv, mode);
-               if (*fp == NULL) {
-                       retval = EXIT_FAILURE;
-                       continue;
+               *fp = stdout;
+               if (NOT_LONE_DASH(*argv)) {
+                       *fp = fopen_or_warn(*argv, mode);
+                       if (*fp == NULL) {
+                               retval = EXIT_FAILURE;
+                               argv++;
+                               continue;
+                       }
                }
                *np = *argv++;
  GOT_NEW_FILE:
-               setbuf(*fp++, NULL);    /* tee must not buffer output. */
+               setbuf(*fp, NULL);      /* tee must not buffer output. */
+               fp++;
                np++;
        } while (*argv);
        /* names[0] will be filled later */
@@ -66,8 +82,8 @@ int tee_main(int argc, char **argv)
        while ((c = safe_read(STDIN_FILENO, buf, sizeof(buf))) > 0) {
                fp = files;
                do
-                       fwrite(buf, 1, c, *fp++);
-               while (*fp);
+                       fwrite(buf, 1, c, *fp);
+               while (*++fp);
        }
        if (c < 0) {            /* Make sure read errors are signaled. */
                retval = EXIT_FAILURE;
@@ -77,8 +93,8 @@ int tee_main(int argc, char **argv)
        while ((c = getchar()) != EOF) {
                fp = files;
                do
-                       putc(c, *fp++);
-               while (*fp);
+                       putc(c, *fp);
+               while (*++fp);
        }
 #endif