summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2008-09-26 13:29:53 +0200
committerBruno Haible <bruno@clisp.org>2008-09-26 13:44:52 +0200
commit94b87393b6947b51b2a842cd88820a3cb60d8cd4 (patch)
tree38cf19e1cb43896e5ae1d0b920d1eb53ac953305
parentb5298eb7a71c5ae0a2320a99dd3965ef8df33648 (diff)
downloadgnulib-94b87393b6947b51b2a842cd88820a3cb60d8cd4.tar.gz
New module 'write'.
-rw-r--r--ChangeLog12
-rw-r--r--doc/posix-functions/write.texi7
-rw-r--r--lib/unistd.in.h15
-rw-r--r--lib/write.c62
-rw-r--r--m4/unistd_h.m429
-rw-r--r--m4/write.m420
-rw-r--r--modules/unistd3
-rw-r--r--modules/write25
8 files changed, 159 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog
index 4c814825d8..2e9c8dbedb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -23,6 +23,18 @@
2008-09-26 Bruno Haible <bruno@clisp.org>
+ * modules/write: New file.
+ * lib/unistd.in.h: Include <sys/types.h>.
+ (write): New declaration.
+ * lib/write.c: New file.
+ * m4/write.m4: New file.
+ * m4/unistd_h.m4 (gl_UNISTD_H_DEFAULTS): Initialize
+ GNULIB_UNISTD_H_SIGPIPE, GNULIB_WRITE, REPLACE_WRITE.
+ * modules/unistd (Makefile.am): Substitute GNULIB_UNISTD_H_SIGPIPE,
+ GNULIB_WRITE, REPLACE_WRITE.
+ * doc/posix-functions/write.texi: Mention the write, sigpipe modules
+ and the SIGPIPE issue.
+
* lib/signal.in.h (SIGPIPE): Define to a replacement value.
(raise): New declaration.
* lib/sigprocmask.c (SIGPIPE_handler): New variable.
diff --git a/doc/posix-functions/write.texi b/doc/posix-functions/write.texi
index 237a89b146..9f81f32418 100644
--- a/doc/posix-functions/write.texi
+++ b/doc/posix-functions/write.texi
@@ -4,10 +4,15 @@
POSIX specification: @url{http://www.opengroup.org/susv3xsh/write.html}
-Gnulib module: ---
+Gnulib module: write, sigpipe
Portability problems fixed by Gnulib:
@itemize
+@item
+When writing to a pipe with no readers, this function fails with error
+@code{EINVAL}, instead of obeying the current @code{SIGPIPE} handler, on
+some platforms:
+mingw.
@end itemize
Portability problems not fixed by Gnulib:
diff --git a/lib/unistd.in.h b/lib/unistd.in.h
index 500de9ce18..e75b4cdae1 100644
--- a/lib/unistd.in.h
+++ b/lib/unistd.in.h
@@ -35,6 +35,11 @@
/* mingw fails to declare _exit in <unistd.h>. */
#include <stdlib.h>
+#if @GNULIB_WRITE@ && @REPLACE_WRITE@ && @GNULIB_UNISTD_H_SIGPIPE@
+/* Get ssize_t. */
+# include <sys/types.h>
+#endif
+
/* The definition of GL_LINK_WARNING is copied here. */
@@ -333,6 +338,16 @@ extern unsigned int sleep (unsigned int n);
#endif
+#if @GNULIB_WRITE@ && @REPLACE_WRITE@ && @GNULIB_UNISTD_H_SIGPIPE@
+/* Write up to COUNT bytes starting at BUF to file descriptor FD.
+ See the POSIX:2001 specification
+ <http://www.opengroup.org/susv3xsh/write.html>. */
+# undef write
+# define write rpl_write
+extern ssize_t write (int fd, const void *buf, size_t count);
+#endif
+
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/write.c b/lib/write.c
new file mode 100644
index 0000000000..250b5cc8fd
--- /dev/null
+++ b/lib/write.c
@@ -0,0 +1,62 @@
+/* POSIX compatible write() function.
+ Copyright (C) 2008 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2008.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <unistd.h>
+
+/* Replace this function only if module 'sigpipe' is requested. */
+#if GNULIB_SIGPIPE
+
+/* On native Windows platforms, SIGPIPE does not exist. When write() is
+ called on a pipe with no readers, WriteFile() fails with error
+ GetLastError() = ERROR_NO_DATA, and write() in consequence fails with
+ error EINVAL. */
+
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+
+# include <errno.h>
+# include <signal.h>
+# include <io.h>
+
+# define WIN32_LEAN_AND_MEAN /* avoid including junk */
+# include <windows.h>
+
+ssize_t
+rpl_write (int fd, const void *buf, size_t count)
+#undef write
+{
+ ssize_t ret = write (fd, buf, count);
+
+ if (ret < 0)
+ {
+ if (GetLastError () == ERROR_NO_DATA
+ && GetFileType (_get_osfhandle (fd)) == FILE_TYPE_PIPE)
+ {
+ /* Try to raise signal SIGPIPE. */
+ raise (SIGPIPE);
+ /* If it is currently blocked or ignored, change errno from EINVAL
+ to EPIPE. */
+ errno = EPIPE;
+ }
+ }
+ return ret;
+}
+
+# endif
+#endif
diff --git a/m4/unistd_h.m4 b/m4/unistd_h.m4
index e8ccab16e8..0e76a52abe 100644
--- a/m4/unistd_h.m4
+++ b/m4/unistd_h.m4
@@ -1,4 +1,4 @@
-# unistd_h.m4 serial 11
+# unistd_h.m4 serial 12
dnl Copyright (C) 2006-2008 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -32,18 +32,20 @@ AC_DEFUN([gl_UNISTD_MODULE_INDICATOR],
AC_DEFUN([gl_UNISTD_H_DEFAULTS],
[
- GNULIB_CHOWN=0; AC_SUBST([GNULIB_CHOWN])
- GNULIB_DUP2=0; AC_SUBST([GNULIB_DUP2])
- GNULIB_ENVIRON=0; AC_SUBST([GNULIB_ENVIRON])
- GNULIB_FCHDIR=0; AC_SUBST([GNULIB_FCHDIR])
- GNULIB_FTRUNCATE=0; AC_SUBST([GNULIB_FTRUNCATE])
- GNULIB_GETCWD=0; AC_SUBST([GNULIB_GETCWD])
- GNULIB_GETLOGIN_R=0; AC_SUBST([GNULIB_GETLOGIN_R])
- GNULIB_GETPAGESIZE=0; AC_SUBST([GNULIB_GETPAGESIZE])
- GNULIB_LCHOWN=0; AC_SUBST([GNULIB_LCHOWN])
- GNULIB_LSEEK=0; AC_SUBST([GNULIB_LSEEK])
- GNULIB_READLINK=0; AC_SUBST([GNULIB_READLINK])
- GNULIB_SLEEP=0; AC_SUBST([GNULIB_SLEEP])
+ GNULIB_CHOWN=0; AC_SUBST([GNULIB_CHOWN])
+ GNULIB_DUP2=0; AC_SUBST([GNULIB_DUP2])
+ GNULIB_ENVIRON=0; AC_SUBST([GNULIB_ENVIRON])
+ GNULIB_FCHDIR=0; AC_SUBST([GNULIB_FCHDIR])
+ GNULIB_FTRUNCATE=0; AC_SUBST([GNULIB_FTRUNCATE])
+ GNULIB_GETCWD=0; AC_SUBST([GNULIB_GETCWD])
+ GNULIB_GETLOGIN_R=0; AC_SUBST([GNULIB_GETLOGIN_R])
+ GNULIB_GETPAGESIZE=0; AC_SUBST([GNULIB_GETPAGESIZE])
+ GNULIB_LCHOWN=0; AC_SUBST([GNULIB_LCHOWN])
+ GNULIB_LSEEK=0; AC_SUBST([GNULIB_LSEEK])
+ GNULIB_READLINK=0; AC_SUBST([GNULIB_READLINK])
+ GNULIB_SLEEP=0; AC_SUBST([GNULIB_SLEEP])
+ GNULIB_UNISTD_H_SIGPIPE=0; AC_SUBST([GNULIB_UNISTD_H_SIGPIPE])
+ GNULIB_WRITE=0; AC_SUBST([GNULIB_WRITE])
dnl Assume proper GNU behavior unless another module says otherwise.
HAVE_DUP2=1; AC_SUBST([HAVE_DUP2])
HAVE_FTRUNCATE=1; AC_SUBST([HAVE_FTRUNCATE])
@@ -60,4 +62,5 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS],
REPLACE_GETPAGESIZE=0; AC_SUBST([REPLACE_GETPAGESIZE])
REPLACE_LCHOWN=0; AC_SUBST([REPLACE_LCHOWN])
REPLACE_LSEEK=0; AC_SUBST([REPLACE_LSEEK])
+ REPLACE_WRITE=0; AC_SUBST([REPLACE_WRITE])
])
diff --git a/m4/write.m4 b/m4/write.m4
new file mode 100644
index 0000000000..812b19b3b0
--- /dev/null
+++ b/m4/write.m4
@@ -0,0 +1,20 @@
+# write.m4 serial 1
+dnl Copyright (C) 2008 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_WRITE],
+[
+ AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+ dnl This ifdef is just an optimization, to avoid performing a configure
+ dnl check whose result is not used. It does not make the test of
+ dnl GNULIB_UNISTD_H_SIGPIPE or GNULIB_SIGPIPE redundant.
+ m4_ifdef([gl_SIGNAL_SIGPIPE], [
+ gl_SIGNAL_SIGPIPE
+ if test $gl_cv_header_signal_h_SIGPIPE != yes; then
+ REPLACE_WRITE=1
+ AC_LIBOBJ([write])
+ fi
+ ])
+])
diff --git a/modules/unistd b/modules/unistd
index 07edf7f227..d9101f36d0 100644
--- a/modules/unistd
+++ b/modules/unistd
@@ -36,6 +36,8 @@ unistd.h: unistd.in.h
-e 's|@''GNULIB_LSEEK''@|$(GNULIB_LSEEK)|g' \
-e 's|@''GNULIB_READLINK''@|$(GNULIB_READLINK)|g' \
-e 's|@''GNULIB_SLEEP''@|$(GNULIB_SLEEP)|g' \
+ -e 's|@''GNULIB_UNISTD_H_SIGPIPE''@|$(GNULIB_UNISTD_H_SIGPIPE)|g' \
+ -e 's|@''GNULIB_WRITE''@|$(GNULIB_WRITE)|g' \
-e 's|@''HAVE_DUP2''@|$(HAVE_DUP2)|g' \
-e 's|@''HAVE_FTRUNCATE''@|$(HAVE_FTRUNCATE)|g' \
-e 's|@''HAVE_GETPAGESIZE''@|$(HAVE_GETPAGESIZE)|g' \
@@ -51,6 +53,7 @@ unistd.h: unistd.in.h
-e 's|@''REPLACE_GETPAGESIZE''@|$(REPLACE_GETPAGESIZE)|g' \
-e 's|@''REPLACE_LCHOWN''@|$(REPLACE_LCHOWN)|g' \
-e 's|@''REPLACE_LSEEK''@|$(REPLACE_LSEEK)|g' \
+ -e 's|@''REPLACE_WRITE''@|$(REPLACE_WRITE)|g' \
< $(srcdir)/unistd.in.h; \
} > $@-t
mv $@-t $@
diff --git a/modules/write b/modules/write
new file mode 100644
index 0000000000..8dd634076c
--- /dev/null
+++ b/modules/write
@@ -0,0 +1,25 @@
+Description:
+POSIX compatible write() function: write data to a file descriptor
+
+Files:
+lib/write.c
+m4/write.m4
+
+Depends-on:
+unistd
+
+configure.ac:
+gl_FUNC_WRITE
+gl_UNISTD_MODULE_INDICATOR([write])
+
+Makefile.am:
+
+Include:
+<unistd.h>
+
+License:
+LGPLv2+
+
+Maintainer:
+Bruno Haible
+