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