* modules/strerror-override: New module.
* lib/strerror_r.c (strerror_r): Move gnulib replacement strings...
* lib/strerror-override.c (strerror_override): ...to new file.
* lib/strerror-override.h: Add prototype.
* lib/strerror-impl.h: Delete.
* lib/strerror.c (strerror): New implementation.
* modules/strerror_r-posix (Files): Add new files.
* modules/strerror (Files): Likewise.
(Depends-on): Drop strerror_r-posix.
* MODULES.html.sh: Document new module and strerror_r-posix.
Requested by Sam Steingold.

Signed-off-by: Eric Blake <ebl...@redhat.com>
---

A new module is required because both strerror and strerror_r might
need strerror-override.o, but they might be in different directories
(one in lib and one in tests), and we can only AC_LIBOBJ it once.

Now, just the strerror module in isolation does not drag in strerror_r.

Tested on glibc with:

gl_cv_header_errno_h_complete=no gl_cv_func_working_strerror=no \
  gl_cv_func_strerror_r_works=no ./gnulib-tool --with-tests \
  --test strerror strerror_r-posix

Hmm, perhaps I should move strerror-override.c to be part of the
errno module, rather than making it a separate module.  That is,
the only time the strerror_override() function should be compiled
is if our replacement errno.h added new values.

 ChangeLog                 |   13 ++
 MODULES.html.sh           |    2 +
 lib/strerror-impl.h       |   42 ------
 lib/strerror-override.c   |  347 +++++++++++++++++++++++++++++++++++++++++++++
 lib/strerror-override.h   |   48 ++++++
 lib/strerror.c            |   36 +++++-
 lib/strerror_r.c          |  318 +----------------------------------------
 modules/strerror          |    9 +-
 modules/strerror-override |   26 ++++
 modules/strerror_r-posix  |    1 +
 10 files changed, 479 insertions(+), 363 deletions(-)
 delete mode 100644 lib/strerror-impl.h
 create mode 100644 lib/strerror-override.c
 create mode 100644 lib/strerror-override.h
 create mode 100644 modules/strerror-override

diff --git a/ChangeLog b/ChangeLog
index a66e44d..1aeaa33 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
 2011-05-24  Eric Blake  <ebl...@redhat.com>

+       strerror: drop strerror_r dependency
+       * modules/strerror-override: New module.
+       * lib/strerror_r.c (strerror_r): Move gnulib replacement strings...
+       * lib/strerror-override.c (strerror_override): ...to new file.
+       * lib/strerror-override.h: Add prototype.
+       * lib/strerror-impl.h: Delete.
+       * lib/strerror.c (strerror): New implementation.
+       * modules/strerror_r-posix (Files): Add new files.
+       * modules/strerror (Files): Likewise.
+       (Depends-on): Drop strerror_r-posix.
+       * MODULES.html.sh: Document new module and strerror_r-posix.
+       Requested by Sam Steingold.
+
        perror: call strerror_r directly
        * modules/perror (Files): Drop strerror-impl.h.
        * lib/perror.c (perror): Use our own stack buffer, rather than
diff --git a/MODULES.html.sh b/MODULES.html.sh
index 18a7472..26c3fa9 100755
--- a/MODULES.html.sh
+++ b/MODULES.html.sh
@@ -1626,6 +1626,7 @@ func_all_modules ()
   func_module atexit
   func_module strtod
   func_module strerror
+  func_module strerror-override
   func_module mktime
   func_end_table

@@ -1789,6 +1790,7 @@ func_all_modules ()
   func_module strcasestr-simple
   func_module strchrnul
   func_module streq
+  func_module strerror_r-posix
   func_module strnlen
   func_module strnlen1
   func_module strndup
