Home | History | Annotate | Download | only in m4
      1 # strerror_r.m4 serial 15
      2 dnl Copyright (C) 2002, 2007-2012 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_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.
     42 AC_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.
     51 AC_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              [
    115 changequote(,)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
    126 changequote([,])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