| 1 | # strerror_r.m4 serial 24
 | 
|---|
| 2 | dnl Copyright (C) 2002, 2007-2022 Free Software Foundation, Inc.
 | 
|---|
| 3 | dnl This file is free software; the Free Software Foundation
 | 
|---|
| 4 | dnl gives unlimited permission to copy and/or distribute it,
 | 
|---|
| 5 | dnl with or without modifications, as long as this notice is preserved.
 | 
|---|
| 6 | 
 | 
|---|
| 7 | AC_DEFUN([gl_FUNC_STRERROR_R],
 | 
|---|
| 8 | [
 | 
|---|
| 9 |   AC_REQUIRE([gl_STRING_H_DEFAULTS])
 | 
|---|
| 10 |   AC_REQUIRE([gl_FUNC_STRERROR_R_WORKS])
 | 
|---|
| 11 | 
 | 
|---|
| 12 |   dnl Some systems don't declare strerror_r() if _THREAD_SAFE and _REENTRANT
 | 
|---|
| 13 |   dnl are not defined.
 | 
|---|
| 14 |   AC_CHECK_DECLS_ONCE([strerror_r])
 | 
|---|
| 15 |   if test $ac_cv_have_decl_strerror_r = no; then
 | 
|---|
| 16 |     HAVE_DECL_STRERROR_R=0
 | 
|---|
| 17 |   fi
 | 
|---|
| 18 | 
 | 
|---|
| 19 |   if test $ac_cv_func_strerror_r = yes; then
 | 
|---|
| 20 |     if test "$GL_GENERATE_ERRNO_H:$REPLACE_STRERROR_0" = false:0; then
 | 
|---|
| 21 |       if test $gl_cv_func_strerror_r_posix_signature = yes; then
 | 
|---|
| 22 |         case "$gl_cv_func_strerror_r_works" in
 | 
|---|
| 23 |           dnl The system's strerror_r has bugs.  Replace it.
 | 
|---|
| 24 |           *no) REPLACE_STRERROR_R=1 ;;
 | 
|---|
| 25 |         esac
 | 
|---|
| 26 |       else
 | 
|---|
| 27 |         dnl The system's strerror_r() has a wrong signature. Replace it.
 | 
|---|
| 28 |         REPLACE_STRERROR_R=1
 | 
|---|
| 29 |       fi
 | 
|---|
| 30 |     else
 | 
|---|
| 31 |       dnl The system's strerror_r() cannot know about the new errno values we
 | 
|---|
| 32 |       dnl add to <errno.h>, or any fix for strerror(0). Replace it.
 | 
|---|
| 33 |       REPLACE_STRERROR_R=1
 | 
|---|
| 34 |     fi
 | 
|---|
| 35 |   fi
 | 
|---|
| 36 | ])
 | 
|---|
| 37 | 
 | 
|---|
| 38 | # Prerequisites of lib/strerror_r.c.
 | 
|---|
| 39 | AC_DEFUN([gl_PREREQ_STRERROR_R], [
 | 
|---|
| 40 |   AC_REQUIRE([AC_FUNC_STRERROR_R])
 | 
|---|
| 41 |   dnl glibc >= 2.3.4 and cygwin 1.7.9 have a function __xpg_strerror_r.
 | 
|---|
| 42 |   AC_CHECK_FUNCS_ONCE([__xpg_strerror_r])
 | 
|---|
| 43 |   AC_CHECK_FUNCS_ONCE([catgets])
 | 
|---|
| 44 |   AC_CHECK_FUNCS_ONCE([snprintf])
 | 
|---|
| 45 | ])
 | 
|---|
| 46 | 
 | 
|---|
| 47 | # Detect if strerror_r works, but without affecting whether a replacement
 | 
|---|
| 48 | # strerror_r will be used.
 | 
