1/* POSIX compatible FILE stream write function. 2 Copyright (C) 2008-2010 Free Software Foundation, Inc. 3 Written by Bruno Haible <bruno@clisp.org>, 2008. 4 5 This program is free software: you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 17 18#include <config.h> 19 20/* Specification. */ 21#include <stdio.h> 22 23/* Replace these functions only if module 'sigpipe' is requested. */ 24#if GNULIB_SIGPIPE 25 26/* On native Windows platforms, SIGPIPE does not exist. When write() is 27 called on a pipe with no readers, WriteFile() fails with error 28 GetLastError() = ERROR_NO_DATA, and write() in consequence fails with 29 error EINVAL. This write() function is at the basis of the function 30 which flushes the buffer of a FILE stream. */ 31 32# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ 33 34# include <errno.h> 35# include <signal.h> 36# include <io.h> 37 38# define WIN32_LEAN_AND_MEAN /* avoid including junk */ 39# include <windows.h> 40 41# define CALL_WITH_SIGPIPE_EMULATION(RETTYPE, EXPRESSION, FAILED) \ 42 if (ferror (stream)) \ 43 return (EXPRESSION); \ 44 else \ 45 { \ 46 RETTYPE ret; \ 47 SetLastError (0); \ 48 ret = (EXPRESSION); \ 49 if (FAILED && GetLastError () == ERROR_NO_DATA && ferror (stream)) \ 50 { \ 51 int fd = fileno (stream); \ 52 if (fd >= 0 \ 53 && GetFileType ((HANDLE) _get_osfhandle (fd)) == FILE_TYPE_PIPE)\ 54 { \ 55 /* Try to raise signal SIGPIPE. */ \ 56 raise (SIGPIPE); \ 57 /* If it is currently blocked or ignored, change errno from \ 58 EINVAL to EPIPE. */ \ 59 errno = EPIPE; \ 60 } \ 61 } \ 62 return ret; \ 63 } 64 65# if !REPLACE_PRINTF_POSIX /* avoid collision with printf.c */ 66# if !DEPENDS_ON_LIBINTL /* avoid collision with intl/printf.c */ 67int 68printf (const char *format, ...) 69{ 70 int retval; 71 va_list args; 72 73 va_start (args, format); 74 retval = vfprintf (stdout, format, args); 75 va_end (args); 76 77 return retval; 78} 79# endif 80# endif 81 82# if !REPLACE_FPRINTF_POSIX /* avoid collision with fprintf.c */ 83int 84fprintf (FILE *stream, const char *format, ...) 85{ 86 int retval; 87 va_list args; 88 89 va_start (args, format); 90 retval = vfprintf (stream, format, args); 91 va_end (args); 92 93 return retval; 94} 95# endif 96 97# if !REPLACE_VPRINTF_POSIX /* avoid collision with vprintf.c */ 98int 99vprintf (const char *format, va_list args) 100{ 101 return vfprintf (stdout, format, args); 102} 103# endif 104 105# if !REPLACE_VFPRINTF_POSIX /* avoid collision with vfprintf.c */ 106int 107vfprintf (FILE *stream, const char *format, va_list args) 108#undef vfprintf 109{ 110 CALL_WITH_SIGPIPE_EMULATION (int, vfprintf (stream, format, args), ret == EOF) 111} 112# endif 113 114int 115putchar (int c) 116{ 117 return fputc (c, stdout); 118} 119 120int 121fputc (int c, FILE *stream) 122#undef fputc 123{ 124 CALL_WITH_SIGPIPE_EMULATION (int, fputc (c, stream), ret == EOF) 125} 126 127int 128fputs (const char *string, FILE *stream) 129#undef fputs 130{ 131 CALL_WITH_SIGPIPE_EMULATION (int, fputs (string, stream), ret == EOF) 132} 133 134int 135puts (const char *string) 136#undef puts 137{ 138 FILE *stream = stdout; 139 CALL_WITH_SIGPIPE_EMULATION (int, puts (string), ret == EOF) 140} 141 142size_t 143fwrite (const void *ptr, size_t s, size_t n, FILE *stream) 144#undef fwrite 145{ 146 CALL_WITH_SIGPIPE_EMULATION (size_t, fwrite (ptr, s, n, stream), ret < n) 147} 148 149# endif 150#endif 151