1/* POSIX compatible FILE stream write function. 2 Copyright (C) 2008-2011 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 'nonblocking' or module 'sigpipe' is 24 requested. */ 25#if GNULIB_NONBLOCKING || GNULIB_SIGPIPE 26 27/* On native Windows platforms, SIGPIPE does not exist. When write() is 28 called on a pipe with no readers, WriteFile() fails with error 29 GetLastError() = ERROR_NO_DATA, and write() in consequence fails with 30 error EINVAL. This write() function is at the basis of the function 31 which flushes the buffer of a FILE stream. */ 32 33# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ 34 35# include <errno.h> 36# include <signal.h> 37# include <io.h> 38 39# define WIN32_LEAN_AND_MEAN /* avoid including junk */ 40# include <windows.h> 41 42# if GNULIB_NONBLOCKING 43# define CLEAR_ERRNO \ 44 errno = 0; 45# define HANDLE_ENOSPC \ 46 if (errno == ENOSPC && ferror (stream)) \ 47 { \ 48 int fd = fileno (stream); \ 49 if (fd >= 0) \ 50 { \ 51 HANDLE h = (HANDLE) _get_osfhandle (fd); \ 52 if (GetFileType (h) == FILE_TYPE_PIPE) \ 53 { \ 54 /* h is a pipe or socket. */ \ 55 DWORD state; \ 56 if (GetNamedPipeHandleState (h, &state, NULL, NULL, \ 57 NULL, NULL, 0) \ 58 && (state & PIPE_NOWAIT) != 0) \ 59 /* h is a pipe in non-blocking mode. \ 60 Change errno from ENOSPC to EAGAIN. */ \ 61 errno = EAGAIN; \ 62 } \ 63 } \ 64 } \ 65 else 66# else 67# define CLEAR_ERRNO 68# define HANDLE_ENOSPC 69# endif 70 71# if GNULIB_SIGPIPE 72# define CLEAR_LastError \ 73 SetLastError (0); 74# define HANDLE_ERROR_NO_DATA \ 75 if (GetLastError () == ERROR_NO_DATA && ferror (stream)) \ 76 { \ 77 int fd = fileno (stream); \ 78 if (fd >= 0 \ 79 && GetFileType ((HANDLE) _get_osfhandle (fd)) \ 80 == FILE_TYPE_PIPE) \ 81 { \ 82 /* Try to raise signal SIGPIPE. */ \ 83 raise (SIGPIPE); \ 84 /* If it is currently blocked or ignored, change errno from \ 85 EINVAL to EPIPE. */ \ 86 errno = EPIPE; \ 87 } \ 88 } \ 89 else 90# else 91# define CLEAR_LastError 92# define HANDLE_ERROR_NO_DATA 93# endif 94 95# define CALL_WITH_SIGPIPE_EMULATION(RETTYPE, EXPRESSION, FAILED) \ 96 if (ferror (stream)) \ 97 return (EXPRESSION); \ 98 else \ 99 { \ 100 RETTYPE ret; \ 101 CLEAR_ERRNO \ 102 CLEAR_LastError \ 103 ret = (EXPRESSION); \ 104 if (FAILED) \ 105 { \ 106 HANDLE_ENOSPC \ 107 HANDLE_ERROR_NO_DATA \ 108 ; \ 109 } \ 110 return ret; \ 111 } 112 113# if !REPLACE_PRINTF_POSIX /* avoid collision with printf.c */ 114int 115printf (const char *format, ...) 116{ 117 int retval; 118 va_list args; 119 120 va_start (args, format); 121 retval = vfprintf (stdout, format, args); 122 va_end (args); 123 124 return retval; 125} 126# endif 127 128# if !REPLACE_FPRINTF_POSIX /* avoid collision with fprintf.c */ 129int 130fprintf (FILE *stream, const char *format, ...) 131{ 132 int retval; 133 va_list args; 134 135 va_start (args, format); 136 retval = vfprintf (stream, format, args); 137 va_end (args); 138 139 return retval; 140} 141# endif 142 143# if !REPLACE_VPRINTF_POSIX /* avoid collision with vprintf.c */ 144int 145vprintf (const char *format, va_list args) 146{ 147 return vfprintf (stdout, format, args); 148} 149# endif 150 151# if !REPLACE_VFPRINTF_POSIX /* avoid collision with vfprintf.c */ 152int 153vfprintf (FILE *stream, const char *format, va_list args) 154#undef vfprintf 155{ 156 CALL_WITH_SIGPIPE_EMULATION (int, vfprintf (stream, format, args), ret == EOF) 157} 158# endif 159 160int 161putchar (int c) 162{ 163 return fputc (c, stdout); 164} 165 166int 167fputc (int c, FILE *stream) 168#undef fputc 169{ 170 CALL_WITH_SIGPIPE_EMULATION (int, fputc (c, stream), ret == EOF) 171} 172 173int 174fputs (const char *string, FILE *stream) 175#undef fputs 176{ 177 CALL_WITH_SIGPIPE_EMULATION (int, fputs (string, stream), ret == EOF) 178} 179 180int 181puts (const char *string) 182#undef puts 183{ 184 FILE *stream = stdout; 185 CALL_WITH_SIGPIPE_EMULATION (int, puts (string), ret == EOF) 186} 187 188size_t 189fwrite (const void *ptr, size_t s, size_t n, FILE *stream) 190#undef fwrite 191{ 192 CALL_WITH_SIGPIPE_EMULATION (size_t, fwrite (ptr, s, n, stream), ret < n) 193} 194 195# endif 196#endif 197