diff --git a/lib/strerror-impl.h b/lib/strerror-impl.h
deleted file mode 100644
index a204243..0000000
--- a/lib/strerror-impl.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* strerror-impl.h --- Implementation of POSIX compatible strerror() function.
-
-   Copyright (C) 2007-2011 Free Software Foundation, Inc.
-
-   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/>.  */
-
-#ifdef STATIC
-STATIC
-#endif
-char *
-strerror (int n)
-{
-  static char buf[256];
-
-  int ret = strerror_r (n, buf, sizeof (buf));
-
-  if (ret == 0)
-    return buf;
-
-  if (ret == ERANGE)
-    /* If this happens, increase the size of buf.  */
-    abort ();
-
-  {
-    static char const fmt[] = "Unknown error (%d)";
-    verify (sizeof (buf) >= sizeof (fmt) + INT_STRLEN_BOUND (n));
-    sprintf (buf, fmt, n);
-    errno = ret;
-    return buf;
-  }
-}
diff --git a/lib/strerror-override.c b/lib/strerror-override.c
new file mode 100644
index 0000000..5fcbe1f
--- /dev/null
+++ b/lib/strerror-override.c
@@ -0,0 +1,347 @@
+/* strerror-override.c --- POSIX compatible system error routine
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+
+   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/>.  */
+
+/* Written by Bruno Haible <br...@clisp.org>, 2010.  */
+
+#include "strerror-override.h"
+
+#include <errno.h>
+
+#if GNULIB_defined_ESOCK /* native Windows platforms */
+# if HAVE_WINSOCK2_H
+#  include <winsock2.h>
+# endif
+#endif
+
+/* This undefine allows testing with gl_cv_header_errno_h_complete=no on
+   a system that otherwise has a complete errno.h.  */
+#undef strerror_override
+
+/* If ERRNUM maps to an errno value defined by gnulib, return a string
+   describing the error.  Otherwise return NULL.  */
+const char *
+strerror_override (int errnum)
+{
+  const char *msg = NULL;
+
+#if GNULIB_defined_ETXTBSY \
+    || GNULIB_defined_ESOCK \
+    || GNULIB_defined_ENOMSG \
+    || GNULIB_defined_EIDRM \
+    || GNULIB_defined_ENOLINK \
+    || GNULIB_defined_EPROTO \
+    || GNULIB_defined_EMULTIHOP \
+    || GNULIB_defined_EBADMSG \
+    || GNULIB_defined_EOVERFLOW \
+    || GNULIB_defined_ENOTSUP \
+    || GNULIB_defined_ESTALE \
+    || GNULIB_defined_EDQUOT \
+    || GNULIB_defined_ECANCELED
+  /* These error messages are taken from glibc/sysdeps/gnu/errlist.c.  */
+  switch (errnum)
+    {
+# if GNULIB_defined_ETXTBSY
+    case ETXTBSY:
+      msg = "Text file busy";
+      break;
+# endif
+
+# if GNULIB_defined_ESOCK /* native Windows platforms */
+      /* EWOULDBLOCK is the same as EAGAIN.  */
+    case EINPROGRESS:
+      msg = "Operation now in progress";
+      break;
+    case EALREADY:
+      msg = "Operation already in progress";
+      break;
+    case ENOTSOCK:
+      msg = "Socket operation on non-socket";
+      break;
+    case EDESTADDRREQ:
+      msg = "Destination address required";
+      break;
+    case EMSGSIZE:
+      msg = "Message too long";
+      break;
+    case EPROTOTYPE:
+      msg = "Protocol wrong type for socket";
+      break;
+    case ENOPROTOOPT:
+      msg = "Protocol not available";
+      break;
+    case EPROTONOSUPPORT:
+      msg = "Protocol not supported";
+      break;
+    case ESOCKTNOSUPPORT:
+      msg = "Socket type not supported";
+      break;
+    case EOPNOTSUPP:
+      msg = "Operation not supported";
+      break;
+    case EPFNOSUPPORT:
+      msg = "Protocol family not supported";
+      break;
+    case EAFNOSUPPORT:
+      msg = "Address family not supported by protocol";
+      break;
+    case EADDRINUSE:
+      msg = "Address already in use";
+      break;
+    case EADDRNOTAVAIL:
+      msg = "Cannot assign requested address";
+      break;
+    case ENETDOWN:
+      msg = "Network is down";
+      break;
+    case ENETUNREACH:
+      msg = "Network is unreachable";
+      break;
+    case ENETRESET:
+      msg = "Network dropped connection on reset";
+      break;
+    case ECONNABORTED:
+      msg = "Software caused connection abort";
+      break;
+    case ECONNRESET:
+      msg = "Connection reset by peer";
+      break;
+    case ENOBUFS:
+      msg = "No buffer space available";
+      break;
+    case EISCONN:
+      msg = "Transport endpoint is already connected";
+      break;
+    case ENOTCONN:
+      msg = "Transport endpoint is not connected";
+      break;
+    case ESHUTDOWN:
+      msg = "Cannot send after transport endpoint shutdown";
+      break;
+    case ETOOMANYREFS:
+      msg = "Too many references: cannot splice";
+      break;
+    case ETIMEDOUT:
+      msg = "Connection timed out";
+      break;
+    case ECONNREFUSED:
+      msg = "Connection refused";
+      break;
+    case ELOOP:
+      msg = "Too many levels of symbolic links";
+      break;
+    case EHOSTDOWN:
+      msg = "Host is down";
+      break;
+    case EHOSTUNREACH:
+      msg = "No route to host";
+      break;
+    case EPROCLIM:
+      msg = "Too many processes";
+      break;
+    case EUSERS:
+      msg = "Too many users";
+      break;
+    case EDQUOT:
+      msg = "Disk quota exceeded";
+      break;
+    case ESTALE:
+      msg = "Stale NFS file handle";
+      break;
+    case EREMOTE:
+      msg = "Object is remote";
+      break;
+#  if HAVE_WINSOCK2_H
+      /* WSA_INVALID_HANDLE maps to EBADF */
+      /* WSA_NOT_ENOUGH_MEMORY maps to ENOMEM */
+      /* WSA_INVALID_PARAMETER maps to EINVAL */
+    case WSA_OPERATION_ABORTED:
+      msg = "Overlapped operation aborted";
+      break;
+    case WSA_IO_INCOMPLETE:
+      msg = "Overlapped I/O event object not in signaled state";
+      break;
+    case WSA_IO_PENDING:
+      msg = "Overlapped operations will complete later";
+      break;
+      /* WSAEINTR maps to EINTR */
+      /* WSAEBADF maps to EBADF */
+      /* WSAEACCES maps to EACCES */
+      /* WSAEFAULT maps to EFAULT */
+      /* WSAEINVAL maps to EINVAL */
+      /* WSAEMFILE maps to EMFILE */
+      /* WSAEWOULDBLOCK maps to EWOULDBLOCK */
+      /* WSAEINPROGRESS is EINPROGRESS */
+      /* WSAEALREADY is EALREADY */
+      /* WSAENOTSOCK is ENOTSOCK */
+      /* WSAEDESTADDRREQ is EDESTADDRREQ */
+      /* WSAEMSGSIZE is EMSGSIZE */
+      /* WSAEPROTOTYPE is EPROTOTYPE */
+      /* WSAENOPROTOOPT is ENOPROTOOPT */
+      /* WSAEPROTONOSUPPORT is EPROTONOSUPPORT */
+      /* WSAESOCKTNOSUPPORT is ESOCKTNOSUPPORT */
+      /* WSAEOPNOTSUPP is EOPNOTSUPP */
+      /* WSAEPFNOSUPPORT is EPFNOSUPPORT */
+      /* WSAEAFNOSUPPORT is EAFNOSUPPORT */
+      /* WSAEADDRINUSE is EADDRINUSE */
+      /* WSAEADDRNOTAVAIL is EADDRNOTAVAIL */
+      /* WSAENETDOWN is ENETDOWN */
+      /* WSAENETUNREACH is ENETUNREACH */
+      /* WSAENETRESET is ENETRESET */
+      /* WSAECONNABORTED is ECONNABORTED */
+      /* WSAECONNRESET is ECONNRESET */
+      /* WSAENOBUFS is ENOBUFS */
+      /* WSAEISCONN is EISCONN */
+      /* WSAENOTCONN is ENOTCONN */
+      /* WSAESHUTDOWN is ESHUTDOWN */
+      /* WSAETOOMANYREFS is ETOOMANYREFS */
+      /* WSAETIMEDOUT is ETIMEDOUT */
+      /* WSAECONNREFUSED is ECONNREFUSED */
+      /* WSAELOOP is ELOOP */
+      /* WSAENAMETOOLONG maps to ENAMETOOLONG */
+      /* WSAEHOSTDOWN is EHOSTDOWN */
+      /* WSAEHOSTUNREACH is EHOSTUNREACH */
+      /* WSAENOTEMPTY maps to ENOTEMPTY */
+      /* WSAEPROCLIM is EPROCLIM */
+      /* WSAEUSERS is EUSERS */
+      /* WSAEDQUOT is EDQUOT */
+      /* WSAESTALE is ESTALE */
+      /* WSAEREMOTE is EREMOTE */
+    case WSASYSNOTREADY:
+      msg = "Network subsystem is unavailable";
+      break;
+    case WSAVERNOTSUPPORTED:
+      msg = "Winsock.dll version out of range";
+      break;
+    case WSANOTINITIALISED:
+      msg = "Successful WSAStartup not yet performed";
+      break;
+    case WSAEDISCON:
+      msg = "Graceful shutdown in progress";
+      break;
+    case WSAENOMORE: case WSA_E_NO_MORE:
+      msg = "No more results";
+      break;
+    case WSAECANCELLED: case WSA_E_CANCELLED:
+      msg = "Call was canceled";
+      break;
+    case WSAEINVALIDPROCTABLE:
+      msg = "Procedure call table is invalid";
+      break;
+    case WSAEINVALIDPROVIDER:
+      msg = "Service provider is invalid";
+      break;
+    case WSAEPROVIDERFAILEDINIT:
+      msg = "Service provider failed to initialize";
+      break;
+    case WSASYSCALLFAILURE:
+      msg = "System call failure";
+      break;
+    case WSASERVICE_NOT_FOUND:
+      msg = "Service not found";
+      break;
+    case WSATYPE_NOT_FOUND:
+      msg = "Class type not found";
+      break;
+    case WSAEREFUSED:
+      msg = "Database query was refused";
+      break;
+    case WSAHOST_NOT_FOUND:
+      msg = "Host not found";
+      break;
+    case WSATRY_AGAIN:
+      msg = "Nonauthoritative host not found";
+      break;
+    case WSANO_RECOVERY:
+      msg = "Nonrecoverable error";
+      break;
+    case WSANO_DATA:
+      msg = "Valid name, no data record of requested type";
+      break;
+      /* WSA_QOS_* omitted */
+#  endif
+# endif
+
+# if GNULIB_defined_ENOMSG
+    case ENOMSG:
+      msg = "No message of desired type";
+      break;
+# endif
+
+# if GNULIB_defined_EIDRM
+    case EIDRM:
+      msg = "Identifier removed";
+      break;
+# endif
+
+# if GNULIB_defined_ENOLINK
+    case ENOLINK:
+      msg = "Link has been severed";
+      break;
+# endif
+
+# if GNULIB_defined_EPROTO
+    case EPROTO:
+      msg = "Protocol error";
+      break;
+# endif
+
+# if GNULIB_defined_EMULTIHOP
+    case EMULTIHOP:
+      msg = "Multihop attempted";
+      break;
+# endif
+
+# if GNULIB_defined_EBADMSG
+    case EBADMSG:
+      msg = "Bad message";
+      break;
+# endif
+
+# if GNULIB_defined_EOVERFLOW
+    case EOVERFLOW:
+      msg = "Value too large for defined data type";
+      break;
+# endif
+
+# if GNULIB_defined_ENOTSUP
+    case ENOTSUP:
+      msg = "Not supported";
+      break;
+# endif
+
+# if GNULIB_defined_ESTALE
+    case ESTALE:
+      msg = "Stale NFS file handle";
+      break;
+# endif
+
+# if GNULIB_defined_EDQUOT
+    case EDQUOT:
+      msg = "Disk quota exceeded";
+      break;
+# endif
+
+# if GNULIB_defined_ECANCELED
+    case ECANCELED:
+      msg = "Operation canceled";
+      break;
+# endif
+    }
+#endif
+
+  return msg;
+}
diff --git a/lib/strerror-override.h b/lib/strerror-override.h
new file mode 100644
index 0000000..0718b53
--- /dev/null
+++ b/lib/strerror-override.h
@@ -0,0 +1,48 @@
+/* strerror-override.h --- POSIX compatible system error routine
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+
+   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/>.  */
+
+#ifndef _GL_STRERROR_OVERRIDE_H
+# define _GL_STRERROR_OVERRIDE_H
+
+# include <string.h>
+
+/* Reasonable buffer size that should never trigger ERANGE; if this
+   proves too small, we intentionally abort(), to remind us to fix
+   this value.  */
+# define STACKBUF_LEN 256
+
+/* If ERRNUM maps to an errno value defined by gnulib, return a string
+   describing the error.  Otherwise return NULL.  */
+# if GNULIB_defined_ETXTBSY \
+    || GNULIB_defined_ESOCK \
+    || GNULIB_defined_ENOMSG \
+    || GNULIB_defined_EIDRM \
+    || GNULIB_defined_ENOLINK \
+    || GNULIB_defined_EPROTO \
+    || GNULIB_defined_EMULTIHOP \
+    || GNULIB_defined_EBADMSG \
+    || GNULIB_defined_EOVERFLOW \
+    || GNULIB_defined_ENOTSUP \
+    || GNULIB_defined_ESTALE \
+    || GNULIB_defined_EDQUOT \
+    || GNULIB_defined_ECANCELED
+extern const char *strerror_override (int errnum);
+# else
+#  define strerror_override(ignored) NULL
+# endif
+
+#endif /* _GL_STRERROR_OVERRIDE_H */
diff --git a/lib/strerror.c b/lib/strerror.c
index 9d1f165..8c41179 100644
--- a/lib/strerror.c
+++ b/lib/strerror.c
@@ -23,11 +23,45 @@
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>

 #include "intprops.h"
