]> The Tcpdump Group git mirrors - libpcap/commitdiff
Make sure asprintf() is declared if it's present.
authorGuy Harris <[email protected]>
Tue, 19 Mar 2019 08:41:03 +0000 (01:41 -0700)
committerGuy Harris <[email protected]>
Tue, 19 Mar 2019 08:41:54 +0000 (01:41 -0700)
GNU libc is a pain.  If you don't define _GNU_SOURCE, it doesn't declare
asprintf().  If you *do* define _GNU_SOURCE, the strerror_r() it
declares isn't POSIX-compliant.

We use asprintf() if present, so we need it to be declared; define
_GNU_SOURCE in ftmacros.h.

At configuration time, if we have strerror_r(), check whether it's
GNU-style or POSIX-style, and define different #defines for those two
cases.  Handle GNU-style strerror_r() and POSIX-style strerror_r()
differently in pcap_fmt_errmsg_for_errno().

Make sure everything that uses asprintf() includes ftmacros.h before
including stdio.h.

CMakeLists.txt
cmakeconfig.h.in
config.h.in
configure
configure.ac
fmtutils.c
ftmacros.h
pcap-new.c

index 27ced43b5d0553335970e54c48270b8295ca5435..e6a0c9abe94ce3d761830da0de7c72759cfac791 100644 (file)
@@ -335,7 +335,34 @@ endif(NOT WIN32)
 #
 check_function_exists(strerror HAVE_STRERROR)
 check_function_exists(strerror_r HAVE_STRERROR_R)
-check_function_exists(strerror_s HAVE_STRERROR_S)
+if(HAVE_STRERROR_R)
+    #
+    # We have strerror_r; if we define _GNU_SOURCE, is it a
+    # POSIX-compliant strerror_r() or a GNU strerror_r()?
+    #
+    check_c_source_compiles(
+"#define _GNU_SOURCE
+#include <string.h>
+
+/* Define it GNU-style; that will cause an error if it's not GNU-style */
+extern char *strerror_r(int, char *, size_t);
+
+int
+main(void)
+{
+       return 0;
+}
+"
+            HAVE_GNU_STRERROR_R)
+    if(NOT HAVE_GNU_STRERROR_R)
+        set(HAVE_POSIX_STRERROR_R YES)
+    endif(NOT HAVE_GNU_STRERROR_R)
+else(HAVE_STRERROR_R)
+    #
+    # We don't have strerror_r; do we have strerror_s?
+    #
+    check_function_exists(strerror_s HAVE_STRERROR_S)
+endif(HAVE_STRERROR_R)
 check_function_exists(strlcpy HAVE_STRLCPY)
 check_function_exists(strlcat HAVE_STRLCAT)
 check_function_exists(snprintf HAVE_SNPRINTF)
index 0d963df570b2642eeed96cfb627f81c4be29b460..6472397999a1583ae403a8d906ace0d3a0244a54 100644 (file)
@@ -54,6 +54,9 @@
 /* Define to 1 if you have the `getspnam' function. */
 #cmakedefine HAVE_GETSPNAM 1
 
+/* Define to 1 if you have a GNU-style `strerror_r' function. */
+#cmakedefine HAVE_GNU_STRERROR_R 1
+
 /* on HP-UX 10.20 or later */
 #cmakedefine HAVE_HPUX10_20_OR_LATER 1
 
 /* Define to 1 if Packet32 API (WinPcap NPF driver) is available */
 #cmakedefine HAVE_PACKET32 1
 
+/* Define to 1 if you have a POSIX-style `strerror_r' function. */
+#cmakedefine HAVE_POSIX_STRERROR_R 1
+
 /* define if net/pfvar.h defines PF_NAT through PF_NORDR */
 #cmakedefine HAVE_PF_NAT_THROUGH_PF_NORDR 1
 
 /* Define to 1 if you have the `strerror' function. */
 #cmakedefine HAVE_STRERROR 1
 
-/* Define to 1 if you have the `strerror_r' function. */
-#cmakedefine HAVE_STRERROR_R 1
-
 /* Define to 1 if you have the `strerror_s' function. */
 #cmakedefine HAVE_STRERROR_S 1
 
index b08657fec9c9cc07ed01d312b8e78388dc28ab88..b7ca36c71af6b45bbe5ff0ade9aa9b005133e537 100644 (file)
@@ -60,6 +60,9 @@
 /* Define to 1 if you have the `getspnam' function. */
 #undef HAVE_GETSPNAM
 
