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