1# strerror_r.m4 serial 23 2dnl Copyright (C) 2002, 2007-2021 Free Software Foundation, Inc. 3dnl This file is free software; the Free Software Foundation 4dnl gives unlimited permission to copy and/or distribute it, 5dnl with or without modifications, as long as this notice is preserved. 6 7AC_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 "$ERRNO_H:$REPLACE_STRERROR_0" = :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. 39AC_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. 49AC_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 "$ERRNO_H:$REPLACE_STRERROR_0" = :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 [ 118changequote(,)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 129changequote([,])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]) 177