From 650d7836e570b6e9c95de173f3870560765fd11c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 12 Nov 2024 12:04:20 +0100 Subject: [PATCH 01/19] configure.ac: report if we would deliver static and/or shared library files Signed-off-by: Jim Klimov --- configure.ac | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configure.ac b/configure.ac index 920612f0..9596eda1 100644 --- a/configure.ac +++ b/configure.ac @@ -200,5 +200,8 @@ AC_MSG_RESULT([ cflags: ${CFLAGS} ${WARNING_CFLAGS} ldflags: ${LDFLAGS} + build shared lib: ${enable_shared} + build static lib: ${enable_static} + tests: ${enable_tests} ]) From 446c2c34f2044bdfad861a4f4726dad61f27386d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 14 Jan 2025 11:26:22 +0100 Subject: [PATCH 02/19] configure.ac: pretty up AC_MSG_RESULT() for current PACKAGE $VERSION string length Signed-off-by: Jim Klimov --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 9596eda1..db82352d 100644 --- a/configure.ac +++ b/configure.ac @@ -189,7 +189,7 @@ AS_IF([test "x$enable_debug" = "xyes"], [ AC_OUTPUT AC_MSG_RESULT([ $PACKAGE $VERSION - =============== + ================ prefix: ${prefix} sysconfdir: ${sysconfdir} From 68791f5e2828cc723397cfe7d0217aabbdb3e43c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 18 Jan 2025 10:00:31 +0100 Subject: [PATCH 03/19] configure.ac: allow to --enable-Werror in test builds Also define WARNING_CXXFLAGS even if not used at the moment; the script already does juggle CXXFLAGS and detects PROG_CXX anyway. Signed-off-by: Jim Klimov --- configure.ac | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index db82352d..4f03561d 100644 --- a/configure.ac +++ b/configure.ac @@ -153,7 +153,9 @@ WARNING_CFLAGS="-Wall \ -Wsign-compare -Wchar-subscripts \ -Wstrict-prototypes -Wshadow \ -Wformat-security" -AC_SUBST([WARNING_CFLAGS]) + +dnl FIXME: define more thoroughly if C++ code ever appears here +WARNING_CXXFLAGS="$WARNING_CFLAGS" # Build options AC_ARG_ENABLE(tests, @@ -186,6 +188,22 @@ AS_IF([test "x$enable_debug" = "xyes"], [ CXXFLAGS="-O2" ]) +dnl NOTE: Do not pass these among C(XX)FLAGS to the configure script itself, +dnl they can break common tests unexpectedly. Variants below should work for +dnl GCC and CLANG, and other compilers that emulate them in terms of CLI API. +AC_ARG_ENABLE([Werror], + [AS_HELP_STRING([--enable-Werror], + [Enable compilation failure on warnings (default is no)])], + [enable_Werror=$enableval], + [enable_Werror=no]) +AS_IF([test "x$enable_Werror" = "xyes"], [ + WARNING_CFLAGS="$WARNING_CFLAGS -Werror" + WARNING_CXXFLAGS="$WARNING_CXXFLAGS -Werror" +]) + +AC_SUBST([WARNING_CFLAGS]) +AC_SUBST([WARNING_CXXFLAGS]) + AC_OUTPUT AC_MSG_RESULT([ $PACKAGE $VERSION From 08cb12f1c4b2709d678128b2348d977d8c50d46b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 18 Jan 2025 10:22:31 +0100 Subject: [PATCH 04/19] src/modbus-tcp.c: fix setsockopt() argument type for WIN32 cross-builds (mingw) Signed-off-by: Jim Klimov --- src/modbus-tcp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/modbus-tcp.c b/src/modbus-tcp.c index 8e5e37cd..8625c183 100644 --- a/src/modbus-tcp.c +++ b/src/modbus-tcp.c @@ -236,7 +236,7 @@ static int _modbus_tcp_set_ipv4_options(int s) /* Set the TCP no delay flag */ /* SOL_TCP = IPPROTO_TCP */ option = 1; - rc = setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &option, sizeof(int)); + rc = setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (const void *)&option, sizeof(option)); if (rc == -1) { return -1; } @@ -264,7 +264,7 @@ static int _modbus_tcp_set_ipv4_options(int s) **/ /* Set the IP low delay option */ option = IPTOS_LOWDELAY; - rc = setsockopt(s, IPPROTO_IP, IP_TOS, &option, sizeof(int)); + rc = setsockopt(s, IPPROTO_IP, IP_TOS, (const void *)&option, sizeof(option)); if (rc == -1) { return -1; } @@ -563,7 +563,7 @@ int modbus_tcp_listen(modbus_t *ctx, int nb_connection) } enable = 1; - if (setsockopt(new_s, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) == -1) { + if (setsockopt(new_s, SOL_SOCKET, SO_REUSEADDR, (const void *)&enable, sizeof(enable)) == -1) { close(new_s); return -1; } @@ -680,7 +680,7 @@ int modbus_tcp_pi_listen(modbus_t *ctx, int nb_connection) continue; } else { int enable = 1; - rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)); + rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const void *)&enable, sizeof(enable)); if (rc != 0) { close(s); if (ctx->debug) { From 63c6f2d063a9a7ff4c1f9b52b4b62873f06125dd Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 18 Jan 2025 10:45:32 +0100 Subject: [PATCH 05/19] configure.ac, src/modbus-tcp.c: import fallback inet_pton() and inet_ntop() from NUT for cross-builds on WIN32 (mingw) Adapted to libmodbus codebase and clang-format Signed-off-by: Jim Klimov --- configure.ac | 102 ++++++++++++++++++++++- src/modbus-tcp.c | 211 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 311 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 4f03561d..2d15d886 100644 --- a/configure.ac +++ b/configure.ac @@ -30,6 +30,8 @@ AC_INIT([libmodbus], AC_CONFIG_SRCDIR([src/modbus.c]) AC_CONFIG_AUX_DIR([build-aux]) AM_INIT_AUTOMAKE([check-news foreign 1.11 silent-rules tar-pax subdir-objects]) +AM_PROG_CC_C_O +AC_PROG_CPP AC_PROG_CC AC_USE_SYSTEM_EXTENSIONS AC_SYS_LARGEFILE @@ -109,7 +111,7 @@ AC_CHECK_DECLS([__CYGWIN__]) AC_SEARCH_LIBS(accept, network socket) # Checks for library functions. -AC_CHECK_FUNCS([accept4 gai_strerror getaddrinfo gettimeofday inet_pton inet_ntop select socket strerror strlcpy]) +AC_CHECK_FUNCS([accept4 gai_strerror getaddrinfo gettimeofday select socket strerror strlcpy]) # Required for MinGW with GCC v4.8.1 on Win7 AC_DEFINE(WINVER, 0x0501, _) @@ -129,12 +131,19 @@ AC_TYPE_UINT32_T AC_TYPE_UINT8_T if test "$os_cygwin" = "false"; then + AC_CHECK_HEADERS([windows.h], HAVE_WINDOWS_H=yes) + # Required for getaddrinfo (TCP IP - IPv6) AC_CHECK_HEADERS([winsock2.h], HAVE_WINSOCK2_H=yes) if test "x$HAVE_WINSOCK2_H" = "xyes"; then LIBS="$LIBS -lws2_32" - AC_SUBST(LIBS) + AC_SUBST(LIBS) fi + + dnl Can bring inet_ntop()/inet_pton()... or not, depending on distro + dnl (e.g. mingw "native" with MSYS2 or cross-built from Linux); that + dnl is further checked below: + AC_CHECK_HEADERS([ws2tcpip.h], HAVE_WS2TCPIP_H=yes) fi if test "$os_sunos" = "true"; then @@ -157,6 +166,95 @@ WARNING_CFLAGS="-Wall \ dnl FIXME: define more thoroughly if C++ code ever appears here WARNING_CXXFLAGS="$WARNING_CFLAGS" +dnl Adapted from NUT v2.8.2 configure.ac : +myCFLAGS="$CFLAGS" +AS_IF([test "${GCC}" = "yes"], + [CFLAGS="$myCFLAGS -Werror -Werror=implicit-function-declaration"], + [dnl # Don't know what to complain about for unknown compilers + dnl # FIXME: We presume here they have at least a "-Werror" option + CFLAGS="$myCFLAGS -Werror" + ]) + +AC_CACHE_CHECK([for inet_ntop() with IPv4 and IPv6 support], + [ac_cv_func_inet_ntop], + [AC_LANG_PUSH([C]) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[ +#if HAVE_WINDOWS_H +# undef inline +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include +# if HAVE_WINSOCK2_H +# include +# endif +# if HAVE_WS2TCPIP_H +# include +# endif +#else +# include +#endif +#include +]], + [[/* const char* inet_ntop(int af, const void* src, char* dst, size_t cnt); */ +char buf[128]; +printf("%s", inet_ntop(AF_INET, "1.2.3.4", buf, 10)); +printf("%s", inet_ntop(AF_INET6, "::1", buf, 10)) +/* autoconf adds ";return 0;" */ +]])], + [ac_cv_func_inet_ntop=yes], [ac_cv_func_inet_ntop=no] + ) + AC_LANG_POP([C]) +]) +AS_IF([test x"${ac_cv_func_inet_ntop}" = xyes], + [AC_DEFINE([HAVE_INET_NTOP], 1, [defined if system has the inet_ntop() method])], + [AC_MSG_WARN([Required C library routine inet_ntop() not found]) + AS_IF([test "${os_win32}" = "true"], [AC_MSG_WARN([Windows antivirus might block this test])]) + ] +) + +AC_CACHE_CHECK([for inet_pton() with IPv4 and IPv6 support], + [ac_cv_func_inet_pton], + [AC_LANG_PUSH([C]) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[ +#if HAVE_WINDOWS_H +# undef inline +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include +# if HAVE_WINSOCK2_H +# include +# endif +# if HAVE_WS2TCPIP_H +# include +# endif +#else +# include +#endif +#include +]], + [[/* int inet_pton(int af, const char *src, char *dst); */ +struct in_addr ipv4; +struct in6_addr ipv6; +printf("%i ", inet_pton(AF_INET, "1.2.3.4", &ipv4)); +printf("%i ", inet_pton(AF_INET6, "::1", &ipv6)) +/* autoconf adds ";return 0;" */ +]])], + [ac_cv_func_inet_pton=yes], [ac_cv_func_inet_pton=no] + ) + AC_LANG_POP([C]) +]) +AS_IF([test x"${ac_cv_func_inet_pton}" = xyes], + [AC_DEFINE([HAVE_INET_PTON], 1, [defined if system has the inet_pton() method])], + [AC_MSG_WARN([Required C library routine inet_pton() not found]) + AS_IF([test "${os_win32}" = "true"], [AC_MSG_WARN([Windows antivirus might block this test])]) + ] +) +CFLAGS="$myCFLAGS" + # Build options AC_ARG_ENABLE(tests, AS_HELP_STRING([--disable-tests], diff --git a/src/modbus-tcp.c b/src/modbus-tcp.c index 8625c183..3337f392 100644 --- a/src/modbus-tcp.c +++ b/src/modbus-tcp.c @@ -68,6 +68,217 @@ #include "modbus-tcp.h" #ifdef OS_WIN32 + +// inet_ntop() and inet_pton() fallbacks picked up from NUT v2.8.2 common/wincompat.c: +#if !HAVE_INET_NTOP +static const char *inet_ntop(int af, const void *src, char *dst, size_t cnt) +{ + /* Instead of WSAAddressToString() consider getnameinfo() if this would in fact + * return decorated addresses (brackets, ports...) as discussed below: + * https://users.ipv6.narkive.com/RXpR5aML/windows-and-inet-ntop-vs-wsaaddresstostring + * https://docs.microsoft.com/en-us/windows/win32/api/ws2tcpip/nf-ws2tcpip-getnameinfo + * https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsaaddresstostringa + */ + switch (af) { + case AF_INET: { + struct sockaddr_in srcaddr; + memset(&srcaddr, 0, sizeof(struct sockaddr_in)); + memcpy(&(srcaddr.sin_addr), src, sizeof(srcaddr.sin_addr)); + srcaddr.sin_family = af; + if (WSAAddressToString((struct sockaddr *) &srcaddr, + sizeof(struct sockaddr_in), + 0, + dst, + (LPDWORD) &cnt) != 0) { + WSAGetLastError(); + return NULL; + } + } break; + + case AF_INET6: + /* NOTE: Since WinXP SP1, with IPv6 installed on the system */ + { + struct sockaddr_in6 srcaddr; + memset(&srcaddr, 0, sizeof(struct sockaddr_in6)); + memcpy(&(srcaddr.sin6_addr), src, sizeof(srcaddr.sin6_addr)); + srcaddr.sin6_family = af; + if (WSAAddressToString((struct sockaddr *) &srcaddr, + sizeof(struct sockaddr_in6), + 0, + dst, + (LPDWORD) &cnt) != 0) { + WSAGetLastError(); + return NULL; + } + } + break; + + default: + errno = EAFNOSUPPORT; + return NULL; + } /* switch */ + + return dst; +} +#endif /* !HAVE_INET_NTOP */ + +#if !HAVE_INET_PTON +/* Fallback implementation of inet_pton() for systems that lack it, + * such as older versions of Windows (including MinGW builds that do + * not specifically target _WIN32_WINNT or newer). + * + * Based on code attributed to Paul Vixie, 1996, + * sourced from https://stackoverflow.com/a/15370175/4715872 + */ + +#define NS_INADDRSZ sizeof(struct in_addr) /* 4 */ +#define NS_IN6ADDRSZ sizeof(struct in6_addr) /* 16 */ +#define NS_INT16SZ sizeof(uint16_t) /* 2 */ + +static int inet_pton4(const char *src, void *dst) +{ + uint8_t tmp[NS_INADDRSZ], *tp; /* for struct in_addr *dst */ + + int saw_digit = 0; + int octets = 0; + int ch; + + *(tp = tmp) = 0; + + while ((ch = *src++) != '\0') { + if (ch >= '0' && ch <= '9') { + uint32_t n = *tp * 10 + (ch - '0'); + + if (saw_digit && *tp == 0) + return 0; + + if (n > 255) + return 0; + + *tp = n; + if (!saw_digit) { + if (++octets > 4) + return 0; + saw_digit = 1; + } + } else if (ch == '.' && saw_digit) { + if (octets == 4) + return 0; + *++tp = 0; + saw_digit = 0; + } else + return 0; + } + if (octets < 4) + return 0; + + memcpy(dst, tmp, NS_INADDRSZ); + + return 1; +} + +static int inet_pton6(const char *src, void *dst) +{ + static const char xdigits[] = "0123456789abcdef"; + uint8_t tmp[NS_IN6ADDRSZ]; /* for struct in6_addr *dst */ + + uint8_t *tp = (uint8_t *) memset(tmp, '\0', NS_IN6ADDRSZ); + uint8_t *endp = tp + NS_IN6ADDRSZ; + uint8_t *colonp = NULL; + + const char *curtok = NULL; + int saw_xdigit = 0; + uint32_t val = 0; + int ch; + + /* Leading :: requires some special handling. */ + if (*src == ':') { + if (*++src != ':') + return 0; + } + + curtok = src; + + while ((ch = tolower(*src++)) != '\0') { + const char *pch = strchr(xdigits, ch); + if (pch != NULL) { + val <<= 4; + val |= (pch - xdigits); + if (val > 0xffff) + return 0; + saw_xdigit = 1; + continue; + } + if (ch == ':') { + curtok = src; + if (!saw_xdigit) { + if (colonp) + return 0; + colonp = tp; + continue; + } else if (*src == '\0') { + return 0; + } + if (tp + NS_INT16SZ > endp) + return 0; + *tp++ = (uint8_t) (val >> 8) & 0xff; + *tp++ = (uint8_t) val & 0xff; + saw_xdigit = 0; + val = 0; + continue; + } + if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && + inet_pton4(curtok, (char *) tp) > 0) { + tp += NS_INADDRSZ; + saw_xdigit = 0; + break; /* '\0' was seen by inet_pton4(). */ + } + return 0; + } + if (saw_xdigit) { + if (tp + NS_INT16SZ > endp) + return 0; + *tp++ = (uint8_t) (val >> 8) & 0xff; + *tp++ = (uint8_t) val & 0xff; + } + if (colonp != NULL) { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const int n = tp - colonp; + int i; + + if (tp == endp) + return 0; + + for (i = 1; i <= n; i++) { + endp[-i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + if (tp != endp) + return 0; + + memcpy(dst, tmp, NS_IN6ADDRSZ); + + return 1; +} + +static int inet_pton(int af, const char *src, void *dst) +{ + switch (af) { + case AF_INET: + return inet_pton4(src, dst); + case AF_INET6: + return inet_pton6(src, dst); + default: + return -1; + } +} +#endif /* !HAVE_INET_PTON */ + static int _modbus_tcp_init_win32(void) { /* Initialise Windows Socket API */ From c7dfb95b4da5ee53af5d6253f93883251e076b33 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 18 Jan 2025 11:01:42 +0000 Subject: [PATCH 06/19] configure.ac: fix detection of netinet/ip.h on platforms where it requires netinet/in.h explicitly included first Looking at FreeBSD, OpenIndiana et al. Signed-off-by: Jim Klimov --- configure.ac | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 2d15d886..831abb98 100644 --- a/configure.ac +++ b/configure.ac @@ -91,7 +91,6 @@ AC_CHECK_HEADERS([ \ linux/serial.h \ netdb.h \ netinet/in.h \ - netinet/ip.h \ netinet/tcp.h \ sys/ioctl.h \ sys/params.h \ @@ -103,6 +102,17 @@ AC_CHECK_HEADERS([ \ unistd.h \ ]) +dnl On some platforms like FreeBSD and OpenIndiana (illumos) the +dnl netinet/ip.h requires netinet/in.h explicitly included first: +AC_CHECK_HEADERS([ \ + netinet/ip.h \ +], [], [], [ + AC_INCLUDES_DEFAULT +#if HAVE_NETINET_IN_H +# include +#endif +]) + # Cygwin defines IPTOS_LOWDELAY but can't handle that flag so it's necessary to # workaround that problem and Cygwin doesn't define MSG_DONTWAIT. AC_CHECK_DECLS([__CYGWIN__]) From 024d58b3a8f01f942f25fe3e7a88bc4304de8d3e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 18 Jan 2025 11:05:25 +0000 Subject: [PATCH 07/19] README.md: clarify possible need for GNU make Signed-off-by: Jim Klimov --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bdf13994..747887b5 100644 --- a/README.md +++ b/README.md @@ -28,8 +28,10 @@ You will only need to install automake, autoconf, libtool and a C compiler (gcc or clang) to compile the library and asciidoc and xmlto to generate the documentation (optional). -To install, just run the usual dance, `./configure && make install`. Run -`./autogen.sh` first to generate the `configure` script if required. +To install, just run the usual dance, `./configure && make install`. +Run `./autogen.sh` first to generate the `configure` script if required. +You may be required to use `gmake` on platforms where default `make` is +different (BSD make, Sun make, etc.) You can change installation directory with prefix option, eg. `./configure --prefix=/usr/local/`. You have to check that the installation library path is From ca8b49985c69e12f6c80730e42cd1098e15c0186 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 18 Jan 2025 20:16:16 +0100 Subject: [PATCH 08/19] GitIgnore src/stamp-h3 Signed-off-by: Jim Klimov --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 8c04291e..61e3525a 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,7 @@ Makefile.in /stamp-h1 src/modbus-version.h src/win32/modbus.dll.manifest +src/stamp-h3 tests/unit-test.h # mkdocs From 9fa858eb2bafdfd3a739518c0d7ea14dbe3b96a8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 18 Jan 2025 14:40:16 +0100 Subject: [PATCH 09/19] src/modbus.c: _modbus_receive_msg(): printf("\n") to flush after angle-bracket debug printout Signed-off-by: Jim Klimov --- src/modbus.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modbus.c b/src/modbus.c index e3737bb2..08bbae70 100644 --- a/src/modbus.c +++ b/src/modbus.c @@ -476,6 +476,7 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) int i; for (i = 0; i < rc; i++) printf("<%.2X>", msg[msg_length + i]); + printf("\n"); } /* Sums bytes received */ From 4d0a737bf8a1d6c806a0402f01533fa76a829109 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 18 Jan 2025 19:37:35 +0100 Subject: [PATCH 10/19] src/modbus.c: _modbus_receive_msg(): if "ctx->backend->select" failed, report it as such (not as generic "select()") Signed-off-by: Jim Klimov --- src/modbus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modbus.c b/src/modbus.c index 08bbae70..eeeed410 100644 --- a/src/modbus.c +++ b/src/modbus.c @@ -414,7 +414,7 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) while (length_to_read != 0) { rc = ctx->backend->select(ctx, &rset, p_tv, length_to_read); if (rc == -1) { - _error_print(ctx, "select"); + _error_print(ctx, "ctx->backend->select"); if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) { #ifdef _WIN32 wsa_err = WSAGetLastError(); From 360c0abf263f51187d8eedd91ccf6c3834b0178d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 18 Jan 2025 17:42:12 +0100 Subject: [PATCH 11/19] src/modbus.c: response_exception(): fflush() before and after vfprintf() to sync the output Signed-off-by: Jim Klimov --- src/modbus.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/modbus.c b/src/modbus.c index eeeed410..6ad0f1fa 100644 --- a/src/modbus.c +++ b/src/modbus.c @@ -756,7 +756,9 @@ static int response_exception(modbus_t *ctx, va_list ap; va_start(ap, template); + fflush(stderr); vfprintf(stderr, template, ap); + fflush(stderr); va_end(ap); } From cbf51f3a1fa311f48300d058e7ccf8c6dd775d98 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 18 Jan 2025 12:36:21 +0100 Subject: [PATCH 12/19] src/modbus-tcp.c: modbus_tcp_listen(): clarify failed TCP listener situations Signed-off-by: Jim Klimov --- src/modbus-tcp.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/modbus-tcp.c b/src/modbus-tcp.c index 3337f392..1084fc8b 100644 --- a/src/modbus-tcp.c +++ b/src/modbus-tcp.c @@ -758,6 +758,8 @@ int modbus_tcp_listen(modbus_t *ctx, int nb_connection) #ifdef OS_WIN32 if (_modbus_tcp_init_win32() == -1) { + if (ctx->debug) + perror("_modbus_tcp_init_win32"); return -1; } #endif @@ -770,11 +772,15 @@ int modbus_tcp_listen(modbus_t *ctx, int nb_connection) new_s = socket(PF_INET, flags, IPPROTO_TCP); if (new_s == -1) { + if (ctx->debug) + perror("socket"); return -1; } enable = 1; if (setsockopt(new_s, SOL_SOCKET, SO_REUSEADDR, (const void *)&enable, sizeof(enable)) == -1) { + if (ctx->debug) + perror("setsockopt"); close(new_s); return -1; } @@ -799,11 +805,15 @@ int modbus_tcp_listen(modbus_t *ctx, int nb_connection) } if (bind(new_s, (struct sockaddr *) &addr, sizeof(addr)) == -1) { + if (ctx->debug) + perror("bind"); close(new_s); return -1; } if (listen(new_s, nb_connection) == -1) { + if (ctx->debug) + perror("listen"); close(new_s); return -1; } From 8641e8792d092a6c113c58bef24ae6b39e0d8a05 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 26 Jan 2025 13:09:29 +0100 Subject: [PATCH 13/19] configure.ac: auto-adjust _PKG_VER_SEPARATOR length to _PKG_VER_TITLE contents in the final report Signed-off-by: Jim Klimov --- configure.ac | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 831abb98..3feb312d 100644 --- a/configure.ac +++ b/configure.ac @@ -312,10 +312,12 @@ AS_IF([test "x$enable_Werror" = "xyes"], [ AC_SUBST([WARNING_CFLAGS]) AC_SUBST([WARNING_CXXFLAGS]) +_PKG_VER_TITLE="$PACKAGE $VERSION" +_PKG_VER_SEPARATOR="`echo "${_PKG_VER_TITLE}" | sed 's,.,=,g'`" AC_OUTPUT AC_MSG_RESULT([ - $PACKAGE $VERSION - ================ + ${_PKG_VER_TITLE} + ${_PKG_VER_SEPARATOR} prefix: ${prefix} sysconfdir: ${sysconfdir} From 20d90a31042e4569363ad272b53afbc28f933f7f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 26 Jan 2025 21:14:27 +0100 Subject: [PATCH 14/19] configure.ac: fix order of AM_PROG_CC_C_O vs. AM_PROG_CC Signed-off-by: Jim Klimov --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 3feb312d..91f9418e 100644 --- a/configure.ac +++ b/configure.ac @@ -30,9 +30,9 @@ AC_INIT([libmodbus], AC_CONFIG_SRCDIR([src/modbus.c]) AC_CONFIG_AUX_DIR([build-aux]) AM_INIT_AUTOMAKE([check-news foreign 1.11 silent-rules tar-pax subdir-objects]) -AM_PROG_CC_C_O AC_PROG_CPP AC_PROG_CC +AM_PROG_CC_C_O AC_USE_SYSTEM_EXTENSIONS AC_SYS_LARGEFILE AC_CONFIG_MACRO_DIR([m4]) From 73afcf8361c0639a350a2c57c2160c1be75dfa02 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 26 Jan 2025 21:17:35 +0100 Subject: [PATCH 15/19] configure.ac: stub AM_SILENT_RULES on platforms that lack it Signed-off-by: Jim Klimov --- configure.ac | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/configure.ac b/configure.ac index 91f9418e..764c63a3 100644 --- a/configure.ac +++ b/configure.ac @@ -36,6 +36,11 @@ AM_PROG_CC_C_O AC_USE_SYSTEM_EXTENSIONS AC_SYS_LARGEFILE AC_CONFIG_MACRO_DIR([m4]) +dnl This feature seems to require automake-1.13 or newer (1.11+ by other info) +dnl On very old systems can comment it away with little loss (then automake-1.10 +dnl is known to suffice): +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])], + [AC_MSG_NOTICE([Silent Rules feature not defined in this automake version, skipped])]) AM_SILENT_RULES([yes]) LIBMODBUS_VERSION_MAJOR=libmodbus_version_major From 225ae04f87407b4e121deca166cd60e6b66ea2f5 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 27 Jan 2025 16:33:32 +0000 Subject: [PATCH 16/19] configure.ac: use a fallback _PKG_VER_SEPARATOR if sed fails Signed-off-by: Jim Klimov --- configure.ac | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 764c63a3..1d3eeea3 100644 --- a/configure.ac +++ b/configure.ac @@ -318,7 +318,8 @@ AC_SUBST([WARNING_CFLAGS]) AC_SUBST([WARNING_CXXFLAGS]) _PKG_VER_TITLE="$PACKAGE $VERSION" -_PKG_VER_SEPARATOR="`echo "${_PKG_VER_TITLE}" | sed 's,.,=,g'`" +_PKG_VER_SEPARATOR="`echo "${_PKG_VER_TITLE}" | sed 's,.,=,g'`" \ +&& test x"${_PKG_VER_SEPARATOR}" != x || _PKG_VER_SEPARATOR="================" AC_OUTPUT AC_MSG_RESULT([ ${_PKG_VER_TITLE} From 4785f5facc2505a1760b2d4f3a917adff265171d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 27 Jan 2025 17:16:40 +0000 Subject: [PATCH 17/19] Makefile.am: avoid AM_MAKEFLAGS values that confuse non-GNU make implementations Signed-off-by: Jim Klimov --- Makefile.am | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 5e9fc7ce..63c16bde 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,8 @@ CLEANFILES = ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} -AM_MAKEFLAGS = --no-print-directory + +# GNU make-ism, precludes builds with BSD and Sun Makes at least +#AM_MAKEFLAGS = --no-print-directory pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libmodbus.pc From 1126701acc49190f68f3a4784d20c0cea3ae10a7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 27 Jan 2025 17:55:37 +0000 Subject: [PATCH 18/19] configure.ac: stub AM_SILENT_RULES on platforms that lack it - and remove the old call Signed-off-by: Jim Klimov --- configure.ac | 1 - 1 file changed, 1 deletion(-) diff --git a/configure.ac b/configure.ac index 1d3eeea3..1b8d1c8f 100644 --- a/configure.ac +++ b/configure.ac @@ -41,7 +41,6 @@ dnl On very old systems can comment it away with little loss (then automake-1.10 dnl is known to suffice): m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])], [AC_MSG_NOTICE([Silent Rules feature not defined in this automake version, skipped])]) -AM_SILENT_RULES([yes]) LIBMODBUS_VERSION_MAJOR=libmodbus_version_major LIBMODBUS_VERSION_MINOR=libmodbus_version_minor From da4a1f0a54d0de077c3eeb71ebd29332f524c4d2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 28 Jan 2025 16:15:14 +0100 Subject: [PATCH 19/19] README.md: document dependency of "make distcheck" on PAX-capable TAR tooling Signed-off-by: Jim Klimov --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 747887b5..5a36e704 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,10 @@ documentation (optional). To install, just run the usual dance, `./configure && make install`. Run `./autogen.sh` first to generate the `configure` script if required. You may be required to use `gmake` on platforms where default `make` is -different (BSD make, Sun make, etc.) +different (BSD make, Sun make, etc.) You may also require GNU `tar` +impementation (or some other archivation tool, possibly `cpio`, that +would be recognized by your installed version of `automake` as supporting +the "pax" archive format) to pass the optional `make distcheck` routine. You can change installation directory with prefix option, eg. `./configure --prefix=/usr/local/`. You have to check that the installation library path is