+#include "strerror-override.h"
 #include "verify.h"

 /* Use the system functions, not the gnulib overrides in this file.  */
 #undef sprintf

-#include "strerror-impl.h"
+char *
+strerror (int n)
+#undef strerror
+{
+  static char buf[STACKBUF_LEN];
+  size_t len;
+
+  /* Cast away const, due to the historical signature of strerror;
+     callers should not be modifying the string.  */
+  const char *msg = strerror_override (n);
+  if (msg)
+    return (char *) msg;
+
+  /* Our strerror_r implementation might use the system's strerror
+     buffer, so all other clients of strerror have to see the error
+     copied into a buffer that we manage.  */
+  msg = strerror (n);
+  if (!msg || !*msg)
+    {
+      static char const fmt[] = "Unknown error %d";
+      verify (sizeof buf >= sizeof (fmt) + INT_STRLEN_BOUND (n));
+      sprintf (buf, fmt, n);
+      errno = EINVAL;
+      return buf;
+    }
+
+  /* Fix STACKBUF_LEN if this ever aborts.  */
+  len = strlen (msg);
+  if (sizeof buf <= len)
+    abort ();
+
+  return memcpy (buf, msg, len + 1);
+}
diff --git a/lib/strerror_r.c b/lib/strerror_r.c
index 494b1f0..462455d 100644
--- a/lib/strerror_r.c
+++ b/lib/strerror_r.c
@@ -28,16 +28,7 @@
 #include <errno.h>
 #include <stdio.h>