+/* Define to 1 if you have a GNU-style `strerror_r' function. */
+#undef HAVE_GNU_STRERROR_R
+
 /* on HP-UX 10.20 or later */
 #undef HAVE_HPUX10_20_OR_LATER
 
 /* define if net/pfvar.h defines PF_NAT through PF_NORDR */
 #undef HAVE_PF_NAT_THROUGH_PF_NORDR
 
+/* Define to 1 if you have a POSIX-style `strerror_r' function. */
+#undef HAVE_POSIX_STRERROR_R
+
 /* Define to 1 if you have the <rte_bus.h> header file. */
 #undef HAVE_RTE_BUS_H
 
 /* Define to 1 if you have the `strerror' function. */
 #undef HAVE_STRERROR
 
-/* Define to 1 if you have the `strerror_r' function. */
-#undef HAVE_STRERROR_R
-
 /* Define to 1 if you have the `strerror_s' function. */
 #undef HAVE_STRERROR_S
 
index 553f138c8281a9a8adc9d0ad67f7b14942f8c52e..b4bcfbba220bcbdd6a2f2473c1eed8bd289e3e20 100755 (executable)
--- a/configure
+++ b/configure
@@ -5340,19 +5340,83 @@ $as_echo "$ac_cv_lbl_gcc_fixincludes" >&6; }
            fi
     fi
 
-for ac_func in strerror strerror_r strerror_s
+for ac_func in strerror
 do :
-  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  ac_fn_c_check_func "$LINENO" "strerror" "ac_cv_func_strerror"
+if test "x$ac_cv_func_strerror" = xyes; then :
   cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+#define HAVE_STRERROR 1
+_ACEOF
+
+fi
+done
+
+ac_fn_c_check_func "$LINENO" "strerror_r" "ac_cv_func_strerror_r"
+if test "x$ac_cv_func_strerror_r" = xyes; then :
+
+       #
+       # We have strerror_r; if we define _GNU_SOURCE, is it a
+       # POSIX-compliant strerror_r() or a GNU strerror_r()?
+       #
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether strerror_r is GNU-style" >&5
+$as_echo_n "checking whether strerror_r is GNU-style... " >&6; }
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+               #define _GNU_SOURCE
+#include <string.h>
+
+/* Define it GNU-style; that will cause an error if it's not GNU-style */
+extern char *strerror_r(int, char *, size_t);
+
+int
+main(void)
+{
+       return 0;
+}
+
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+               # GNU-style
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_GNU_STRERROR_R /**/" >>confdefs.h
+
+
+else
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+$as_echo "#define HAVE_POSIX_STRERROR_R /**/" >>confdefs.h
+
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+else
+
+       #
+       # We don't have strerror_r; do we have strerror_s?
+       #
+       for ac_func in strerror_s
+do :
+  ac_fn_c_check_func "$LINENO" "strerror_s" "ac_cv_func_strerror_s"
+if test "x$ac_cv_func_strerror_s" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_STRERROR_S 1
 _ACEOF
 
 fi
 done
 
 
+fi
+
+
 #
 # Thanks, IBM, for not providing vsyslog() in AIX!
 #
index efffe4d7c867bf3447e0cb4255ec9f12cf668877..91efafc5a43d754d6e225cb1786a361937edca17 100644 (file)
@@ -110,7 +110,48 @@ esac
 
 AC_LBL_FIXINCLUDES
 
