summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS3
-rw-r--r--doc/coreutils.texi14
-rw-r--r--src/tee.c57
-rwxr-xr-xtests/misc/tee.sh26
4 files changed, 53 insertions, 47 deletions
diff --git a/NEWS b/NEWS
index 8aef1a672..1a5123574 100644
--- a/NEWS
+++ b/NEWS
@@ -58,7 +58,8 @@ GNU coreutils NEWS -*- outline -*-
sync no longer ignores arguments, and syncs each specified file, or with the
--file-system option, the file systems associated with each specified file.
- tee accepts a new --write-error option to control operation with pipes.
+ tee accepts a new --output-error option to control operation with pipes
+ and output errors in general.
** Changes in behavior
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index d3239a567..6110cecd0 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -13202,29 +13202,29 @@ them.
Ignore interrupt signals.
@item -p
-@itemx --write-error[=@var{mode}]
+@itemx --output-error[=@var{mode}]
@opindex -p
-@opindex --write-error
-Select the behavior with write errors on the outputs,
+@opindex --output-error
+Select the behavior with errors on the outputs,
where @var{mode} is one of the following:
@table @samp
@item warn
-Warn on error writing any output, including pipes.
+Warn on error opening or writing any output, including pipes.
Writing is continued to still open files/pipes.
Exit status indicates failure if any output has an error.
@item warn-nopipe
-Warn on error writing any output, except pipes.
+Warn on error opening or writing any output, except pipes.
Writing is continued to still open files/pipes.
Exit status indicates failure if any non pipe output had an error.
This is the default @var{mode} when not specified.
@item exit
-Exit on error writing any output, including pipes.
+Exit on error opening or writing any output, including pipes.
@item exit-nopipe
-Exit on error writing any output, except pipes.
+Exit on error opening or writing any output, except pipes.
@end table
@end table
diff --git a/src/tee.c b/src/tee.c
index c163184cb..3c39a4ab3 100644
--- a/src/tee.c
+++ b/src/tee.c
@@ -44,37 +44,37 @@ static bool append;
/* If true, ignore interrupts. */
static bool ignore_interrupts;
-enum write_error
+enum output_error
{
- write_error_sigpipe, /* traditional behavior, sigpipe enabled. */
- write_error_warn, /* warn on EPIPE, but continue. */
- write_error_warn_nopipe, /* ignore EPIPE, continue. */
- write_error_exit, /* exit on any write error. */
- write_error_exit_nopipe /* exit on any write error except EPIPE. */
+ output_error_sigpipe, /* traditional behavior, sigpipe enabled. */
+ output_error_warn, /* warn on EPIPE, but continue. */
+ output_error_warn_nopipe, /* ignore EPIPE, continue. */
+ output_error_exit, /* exit on any output error. */
+ output_error_exit_nopipe /* exit on any output error except EPIPE. */
};
-static enum write_error write_error;
+static enum output_error output_error;
static struct option const long_options[] =
{
{"append", no_argument, NULL, 'a'},
{"ignore-interrupts", no_argument, NULL, 'i'},
- {"write-error", optional_argument, NULL, 'p'},
+ {"output-error", optional_argument, NULL, 'p'},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
{NULL, 0, NULL, 0}
};
-static char const *const write_error_args[] =
+static char const *const output_error_args[] =
{
"warn", "warn-nopipe", "exit", "exit-nopipe", NULL
};
-static enum write_error const write_error_types[] =
+static enum output_error const output_error_types[] =
{
- write_error_warn, write_error_warn_nopipe,
- write_error_exit, write_error_exit_nopipe
+ output_error_warn, output_error_warn_nopipe,
+ output_error_exit, output_error_exit_nopipe
};
-ARGMATCH_VERIFY (write_error_args, write_error_types);
+ARGMATCH_VERIFY (output_error_args, output_error_types);
void
usage (int status)
@@ -91,7 +91,7 @@ Copy standard input to each FILE, and also to standard output.\n\
-i, --ignore-interrupts ignore interrupt signals\n\
"), stdout);
fputs (_("\
- -p, --write-error[=MODE] behavior on write error. See MODE details below\n\
+ -p, --output-error[=MODE] behavior on write error. See MODE details below\n\
"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
@@ -103,7 +103,7 @@ MODE determines behavior with write errors on the outputs:\n\
'exit' exit on error writing to any output\n\
'exit-nopipe' exit on error writing to any output not a pipe\n\
The default MODE for the -p option is 'warn-nopipe'.\n\
-The default operation when --write-error is not specified, is to\n\
+The default operation when --output-error is not specified, is to\n\
exit immediately on error writing to a pipe, and diagnose errors\n\
writing to non pipe outputs.\n\
"), stdout);
@@ -143,10 +143,10 @@ main (int argc, char **argv)
case 'p':
if (optarg)
- write_error = XARGMATCH ("--write-error", optarg, write_error_args,
- write_error_types);
+ output_error = XARGMATCH ("--output-error", optarg,
+ output_error_args, output_error_types);
else
- write_error = write_error_warn_nopipe;
+ output_error = output_error_warn_nopipe;
break;
case_GETOPT_HELP_CHAR;
@@ -161,7 +161,7 @@ main (int argc, char **argv)
if (ignore_interrupts)
signal (SIGINT, SIG_IGN);
- if (write_error != write_error_sigpipe)
+ if (output_error != output_error_sigpipe)
signal (SIGPIPE, SIG_IGN);
/* Do *not* warn if tee is given no file arguments.
@@ -184,7 +184,7 @@ tee_files (int nfiles, const char **files)
size_t n_outputs = 0;
FILE **descriptors;
char buffer[BUFSIZ];
- ssize_t bytes_read;
+ ssize_t bytes_read = 0;
int i;
bool ok = true;
char const *mode_string =
@@ -219,7 +219,9 @@ tee_files (int nfiles, const char **files)
descriptors[i] = fopen (files[i], mode_string);
if (descriptors[i] == NULL)
{
- error (0, errno, "%s", files[i]);
+ error (output_error == output_error_exit
+ || output_error == output_error_exit_nopipe,
+ errno, "%s", files[i]);
ok = false;
}
else
@@ -229,7 +231,7 @@ tee_files (int nfiles, const char **files)
}
}
- while (1)
+ while (n_outputs)
{
bytes_read = read (0, buffer, sizeof buffer);
if (bytes_read < 0 && errno == EINTR)
@@ -244,14 +246,14 @@ tee_files (int nfiles, const char **files)
&& fwrite (buffer, bytes_read, 1, descriptors[i]) != 1)
{
int w_errno = errno;
- bool fail = errno != EPIPE || (write_error == write_error_exit
- || write_error == write_error_warn);
+ bool fail = errno != EPIPE || (output_error == output_error_exit
+ || output_error == output_error_warn);
if (descriptors[i] == stdout)
clearerr (stdout); /* Avoid redundant close_stdout diagnostic. */
if (fail)
{
- error (write_error == write_error_exit
- || write_error == write_error_exit_nopipe,
+ error (output_error == output_error_exit
+ || output_error == output_error_exit_nopipe,
w_errno, "%s", files[i]);
}
descriptors[i] = NULL;
@@ -259,9 +261,6 @@ tee_files (int nfiles, const char **files)
ok = false;
n_outputs--;
}
-
- if (n_outputs == 0)
- break;
}
if (bytes_read == -1)
diff --git a/tests/misc/tee.sh b/tests/misc/tee.sh
index 84665cd00..f457a0b7a 100755
--- a/tests/misc/tee.sh
+++ b/tests/misc/tee.sh
@@ -64,7 +64,7 @@ if test -w /dev/full && test -c /dev/full; then
fi
-# Ensure tee honors --write-error modes
+# Ensure tee honors --output-error modes
mkfifo_or_skip_ fifo
read_fifo() { timeout 10 dd count=1 if=fifo of=/dev/null status=none & }
@@ -73,30 +73,36 @@ read_fifo
yes >fifo
pipe_status=$?
-# Default operation is to exit silently on SIGPIPE
+# Default operation is to continue on output errors but exit silently on SIGPIPE
read_fifo
-yes | returns_ $pipe_status timeout 10 tee 2>err >fifo || fail=1
-test $(wc -l < err) = 0 || { cat err; fail=1; }
+yes | returns_ $pipe_status timeout 10 tee ./e/noent 2>err >fifo || fail=1
+test $(wc -l < err) = 1 || { cat err; fail=1; }
# With -p, SIGPIPE is suppressed, exit 0 for EPIPE when all outputs finished
read_fifo
yes | timeout 10 tee -p 2>err >fifo || fail=1
test $(wc -l < err) = 0 || { cat err; fail=1; }
-# With --write-error=warn, exit 1 for EPIPE when all outputs finished
+# With --output-error=warn, exit 1 for EPIPE when all outputs finished
+read_fifo
+yes | returns_ 1 timeout 10 tee --output-error=warn 2>err >fifo || fail=1
+test $(wc -l < err) = 1 || { cat err; fail=1; }
+
+# With --output-error=exit, exit 1 immediately for EPIPE
read_fifo
-yes | returns_ 1 timeout 10 tee --write-error=warn 2>err >fifo || fail=1
+yes | returns_ 1 timeout 10 tee --output-error=exit /dev/null 2>err >fifo \
+ || fail=1
test $(wc -l < err) = 1 || { cat err; fail=1; }
-# With --write-error=exit, exit 1 immediately for EPIPE
+# With --output-error=exit, exit 1 immediately on output error
read_fifo
-yes | returns_ 1 timeout 10 tee --write-error=exit /dev/null 2>err >fifo \
+yes | returns_ 1 timeout 10 tee --output-error=exit ./e/noent 2>err >fifo \
|| fail=1
test $(wc -l < err) = 1 || { cat err; fail=1; }
-# With --write-error=exit-nopipe, exit 0 for EPIPE
+# With --output-error=exit-nopipe, exit 0 for EPIPE
read_fifo
-yes | timeout 10 tee --write-error=exit-nopipe 2>err >fifo || fail=1
+yes | timeout 10 tee --output-error=exit-nopipe 2>err >fifo || fail=1
test $(wc -l < err) = 0 || { cat err; fail=1; }
wait