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