-AC_CHECK_FUNCS(strerror strerror_r strerror_s)
+AC_CHECK_FUNCS(strerror)
+AC_CHECK_FUNC(strerror_r,
+    [
+       #
+       # We have strerror_r; if we define _GNU_SOURCE, is it a
+       # POSIX-compliant strerror_r() or a GNU strerror_r()?
+       #
+       AC_MSG_CHECKING(whether strerror_r is GNU-style)
+       AC_COMPILE_IFELSE(
+           [
+               AC_LANG_SOURCE(
+#define _GNU_SOURCE
+#include <string.h>
+
+/* Define it GNU-style; that will cause an error if it's not GNU-style */
+extern char *strerror_r(int, char *, size_t);
+
+int
+main(void)
+{
+       return 0;
+}
+)
+           ],
+           [
+               # GNU-style
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_GNU_STRERROR_R,,
+                   [Define to 1 if you have a GNU-style `strerror_r' function.])
+           ],
+           [
+               AC_MSG_RESULT(no)
+               AC_DEFINE(HAVE_POSIX_STRERROR_R,,
+                   [Define to 1 if you have a POSIX-style `strerror_r' function.])
+           ])
+    ],
+    [
+       #
+       # We don't have strerror_r; do we have strerror_s?
+       #
+       AC_CHECK_FUNCS(strerror_s)
+    ])
 
 #
 # Thanks, IBM, for not providing vsyslog() in AIX!
index 0c527453547f2c2e68d60518f9d070a22b3c6db6..d01dc3e2637b1b36c0ecece6e04ed194753d6a74 100644 (file)
@@ -65,11 +65,6 @@ pcap_fmt_errmsg_for_errno(char *errbuf, size_t errbuflen, int errnum,
        size_t msglen;
        char *p;
        size_t errbuflen_remaining;
-#if defined(HAVE_STRERROR_S)
-       errno_t err;
-#elif defined(HAVE_STRERROR_R)
-       int err;
-#endif
 
        va_start(ap, fmt);
        pcap_vsnprintf(errbuf, errbuflen, fmt, ap);
@@ -96,7 +91,10 @@ pcap_fmt_errmsg_for_errno(char *errbuf, size_t errbuflen, int errnum,
         * Now append the string for the error code.
         */
 #if defined(HAVE_STRERROR_S)
-       err = strerror_s(p, errbuflen_remaining, errnum);
+       /*
+        * We have a Windows-style strerror_s().
+        */
+       errno_t err = strerror_s(p, errbuflen_remaining, errnum);
        if (err != 0) {
                /*
                 * It doesn't appear to be documented anywhere obvious
@@ -104,8 +102,24 @@ pcap_fmt_errmsg_for_errno(char *errbuf, size_t errbuflen, int errnum,
                 */
                pcap_snprintf(p, errbuflen_remaining, "Error %d", errnum);
        }
-#elif defined(HAVE_STRERROR_R)
-       err = strerror_r(errnum, p, errbuflen_remaining);
+#elif defined(HAVE_GNU_STRERROR_R)
+       /*
+        * We have a GNU-style strerror_r(), which is *not* guaranteed to
+        * do anything to the buffer handed to it, and which returns a
+        * pointer to the error string, which may or may not be in
+        * the buffer.
+        *
+        * It is, however, guaranteed to succeed.
+        */
+       char strerror_buf[PCAP_ERRBUF_SIZE];
+       char *errstring = strerror_r(errnum, strerror_buf, PCAP_ERRBUF_SIZE);
+       pcap_snprintf(p, errbuflen_remaining, "%s", errstring);
+#elif defined(HAVE_POSIX_STRERROR_R)
+       /*
+        * We have a POSIX-style strerror_r(), which is guaranteed to fill
+        * in the buffer, but is not guaranteed to succeed.
+        */
+       int err = strerror_r(errnum, p, errbuflen_remaining);
        if (err == EINVAL) {
                /*
                 * UNIX 03 says this isn't guaranteed to produce a
index de8da98e38b6d0bb71bd82a1f1622e8ad9cdddd4..cd3daebdf175e25974c04f1fa91dfc7e70ea26f8 100644 (file)
    */
 #elif defined(__linux__) || defined(linux) || defined(__linux)
   /*
-   * We can't turn _GNU_SOURCE on because some versions of GNU Libc
-   * will give the GNU version of strerror_r(), which returns a
-   * string pointer and doesn't necessarily fill in the buffer,
-   * rather than the standard version of strerror_r(), which
-   * returns 0 or an errno and always fills in the buffer.  We
-   * require both of the latter behaviors.
+   * Turn on _GNU_SOURCE to get everything GNU libc has to offer,
+   * including asprintf().
    *
-   * So we try turning everything else on that we can.  This includes
-   * defining _XOPEN_SOURCE as 600, because we want to force crypt()
-   * to be declared on systems that use GNU libc, such as most Linux
-   * distributions.
+   * Unfortunately, one thing it has to offer is a strerror_r()
+   * that's not POSIX-compliant, but we deal with that in
+   * pcap_fmt_errmsg_for_errno().
    */
-  #define _POSIX_C_SOURCE 200809L
-  #define _XOPEN_SOURCE 600
+  #define _GNU_SOURCE
 
   /*
    * We turn on both _DEFAULT_SOURCE and _BSD_SOURCE to try to get
index 6b333e4e2260d27607f378e358216df8a241a28a..2cce433c4666876be139076e9786d1c4b15db9d1 100644 (file)
@@ -35,6 +35,8 @@
 #include <config.h>
 #endif
 
+#include "ftmacros.h"
+
 /*
  * sockutils.h may include <crtdbg.h> on Windows, and pcap-int.h will
  * include portability.h, and portability.h, on Windows, expects that