diff options
author | Ron Yorston <rmy@pobox.com> | 2018-03-06 14:08:23 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2018-03-06 14:08:23 +0000 |
commit | 922dba2a9a00c35abb19c5dba01169e7335ce23b (patch) | |
tree | 7152daf82d775da4fc588ce81e435730a9eb30dd /win32 | |
parent | c44b18ace0b3e020e594f4d4ab2c9a1211ec90ab (diff) | |
download | busybox-w32-922dba2a9a00c35abb19c5dba01169e7335ce23b.tar.gz busybox-w32-922dba2a9a00c35abb19c5dba01169e7335ce23b.tar.bz2 busybox-w32-922dba2a9a00c35abb19c5dba01169e7335ce23b.zip |
winansi: check for broken pipe
Microsoft Windows doesn't support SIGPIPE and its support for the
EPIPE error is somewhat inadequate. Most of the time a broken pipe
leads to an EINVAL error which is misleading:
$ yes hello | head -1
hello
yes: Invalid argument
Add a function to test for the underlying Windows error that indicates
a broken pipe and set errno to EPIPE. Call this function in a few
strategic places.
Diffstat (limited to 'win32')
-rw-r--r-- | win32/winansi.c | 35 |
1 files changed, 29 insertions, 6 deletions
diff --git a/win32/winansi.c b/win32/winansi.c index 8e583e0ce..256ef4fa9 100644 --- a/win32/winansi.c +++ b/win32/winansi.c | |||
@@ -475,16 +475,31 @@ int winansi_puts(const char *s) | |||
475 | return (winansi_fputs(s, stdout) == EOF || putchar('\n') == EOF) ? EOF : 0; | 475 | return (winansi_fputs(s, stdout) == EOF || putchar('\n') == EOF) ? EOF : 0; |
476 | } | 476 | } |
477 | 477 | ||
478 | static void check_pipe(FILE *stream) | ||
479 | { | ||
480 | if (GetLastError() == ERROR_NO_DATA && ferror(stream)) { | ||
481 | int fd = fileno(stream); | ||
482 | if (fd != -1 && | ||
483 | GetFileType((HANDLE)_get_osfhandle(fd)) == FILE_TYPE_PIPE) { | ||
484 | errno = EPIPE; | ||
485 | } | ||
486 | } | ||
487 | } | ||
488 | |||
478 | size_t winansi_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) | 489 | size_t winansi_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) |
479 | { | 490 | { |
480 | size_t lsize, lmemb; | 491 | size_t lsize, lmemb, ret; |
481 | char *str; | 492 | char *str; |
482 | int rv; | 493 | int rv; |
483 | 494 | ||
484 | lsize = MIN(size, nmemb); | 495 | lsize = MIN(size, nmemb); |
485 | lmemb = MAX(size, nmemb); | 496 | lmemb = MAX(size, nmemb); |
486 | if (lsize != 1 || !is_console(fileno(stream))) | 497 | if (lsize != 1 || !is_console(fileno(stream))) { |
487 | return fwrite(ptr, size, nmemb, stream); | 498 | SetLastError(0); |
499 | if ((ret=fwrite(ptr, size, nmemb, stream)) < nmemb) | ||
500 | check_pipe(stream); | ||
501 | return ret; | ||
502 | } | ||
488 | 503 | ||
489 | str = xmalloc(lmemb+1); | 504 | str = xmalloc(lmemb+1); |
490 | memcpy(str, ptr, lmemb); | 505 | memcpy(str, ptr, lmemb); |
@@ -498,8 +513,14 @@ size_t winansi_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) | |||
498 | 513 | ||
499 | int winansi_fputs(const char *str, FILE *stream) | 514 | int winansi_fputs(const char *str, FILE *stream) |
500 | { | 515 | { |
501 | if (!is_console(fileno(stream))) | 516 | int ret; |
502 | return fputs(str, stream); | 517 | |
518 | if (!is_console(fileno(stream))) { | ||
519 | SetLastError(0); | ||
520 | if ((ret=fputs(str, stream)) == EOF) | ||
521 | check_pipe(stream); | ||
522 | return ret; | ||
523 | } | ||
503 | 524 | ||
504 | return ansi_emulate(str, stream) == EOF ? EOF : 0; | 525 | return ansi_emulate(str, stream) == EOF ? EOF : 0; |
505 | } | 526 | } |
@@ -538,7 +559,9 @@ int winansi_vfprintf(FILE *stream, const char *format, va_list list) | |||
538 | return rv; | 559 | return rv; |
539 | 560 | ||
540 | abort: | 561 | abort: |
541 | rv = vfprintf(stream, format, list); | 562 | SetLastError(0); |
563 | if ((rv=vfprintf(stream, format, list)) == EOF) | ||
564 | check_pipe(stream); | ||
542 | return rv; | 565 | return rv; |
543 | } | 566 | } |
544 | 567 | ||