|---|
| 49 | AC_DEFUN([gl_FUNC_STRERROR_R_WORKS],
 | 
|---|
| 50 | [
 | 
|---|
| 51 |   AC_REQUIRE([gl_HEADER_ERRNO_H])
 | 
|---|
| 52 |   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
 | 
|---|
| 53 | 
 | 
|---|
| 54 |   dnl Persuade Android <string.h> to use the GNU strerror_r API,
 | 
|---|
| 55 |   dnl and Solaris <string.h> to declare strerror_r.
 | 
|---|
| 56 |   AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
 | 
|---|
| 57 | 
 | 
|---|
| 58 |   AC_REQUIRE([gl_FUNC_STRERROR_0])
 | 
|---|
| 59 | 
 | 
|---|
| 60 |   AC_CHECK_FUNCS_ONCE([strerror_r])
 | 
|---|
| 61 |   if test $ac_cv_func_strerror_r = yes; then
 | 
|---|
| 62 |     if test "$GL_GENERATE_ERRNO_H:$REPLACE_STRERROR_0" = false:0; then
 | 
|---|
| 63 |       dnl The POSIX prototype is:  int strerror_r (int, char *, size_t);
 | 
|---|
| 64 |       dnl glibc, Cygwin:           char *strerror_r (int, char *, size_t);
 | 
|---|
| 65 |       dnl AIX 5.1, OSF/1 5.1:      int strerror_r (int, char *, int);
 | 
|---|
| 66 |       AC_CACHE_CHECK([for strerror_r with POSIX signature],
 | 
|---|
| 67 |         [gl_cv_func_strerror_r_posix_signature],
 | 
|---|
| 68 |         [AC_COMPILE_IFELSE(
 | 
|---|
| 69 |            [AC_LANG_PROGRAM(
 | 
|---|
| 70 |               [[#include <string.h>
 | 
|---|
| 71 |                 int strerror_r (int, char *, size_t);
 | 
|---|
| 72 |               ]],
 | 
|---|
| 73 |               [])],
 | 
|---|
| 74 |            [gl_cv_func_strerror_r_posix_signature=yes],
 | 
|---|
| 75 |            [gl_cv_func_strerror_r_posix_signature=no])
 | 
|---|
| 76 |         ])
 | 
|---|
| 77 |       if test $gl_cv_func_strerror_r_posix_signature = yes; then
 | 
|---|
| 78 |         dnl AIX 6.1 strerror_r fails by returning -1, not an error number.
 | 
|---|
| 79 |         dnl HP-UX 11.31 strerror_r always fails when the buffer length argument
 | 
|---|
| 80 |         dnl is less than 80.
 | 
|---|
| 81 |         dnl FreeBSD 8.s strerror_r claims failure on 0
 | 
|---|
| 82 |         dnl Mac OS X 10.5 strerror_r treats 0 like -1
 | 
|---|
| 83 |         dnl Solaris 10 strerror_r corrupts errno on failure
 | 
|---|
| 84 |         AC_CACHE_CHECK([whether strerror_r works],
 | 
|---|
| 85 |           [gl_cv_func_strerror_r_works],
 | 
|---|
| 86 |           [AC_RUN_IFELSE(
 | 
|---|
| 87 |              [AC_LANG_PROGRAM(
 | 
|---|
| 88 |                 [[#include <errno.h>
 | 
|---|
| 89 |                   #include <string.h>
 | 
|---|
| 90 |                 ]],
 | 
|---|
| 91 |                 [[int result = 0;
 | 
|---|
| 92 |                   char buf[79];
 | 
|---|
| 93 |                   if (strerror_r (EACCES, buf, 0) < 0)
 | 
|---|
| 94 |                     result |= 1;
 | 
|---|
| 95 |                   errno = 0;
 | 
|---|
| 96 |                   if (strerror_r (EACCES, buf, sizeof buf) != 0)
 | 
|---|
| 97 |                     result |= 2;
 | 
|---|
| 98 |                   strcpy (buf, "Unknown");
 | 
|---|
| 99 |                   if (strerror_r (0, buf, sizeof buf) != 0)
 | 
|---|
| 100 |                     result |= 4;
 | 
|---|
| 101 |                   if (errno)
 | 
|---|
| 102 |                     result |= 8;
 | 
|---|
| 103 |                   if (strstr (buf, "nknown") || strstr (buf, "ndefined"))
 | 
|---|
| 104 |                     result |= 0x10;
 | 
|---|
| 105 |                   errno = 0;
 | 
|---|
| 106 |                   *buf = 0;
 | 
|---|
| 107 |                   if (strerror_r (-3, buf, sizeof buf) < 0)
 | 
|---|
| 108 |                     result |= 0x20;
 | 
|---|
| 109 |                   if (errno)
 | 
|---|
| 110 |                     result |= 0x40;
 | 
|---|
| 111 |                   if (!*buf)
 | 
|---|
| 112 |                     result |= 0x80;
 | 
|---|
| 113 |                   return result;
 | 
|---|
| 114 |                 ]])],
 | 
|---|
| 115 |              [gl_cv_func_strerror_r_works=yes],
 | 
|---|
| 116 |              [gl_cv_func_strerror_r_works=no],
 | 
|---|
| 117 |              [
 | 
|---|
| 118 | changequote(,)dnl
 | 
|---|
| 119 |               case "$host_os" in
 | 
|---|
| 120 |                        # Guess no on AIX.
 | 
|---|
| 121 |                 aix*)  gl_cv_func_strerror_r_works="guessing no";;
 | 
|---|
| 122 |                        # Guess no on HP-UX.
 | 
|---|
| 123 |                 hpux*) gl_cv_func_strerror_r_works="guessing no";;
 | 
|---|
| 124 |                        # Guess no on BSD variants.
 | 
|---|
| 125 |                 *bsd*)  gl_cv_func_strerror_r_works="guessing no";;
 | 
|---|
| 126 |                        # Guess yes otherwise.
 | 
|---|
| 127 |                 *)     gl_cv_func_strerror_r_works="guessing yes";;
 | 
|---|
| 128 |               esac
 | 
|---|
| 129 | changequote([,])dnl
 | 
|---|
| 130 |              ])
 | 