-#if GNULIB_defined_ESOCK /* native Windows platforms */
-# if HAVE_WINSOCK2_H
-#  include <winsock2.h>
-# endif
-#endif
-
-/* Reasonable buffer size that should never trigger ERANGE; if this
-   proves too small, we intentionally abort(), to remind us to fix
-   this value as well as strerror-impl.h.  */
-#define STACKBUF_LEN 256
+#include "strerror-override.h"

 #if (__GLIBC__ >= 2 || defined __UCLIBC__ || defined __CYGWIN__) && 
HAVE___XPG_STRERROR_R /* glibc >= 2.3.4, cygwin >= 1.7.9 */

@@ -136,316 +127,13 @@ strerror_r (int errnum, char *buf, size_t buflen)
     }
   *buf = '\0';

-#if GNULIB_defined_ETXTBSY \
-    || GNULIB_defined_ESOCK \
-    || GNULIB_defined_ENOMSG \
-    || GNULIB_defined_EIDRM \
-    || GNULIB_defined_ENOLINK \
-    || GNULIB_defined_EPROTO \
-    || GNULIB_defined_EMULTIHOP \
-    || GNULIB_defined_EBADMSG \
-    || GNULIB_defined_EOVERFLOW \
-    || GNULIB_defined_ENOTSUP \
-    || GNULIB_defined_ESTALE \
-    || GNULIB_defined_EDQUOT \
-    || GNULIB_defined_ECANCELED
+  /* Check for gnulib overrides.  */
   {
-    char const *msg = NULL;
-    /* These error messages are taken from glibc/sysdeps/gnu/errlist.c.  */
-    switch (errnum)
-      {
-# if GNULIB_defined_ETXTBSY
-      case ETXTBSY:
-        msg = "Text file busy";
-        break;
-# endif
-
-# if GNULIB_defined_ESOCK /* native Windows platforms */
-      /* EWOULDBLOCK is the same as EAGAIN.  */
-      case EINPROGRESS:
-        msg = "Operation now in progress";
-        break;
-      case EALREADY:
-        msg = "Operation already in progress";
-        break;
-      case ENOTSOCK:
-        msg = "Socket operation on non-socket";
-        break;
-      case EDESTADDRREQ:
-        msg = "Destination address required";
-        break;
-      case EMSGSIZE:
-        msg = "Message too long";
-        break;
-      case EPROTOTYPE:
-        msg = "Protocol wrong type for socket";
-        break;
-      case ENOPROTOOPT:
-        msg = "Protocol not available";
-        break;
-      case EPROTONOSUPPORT:
-        msg = "Protocol not supported";
-        break;
-      case ESOCKTNOSUPPORT:
-        msg = "Socket type not supported";
-        break;
-      case EOPNOTSUPP:
-        msg = "Operation not supported";
-        break;
-      case EPFNOSUPPORT:
-        msg = "Protocol family not supported";
-        break;
-      case EAFNOSUPPORT:
-        msg = "Address family not supported by protocol";
-        break;
-      case EADDRINUSE:
-        msg = "Address already in use";
-        break;
-      case EADDRNOTAVAIL:
-        msg = "Cannot assign requested address";
-        break;
-      case ENETDOWN:
-        msg = "Network is down";
-        break;
-      case ENETUNREACH:
-        msg = "Network is unreachable";
-        break;
-      case ENETRESET:
-        msg = "Network dropped connection on reset";
-        break;
-      case ECONNABORTED:
-        msg = "Software caused connection abort";
-        break;
-      case ECONNRESET:
-        msg = "Connection reset by peer";
-        break;
-      case ENOBUFS:
-        msg = "No buffer space available";
-        break;
-      case EISCONN:
-        msg = "Transport endpoint is already connected";
-        break;
-      case ENOTCONN:
-        msg = "Transport endpoint is not connected";
-        break;
-      case ESHUTDOWN:
-        msg = "Cannot send after transport endpoint shutdown";
-        break;
-      case ETOOMANYREFS:
-        msg = "Too many references: cannot splice";
-        break;
-      case ETIMEDOUT:
-        msg = "Connection timed out";
-        break;
-      case ECONNREFUSED:
-        msg = "Connection refused";
-        break;
-      case ELOOP:
-        msg = "Too many levels of symbolic links";
-        break;
-      case EHOSTDOWN:
-        msg = "Host is down";
-        break;
-      case EHOSTUNREACH:
-        msg = "No route to host";
-        break;
-      case EPROCLIM:
-        msg = "Too many processes";
-        break;
-      case EUSERS:
-        msg = "Too many users";
-        break;
-      case EDQUOT:
-        msg = "Disk quota exceeded";
-        break;
-      case ESTALE:
-        msg = "Stale NFS file handle";
-        break;
-      case EREMOTE:
-        msg = "Object is remote";
-        break;
-#  if HAVE_WINSOCK2_H
-      /* WSA_INVALID_HANDLE maps to EBADF */
-      /* WSA_NOT_ENOUGH_MEMORY maps to ENOMEM */
-      /* WSA_INVALID_PARAMETER maps to EINVAL */
-      case WSA_OPERATION_ABORTED:
-        msg = "Overlapped operation aborted";
-        break;
-      case WSA_IO_INCOMPLETE:
-        msg = "Overlapped I/O event object not in signaled state";
-        break;
-      case WSA_IO_PENDING:
-        msg = "Overlapped operations will complete later";
-        break;
-      /* WSAEINTR maps to EINTR */
-      /* WSAEBADF maps to EBADF */
-      /* WSAEACCES maps to EACCES */
-      /* WSAEFAULT maps to EFAULT */
-      /* WSAEINVAL maps to EINVAL */
-      /* WSAEMFILE maps to EMFILE */
-      /* WSAEWOULDBLOCK maps to EWOULDBLOCK */
-      /* WSAEINPROGRESS is EINPROGRESS */
-      /* WSAEALREADY is EALREADY */
-      /* WSAENOTSOCK is ENOTSOCK */
-      /* WSAEDESTADDRREQ is EDESTADDRREQ */
-      /* WSAEMSGSIZE is EMSGSIZE */
-      /* WSAEPROTOTYPE is EPROTOTYPE */
-      /* WSAENOPROTOOPT is ENOPROTOOPT */
-      /* WSAEPROTONOSUPPORT is EPROTONOSUPPORT */
-      /* WSAESOCKTNOSUPPORT is ESOCKTNOSUPPORT */
-      /* WSAEOPNOTSUPP is EOPNOTSUPP */
-      /* WSAEPFNOSUPPORT is EPFNOSUPPORT */
-      /* WSAEAFNOSUPPORT is EAFNOSUPPORT */
-      /* WSAEADDRINUSE is EADDRINUSE */
-      /* WSAEADDRNOTAVAIL is EADDRNOTAVAIL */
-      /* WSAENETDOWN is ENETDOWN */
-      /* WSAENETUNREACH is ENETUNREACH */
-      /* WSAENETRESET is ENETRESET */
-      /* WSAECONNABORTED is ECONNABORTED */
-      /* WSAECONNRESET is ECONNRESET */
-      /* WSAENOBUFS is ENOBUFS */
-      /* WSAEISCONN is EISCONN */
-      /* WSAENOTCONN is ENOTCONN */
-      /* WSAESHUTDOWN is ESHUTDOWN */
-      /* WSAETOOMANYREFS is ETOOMANYREFS */
-      /* WSAETIMEDOUT is ETIMEDOUT */
-      /* WSAECONNREFUSED is ECONNREFUSED */
-      /* WSAELOOP is ELOOP */
-      /* WSAENAMETOOLONG maps to ENAMETOOLONG */
-      /* WSAEHOSTDOWN is EHOSTDOWN */
-      /* WSAEHOSTUNREACH is EHOSTUNREACH */
-      /* WSAENOTEMPTY maps to ENOTEMPTY */
-      /* WSAEPROCLIM is EPROCLIM */
-      /* WSAEUSERS is EUSERS */
-      /* WSAEDQUOT is EDQUOT */
-      /* WSAESTALE is ESTALE */
-      /* WSAEREMOTE is EREMOTE */
-      case WSASYSNOTREADY:
-        msg = "Network subsystem is unavailable";
-        break;
-      case WSAVERNOTSUPPORTED:
-        msg = "Winsock.dll version out of range";
-        break;
-      case WSANOTINITIALISED:
-        msg = "Successful WSAStartup not yet performed";
-        break;
-      case WSAEDISCON:
-        msg = "Graceful shutdown in progress";
-        break;
-      case WSAENOMORE: case WSA_E_NO_MORE:
-        msg = "No more results";
-        break;
-      case WSAECANCELLED: case WSA_E_CANCELLED:
-        msg = "Call was canceled";
-        break;
-      case WSAEINVALIDPROCTABLE:
-        msg = "Procedure call table is invalid";
-        break;
-      case WSAEINVALIDPROVIDER:
-        msg = "Service provider is invalid";
-        break;
-      case WSAEPROVIDERFAILEDINIT:
-        msg = "Service provider failed to initialize";
-        break;
-      case WSASYSCALLFAILURE:
-        msg = "System call failure";
-        break;
-      case WSASERVICE_NOT_FOUND:
-        msg = "Service not found";
-        break;
-      case WSATYPE_NOT_FOUND:
-        msg = "Class type not found";
-        break;
-      case WSAEREFUSED:
-        msg = "Database query was refused";
-        break;
-      case WSAHOST_NOT_FOUND:
-        msg = "Host not found";
-        break;
-      case WSATRY_AGAIN:
-        msg = "Nonauthoritative host not found";
-        break;
-      case WSANO_RECOVERY:
-        msg = "Nonrecoverable error";
-        break;
-      case WSANO_DATA:
-        msg = "Valid name, no data record of requested type";
-        break;
-      /* WSA_QOS_* omitted */
-#  endif
-# endif
-
-# if GNULIB_defined_ENOMSG
-      case ENOMSG:
-        msg = "No message of desired type";
-        break;
-# endif
-
-# if GNULIB_defined_EIDRM
-      case EIDRM:
-        msg = "Identifier removed";
-        break;
-# endif
-
-# if GNULIB_defined_ENOLINK
-      case ENOLINK:
-        msg = "Link has been severed";
-        break;
-# endif
-
-# if GNULIB_defined_EPROTO
-      case EPROTO:
-        msg = "Protocol error";
-        break;
-# endif
-
-# if GNULIB_defined_EMULTIHOP
-      case EMULTIHOP:
-        msg = "Multihop attempted";
-        break;
-# endif
-
-# if GNULIB_defined_EBADMSG
-      case EBADMSG:
-        msg = "Bad message";
-        break;
-# endif
-
-# if GNULIB_defined_EOVERFLOW
-      case EOVERFLOW:
-        msg = "Value too large for defined data type";
-        break;
-# endif
-
-# if GNULIB_defined_ENOTSUP
-      case ENOTSUP:
-        msg = "Not supported";
-        break;
-# endif
-
-# if GNULIB_defined_ESTALE
-      case ESTALE:
-        msg = "Stale NFS file handle";
-        break;
-# endif
-
-# if GNULIB_defined_EDQUOT
-      case EDQUOT:
-        msg = "Disk quota exceeded";
-        break;
-# endif
-
-# if GNULIB_defined_ECANCELED
-      case ECANCELED:
-        msg = "Operation canceled";
-        break;
-# endif
-      }
+    char const *msg = strerror_override (errnum);

     if (msg)
       return safe_copy (buf, buflen, msg);
   }
