getloadavg: Don't clobber LIBS. Regression from previous commit.
[pspp] / lib / strerror.c
index 6137552efd6c9bcb2bbdbf686409d7956efa8f78..d0dd1af98431674050072e6c725a6909408dc5c6 100644 (file)
 /* Specification.  */
 #include <string.h>
 
-#if REPLACE_STRERROR
-
-# include <errno.h>
-# include <stdio.h>
-# include <stdlib.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 
-# include "intprops.h"
-# include "verify.h"
+#include "intprops.h"
+#include "strerror-override.h"
+#include "verify.h"
 
 /* Use the system functions, not the gnulib overrides in this file.  */
-# undef sprintf
+#undef sprintf
 
 char *
 strerror (int n)
+#undef strerror
 {
-  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.  */
+  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;
+
+  /* FreeBSD rejects 0; see http://austingroupbugs.net/view.php?id=382.
+     MacOS X 10.5 does not distinguish 0 from -1.  */
+  if (n)
+    msg = strerror (n);
+  else
+    {
+      int saved_errno = errno;
+      errno = 0;
+      msg = strerror (n);
+      if (errno || (msg &&
+                    (strstr (msg, "nknown") || strstr (msg, "ndefined"))))
+        msg = "Success";
+      errno = saved_errno;
+    }
+
+  /* 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.  This is not thread-safe,
+     even if the system strerror is, but portable programs shouldn't
+     be using strerror if they care about thread-safety.  */
+  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 ();
 
-  {
-    static char const fmt[] = "Unknown error (%d)";
-    verify (sizeof (buf) >= sizeof (fmt) + INT_STRLEN_BOUND (n));
-    sprintf (buf, fmt, n);
-    return buf;
-  }
+  return memcpy (buf, msg, len + 1);
 }
-
-#endif