aboutsummaryrefslogtreecommitdiff
path: root/win32
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2018-03-06 14:08:23 +0000
committerRon Yorston <rmy@pobox.com>2018-03-06 14:08:23 +0000
commit922dba2a9a00c35abb19c5dba01169e7335ce23b (patch)
tree7152daf82d775da4fc588ce81e435730a9eb30dd /win32
parentc44b18ace0b3e020e594f4d4ab2c9a1211ec90ab (diff)
downloadbusybox-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.c35
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
478static 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
478size_t winansi_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) 489size_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
499int winansi_fputs(const char *str, FILE *stream) 514int 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
540abort: 561abort:
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