summaryrefslogtreecommitdiff
path: root/src/seq.c
diff options
context:
space:
mode:
authorAssaf Gordon <assafgordon@gmail.com>2016-04-17 02:28:13 -0400
committerAssaf Gordon <assafgordon@gmail.com>2016-04-24 18:19:50 -0400
commitc92585b10b29ce2c31c69cea52e69ef053c9679f (patch)
treeff733fa4b684abfa59dd5a7b3d56f411c9027fee /src/seq.c
parent8c8163838aa5589f5dfe2c94dcc48f0ab443fd35 (diff)
downloadcoreutils-c92585b10b29ce2c31c69cea52e69ef053c9679f.tar.xz
seq: detect and report I/O errors immediately
Ensure I/O errors are detected (and terminate seq), preventing seq from infloop (or running for long time with a large range) upon write errors or ignored SIGPIPE. Examples: seq 1 inf > /dev/full (seq_fast) seq 1.1 0.1 inf >/dev/full (print_numbers) * src/seq.c (io_error): A new function to diagnose appropriate stdio errors and exit the program with failure status. (seq_fast, print_numbers): Explicitly check for write errors and terminate the program with diagnostic. * tests/misc/seq-io-errors.sh: Test error detection with /dev/full. * tests/misc/seq-epipe.sh: Test error detection with broken pipes. * tests/local.mk: Add new tests. * NEWS: Mention the fix.
Diffstat (limited to 'src/seq.c')
-rw-r--r--src/seq.c24
1 files changed, 19 insertions, 5 deletions
diff --git a/src/seq.c b/src/seq.c
index de92bc278..1b9da40fb 100644
--- a/src/seq.c
+++ b/src/seq.c
@@ -278,6 +278,15 @@ long_double_format (char const *fmt, struct layout *layout)
}
}
+static void ATTRIBUTE_NORETURN
+io_error (void)
+{
+ /* FIXME: consider option to silently ignore errno=EPIPE */
+ error (0, errno, _("standard output"));
+ clearerr (stdout);
+ exit (EXIT_FAILURE);
+}
+
/* Actually print the sequence of numbers in the specified range, with the
given or default stepping and format. */
@@ -295,7 +304,8 @@ print_numbers (char const *fmt, struct layout layout,
for (i = 1; ; i++)
{
long double x0 = x;
- printf (fmt, x);
+ if (printf (fmt, x) < 0)
+ io_error ();
if (out_of_range)
break;
x = first + i * step;
@@ -336,10 +346,12 @@ print_numbers (char const *fmt, struct layout layout,
break;
}
- fputs (separator, stdout);
+ if (fputs (separator, stdout) == EOF)
+ io_error ();
}
- fputs (terminator, stdout);
+ if (fputs (terminator, stdout) == EOF)
+ io_error ();
}
}
@@ -506,14 +518,16 @@ seq_fast (char const *a, char const *b)
output buffer so far, and reset to start of buffer. */
if (buf_end - (p_len + 1) < bufp)
{
- fwrite (buf, bufp - buf, 1, stdout);
+ if (fwrite (buf, bufp - buf, 1, stdout) != 1)
+ io_error ();
bufp = buf;
}
}
/* Write any remaining buffered output, and the terminator. */
*bufp++ = *terminator;
- fwrite (buf, bufp - buf, 1, stdout);
+ if (fwrite (buf, bufp - buf, 1, stdout) != 1)
+ io_error ();
IF_LINT (free (buf));
}