-#endif

   {
     int ret;
diff --git a/modules/strerror b/modules/strerror
index 0e7a254..804df27 100644
--- a/modules/strerror
+++ b/modules/strerror
@@ -3,15 +3,14 @@ strerror() function: return string describing error code.

 Files:
 lib/strerror.c
-lib/strerror-impl.h
 m4/strerror.m4

 Depends-on:
 string
-errno            [test $REPLACE_STRERROR = 1]
-intprops         [test $REPLACE_STRERROR = 1]
-verify           [test $REPLACE_STRERROR = 1]
-strerror_r-posix [test $REPLACE_STRERROR = 1]
+errno             [test $REPLACE_STRERROR = 1]
+intprops          [test $REPLACE_STRERROR = 1]
+strerror-override [test $REPLACE_STRERROR = 1]
+verify            [test $REPLACE_STRERROR = 1]

 configure.ac:
 gl_FUNC_STRERROR
diff --git a/modules/strerror-override b/modules/strerror-override
new file mode 100644
index 0000000..a31e8a1
--- /dev/null
+++ b/modules/strerror-override
@@ -0,0 +1,26 @@
+Description:
+strerror_override() function: provide strings for gnulib-specific errno values
+
+Files:
+lib/strerror-override.h
+lib/strerror-override.c
+
+Depends-on:
+errno
+
+configure.ac:
+AC_REQUIRE([gl_HEADER_ERRNO_H])
+if test -n "$ERRNO_H"; then
+  AC_LIBOBJ([strerror-override])
+fi
+
+Makefile.am:
+
+Include:
+"strerror-override.h"
+
+License:
+LGPLv2+
+
+Maintainer:
+all
diff --git a/modules/strerror_r-posix b/modules/strerror_r-posix
index a36f2e6..3c80d79 100644
--- a/modules/strerror_r-posix
+++ b/modules/strerror_r-posix
@@ -10,6 +10,7 @@ string
 extensions
 errno           [test $HAVE_DECL_STRERROR_R = 0 || test $REPLACE_STRERROR_R = 
1]
 lock            [test $HAVE_DECL_STRERROR_R = 0 || test $REPLACE_STRERROR_R = 
1]
+strerror-override [test $HAVE_DECL_STRERROR_R = 0 || test $REPLACE_STRERROR_R 
= 1]

 configure.ac:
 gl_FUNC_STRERROR_R
-- 
1.7.4.4


Reply via email to