|---|
| 131 |           ])
 | 
|---|
| 132 |       else
 | 
|---|
| 133 |         dnl The system's strerror() has a wrong signature.
 | 
|---|
| 134 |         dnl glibc >= 2.3.4 and cygwin 1.7.9 have a function __xpg_strerror_r.
 | 
|---|
| 135 |         AC_CHECK_FUNCS_ONCE([__xpg_strerror_r])
 | 
|---|
| 136 |         dnl In glibc < 2.14, __xpg_strerror_r does not populate buf on failure.
 | 
|---|
| 137 |         dnl In cygwin < 1.7.10, __xpg_strerror_r clobbers strerror's buffer.
 | 
|---|
| 138 |         if test $ac_cv_func___xpg_strerror_r = yes; then
 | 
|---|
| 139 |           AC_CACHE_CHECK([whether __xpg_strerror_r works],
 | 
|---|
| 140 |             [gl_cv_func_strerror_r_works],
 | 
|---|
| 141 |             [AC_RUN_IFELSE(
 | 
|---|
| 142 |                [AC_LANG_PROGRAM(
 | 
|---|
| 143 |                   [[#include <errno.h>
 | 
|---|
| 144 |                     #include <string.h>
 | 
|---|
| 145 |                     extern
 | 
|---|
| 146 |                     #ifdef __cplusplus
 | 
|---|
| 147 |                     "C"
 | 
|---|
| 148 |                     #endif
 | 
|---|
| 149 |                     int __xpg_strerror_r(int, char *, size_t);
 | 
|---|
| 150 |                   ]],
 | 
|---|
| 151 |                   [[int result = 0;
 | 
|---|
| 152 |                     char buf[256] = "^";
 | 
|---|
| 153 |                     char copy[256];
 | 
|---|
| 154 |                     char *str = strerror (-1);
 | 
|---|
| 155 |                     strcpy (copy, str);
 | 
|---|
| 156 |                     if (__xpg_strerror_r (-2, buf, 1) == 0)
 | 
|---|
| 157 |                       result |= 1;
 | 
|---|
| 158 |                     if (*buf)
 | 
|---|
| 159 |                       result |= 2;
 | 
|---|
| 160 |                     __xpg_strerror_r (-2, buf, 256);
 | 
|---|
| 161 |                     if (strcmp (str, copy))
 | 
|---|
| 162 |                       result |= 4;
 | 
|---|
| 163 |                     return result;
 | 
|---|
| 164 |                   ]])],
 | 
|---|
| 165 |                [gl_cv_func_strerror_r_works=yes],
 | 
|---|
| 166 |                [gl_cv_func_strerror_r_works=no],
 | 
|---|
| 167 |                [dnl Guess no on all platforms that have __xpg_strerror_r,
 | 
|---|
| 168 |                 dnl at least until fixed glibc and cygwin are more common.
 | 
|---|
| 169 |                 gl_cv_func_strerror_r_works="$gl_cross_guess_normal"
 | 
|---|
| 170 |                ])
 | 
|---|
| 171 |             ])
 | 
|---|
| 172 |         fi
 | 
|---|
| 173 |       fi
 | 
|---|
| 174 |     fi
 | 
|---|
| 175 |   fi
 | 
|---|
| 176 | ])
 | 
|---|