diff --git a/Jenkinsfile-dynamatrix b/Jenkinsfile-dynamatrix index c44e565c52..c8fcb5b80d 100644 --- a/Jenkinsfile-dynamatrix +++ b/Jenkinsfile-dynamatrix @@ -55,8 +55,16 @@ import org.nut.dynamatrix.*; dynacfgPipeline.disableSlowBuildCIBuild_QEMU = false } - dynacfgPipeline.traceBuildShell_configureEnvvars = false// true - dynacfgPipeline.traceBuildShell = false //true + dynacfgPipeline.traceBuildShell_configureEnvvars = false // true + dynacfgPipeline.traceBuildShell = false // true + + //if (false) // <<< (Un-)comment away in select runs/branches + //if (true) // <<< (Un-)comment away in select runs/branches + if ( env?.BRANCH_NAME ==~ /.*fightwarn-verbose.*/ ) + { + dynacfgPipeline.traceBuildShell_configureEnvvars = true // false + dynacfgPipeline.traceBuildShell = true // false + } dynacfgPipeline.failFast = //true // false @@ -98,7 +106,7 @@ import org.nut.dynamatrix.*; //'stageNameFunc': null, //'dynamatrixAxesLabels': [~/^OS_.+/, 'MAKE'], 'dynamatrixAxesLabels': ['OS_FAMILY', 'OS_DISTRO', 'MAKE'], - 'single': '( \${MAKE} shellcheck )', + 'single': '( if [ x"\${MAKE-}" = x ]; then echo "WARNING: MAKE is somehow unset, defaulting!" >&2; MAKE=make; fi; \${MAKE} shellcheck )', 'multi': '(cd tests && SERVICE_FRAMEWORK="selftest" SHELL_PROGS="$SHELL_PROGS" ./nut-driver-enumerator-test.sh )', 'multiLabel': 'SHELL_PROGS', 'skipShells': [ 'zsh', 'tcsh', 'csh' ] @@ -233,7 +241,10 @@ import org.nut.dynamatrix.*; if (!dynacfgPipeline.containsKey('buildPhases')) { dynacfgPipeline.buildPhases = [:] } - dynacfgPipeline.buildPhases['distcheck'] = """( eval \${CONFIG_ENVVARS} time \${MAKE} \${MAKE_OPTS} distcheck DISTCHECK_FLAGS="\${CONFIG_OPTS}" )""" + + // Imported from jenkins-dynamatrix JSL vars/autotools.groovy: + // a workaround for the cases of curiously missing MAKE envvar... + dynacfgPipeline.buildPhases['distcheck'] = """( if [ x"\${MAKE-}" = x ]; then echo "WARNING: MAKE is somehow unset, defaulting!" >&2; MAKE=make; fi; eval \${CONFIG_ENVVARS} time \${MAKE} \${MAKE_OPTS} distcheck DISTCHECK_FLAGS="\${CONFIG_OPTS}" )""" // Note: shellcheck/spellcheck/... require autotools currently // or need to be redefined with respective BUILD_TYPE @@ -246,7 +257,8 @@ import org.nut.dynamatrix.*; def dsbcClone = dsbc.clone() stage('Investigate envvars (Autotools DEBUG)') { - echo "Running default custom build for '${stageNameClone}' ==> ${dsbcClone.toString()}" + echo "Running default custom build for '${stageNameClone}' ==> ${dsbcClone.toString()}" + + (dynacfgPipeline?.configureEnvvars ? "" : " (note: has no dynacfgPipeline.configureEnvvars)") // Trick about endianness via ELF binary header picked up from https://serverfault.com/a/749469/490516 sh label: 'Inspect initial envvars', script: """ hostname; date -u; uname -a echo "LONG_BIT:`getconf LONG_BIT` WORD_BIT:`getconf WORD_BIT`" || true @@ -275,7 +287,8 @@ set | sort -n """ def dsbcClone = dsbc.clone() stage('Investigate envvars (CI_Build DEBUG)') { - echo "Running default custom build for '${stageNameClone}' ==> ${dsbcClone.toString()}" + echo "Running default custom build for '${stageNameClone}' ==> ${dsbcClone.toString()}" + + (dynacfgPipeline?.configureEnvvars ? "" : " (note: has no dynacfgPipeline.configureEnvvars)") // Trick about endianness via ELF binary header picked up from https://serverfault.com/a/749469/490516 sh label: 'Inspect initial envvars', script: """ hostname; date -u; uname -a echo "LONG_BIT:`getconf LONG_BIT` WORD_BIT:`getconf WORD_BIT`" || true @@ -1263,14 +1276,15 @@ def stageNameFunc_ShellcheckCustom(DynamatrixSingleBuildConfig dsbc) { /////////////////////////////////////////////////////////////////////////// - // Hacky big switch for a max debug option - if (true) - if (false) - { +// Hacky big switch for a max debug option +//if (true) // <<< (Un-)comment away in select runs/branches +//if (false) // <<< (Un-)comment away in select runs/branches +if ( env?.BRANCH_NAME ==~ /.*verbose.*/ ) +{ dynamatrixGlobalState.enableDebugTrace = true dynamatrixGlobalState.enableDebugErrors = true dynamatrixGlobalState.enableDebugMilestones = true dynamatrixGlobalState.enableDebugMilestonesDetails = true - } +} dynamatrixPipeline(dynacfgBase, dynacfgPipeline) diff --git a/clients/upsclient.c b/clients/upsclient.c index 22604a9ada..74290cd26f 100644 --- a/clients/upsclient.c +++ b/clients/upsclient.c @@ -909,6 +909,10 @@ static int upscli_sslinit(UPSCONN_t *ups, int verifycert) return -1; } +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_CAST_FUNCTION_TYPE_STRICT) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-function-type-strict" +#endif if (verifycert) { status = SSL_AuthCertificateHook(ups->ssl, (SSLAuthCertificate)AuthCertificate, CERT_GetDefaultCertDB()); @@ -938,6 +942,9 @@ static int upscli_sslinit(UPSCONN_t *ups, int verifycert) nss_error("upscli_sslinit / SSL_HandshakeCallback"); return -1; } +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_CAST_FUNCTION_TYPE_STRICT) +#pragma GCC diagnostic pop +#endif cert = upscli_find_host_cert(ups->host); if (cert != NULL && cert->certname != NULL) { diff --git a/clients/upssched.c b/clients/upssched.c index 4b8e9c4ba9..029736bf07 100644 --- a/clients/upssched.c +++ b/clients/upssched.c @@ -959,7 +959,7 @@ static void start_daemon(TYPE_FD lockfd) if (d > 0 && d < 0.2) { d = (1.0 - d) * 1000000.0; upsdebugx(5, "Enforcing a throttling sleep: %f usec", d); - usleep(d); + usleep((useconds_t)d); } } } diff --git a/common/common.c b/common/common.c index 89991619cb..c12587ae1d 100644 --- a/common/common.c +++ b/common/common.c @@ -687,7 +687,7 @@ double difftimeval(struct timeval x, struct timeval y) result.tv_sec = x.tv_sec - y.tv_sec; result.tv_usec = x.tv_usec - y.tv_usec; - d = 0.000001 * result.tv_usec + result.tv_sec; + d = 0.000001 * (double)(result.tv_usec) + (double)(result.tv_sec); return d; } @@ -718,7 +718,7 @@ static usec_t timespec_load(const struct timespec *ts) { if (ts->tv_sec < 0 || ts->tv_nsec < 0) return USEC_INFINITY; - if ((usec_t) ts->tv_sec > (UINT64_MAX - (ts->tv_nsec / NSEC_PER_USEC)) / USEC_PER_SEC) + if ((usec_t) ts->tv_sec > (UINT64_MAX - ((uint64_t)(ts->tv_nsec) / NSEC_PER_USEC)) / USEC_PER_SEC) return USEC_INFINITY; return @@ -767,7 +767,7 @@ double difftimespec(struct timespec x, struct timespec y) result.tv_sec = x.tv_sec - y.tv_sec; result.tv_nsec = x.tv_nsec - y.tv_nsec; - d = 0.000000001 * result.tv_nsec + result.tv_sec; + d = 0.000000001 * (double)(result.tv_nsec) + (double)(result.tv_sec); return d; } #endif /* HAVE_CLOCK_GETTIME && HAVE_CLOCK_MONOTONIC */ @@ -1265,7 +1265,7 @@ static void vupslog(int priority, const char *fmt, va_list va, int use_strerror) if (((uintmax_t)ret) > (SIZE_MAX - LARGEBUF)) { goto vupslog_too_long; } - newbufsize = ret + LARGEBUF; + newbufsize = (size_t)ret + LARGEBUF; } /* else: errno, e.g. ERANGE printing: * "...(34 => Result too large)" */ if (nut_debug_level > 0) { diff --git a/common/wincompat.c b/common/wincompat.c index 4d3467e3d5..745b0bf9e3 100644 --- a/common/wincompat.c +++ b/common/wincompat.c @@ -22,6 +22,17 @@ #include "wincompat.h" #include "nut_stdint.h" +#if ! HAVE_INET_PTON +# include +# include +# if HAVE_WINSOCK2_H +# include +# endif +# if HAVE_WS2TCPIP_H +# include +# endif +#endif + #if (0) extern int errno; #endif @@ -204,6 +215,181 @@ const char* inet_ntop(int af, const void* src, char* dst, size_t cnt) } #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; +} + +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 */ + /* "system" call seems to handle path with blank name incorrectly */ int win_system(const char * command) { @@ -1448,9 +1634,9 @@ speed_t cfgetospeed(const struct termios *t) return t->c_ospeed; } -#else +#else /* !WIN32 */ /* Just avoid: ISO C forbids an empty translation unit [-Werror=pedantic] */ int main (int argc, char ** argv); -#endif +#endif /* WIN32 */ diff --git a/configure.ac b/configure.ac index 313870565a..66821dde42 100644 --- a/configure.ac +++ b/configure.ac @@ -1171,8 +1171,100 @@ 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_CASE([${target_os}], - [*mingw*], [AC_MSG_WARN([Windows antivirus might block this test])] - ) + [*mingw*], [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]) + dnl e.g. add "-lws2_32" for mingw builds + dnl the NETLIBS are set by NUT_CHECK_SOCKETLIB above + SAVED_LIBS="$LIBS" + LIBS="$LIBS $NETLIBS" + AX_RUN_OR_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]) + LIBS="$SAVED_LIBS" +]) +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_CASE([${target_os}], + [*mingw*], [AC_MSG_WARN([Windows antivirus might block this test])] + ) + ] + ) + +AC_CACHE_CHECK([for struct pollfd], + [ac_cv_struct_pollfd], + [AC_LANG_PUSH([C]) + dnl e.g. add "-lws2_32" for mingw builds + dnl the NETLIBS are set by NUT_CHECK_SOCKETLIB above + SAVED_LIBS="$LIBS" + LIBS="$LIBS $NETLIBS" + AX_RUN_OR_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 +]], + [[ +struct pollfd pfd; +pfd.fd = 0; +/* autoconf adds ";return 0;" */ +]])], + [ac_cv_struct_pollfd=yes], [ac_cv_struct_pollfd=no] + ) + AC_LANG_POP([C]) + LIBS="$SAVED_LIBS" +]) +AS_IF([test x"${ac_cv_struct_pollfd}" = xyes], + [AC_DEFINE([HAVE_STRUCT_POLLFD], 1, [defined if system has the struct pollfd type])], + [AC_MSG_WARN([Required C library type struct pollfd not found]) + AS_CASE([${target_os}], + [*mingw*], [AC_MSG_WARN([Windows antivirus might block this test])] + ) ] ) diff --git a/data/driver.list.in b/data/driver.list.in index d1eb3951e2..8d9b56e0b0 100644 --- a/data/driver.list.in +++ b/data/driver.list.in @@ -236,6 +236,7 @@ "Cyber Power Systems" "ups" "3" "CP1350AVRLCD" "USB" "usbhid-ups" "Cyber Power Systems" "ups" "3" "CP1500AVRLCD" "USB" "usbhid-ups" "Cyber Power Systems" "ups" "3" "CP850PFCLCD" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/605 +"Cyber Power Systems" "ups" "3" "CP1350PFCLCD" "USB" "usbhid-ups" # https://alioth-lists.debian.net/pipermail/nut-upsuser/2023-October/013441.html "Cyber Power Systems" "ups" "3" "CP1500PFCLCD" "USB" "usbhid-ups" # https://www.cyberpowersystems.com/product/ups/cp1500pfclcd/ https://github.com/networkupstools/nut/issues/520 "Cyber Power Systems" "ups" "3" "CPJ500" "USB" "usbhid-ups" # https://www.cyberpower.com/jp/ja/product/sku/cpj500#downloads https://github.com/networkupstools/nut/issues/1403 "Cyber Power Systems" "ups" "3" "CP900AVR" "USB" "usbhid-ups" diff --git a/drivers/apcupsd-ups.c b/drivers/apcupsd-ups.c index cf6443f385..82bc3af631 100644 --- a/drivers/apcupsd-ups.c +++ b/drivers/apcupsd-ups.c @@ -31,7 +31,25 @@ # include /* nfds_t */ #else typedef unsigned long int nfds_t; -#endif + +# ifndef POLLRDNORM +# define POLLRDNORM 0x0100 +# endif +# ifndef POLLRDBAND +# define POLLRDBAND 0x0200 +# endif +# ifndef POLLIN +# define POLLIN (POLLRDNORM | POLLRDBAND) +# endif +# if ! HAVE_STRUCT_POLLFD +typedef struct pollfd { + SOCKET fd; + short events; + short revents; +} pollfd_t; +# define HAVE_STRUCT_POLLFD 1 +# endif +#endif /* !HAVE_POLL_H */ #include "main.h" #include "apcupsd-ups.h" diff --git a/drivers/clone.c b/drivers/clone.c index c12cc55d4b..9f963b09a6 100644 --- a/drivers/clone.c +++ b/drivers/clone.c @@ -570,7 +570,7 @@ void upsdrv_updateinfo(void) if (ups.timer.shutdown >= 0) { - ups.timer.shutdown -= difftime(now, last_poll); + ups.timer.shutdown -= (suseconds_t)(difftime(now, last_poll)); if (ups.timer.shutdown < 0) { const char *val; @@ -589,7 +589,7 @@ void upsdrv_updateinfo(void) } else if (ups.timer.start >= 0) { if (online) { - ups.timer.start -= difftime(now, last_poll); + ups.timer.start -= (suseconds_t)(difftime(now, last_poll)); } else { ups.timer.start = ondelay; } diff --git a/drivers/dummy-ups.c b/drivers/dummy-ups.c index 8a58242bce..3b4be2436c 100644 --- a/drivers/dummy-ups.c +++ b/drivers/dummy-ups.c @@ -130,7 +130,7 @@ void upsdrv_initinfo(void) /* Set max length for strings, if needed */ if (item->info_flags & ST_FLAG_STRING) - dstate_setaux(item->info_type, item->info_len); + dstate_setaux(item->info_type, (long)item->info_len); } } @@ -578,7 +578,7 @@ static int setvar(const char *varname, const char *val) /* Set max length for strings, if needed */ if (item->info_flags & ST_FLAG_STRING) - dstate_setaux(item->info_type, item->info_len); + dstate_setaux(item->info_type, (long)item->info_len); } else { diff --git a/drivers/main.c b/drivers/main.c index c48e291ef7..919355fda9 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -1920,7 +1920,7 @@ int main(int argc, char **argv) * approach (kill sibling if needed, recapture device, * command it...) */ - int cmdret = -1; + ssize_t cmdret = -1; struct timeval tv; /* Post the query and wait for reply */ @@ -1942,13 +1942,13 @@ int main(int argc, char **argv) if (cmdret < 0) { upsdebugx(1, "Socket dialog with the other driver instance: %s", strerror(errno)); } else { - upslogx(LOG_INFO, "Request to killpower via running driver returned code %d", cmdret); + upslogx(LOG_INFO, "Request to killpower via running driver returned code %" PRIiSIZE, cmdret); if (cmdret == 0) /* Note: many drivers would abort with - * "shutdown not supported" at this - * point... we would too, but later - * and at a higher time/processing cost. - */ + * "shutdown not supported" at this + * point... we would too, but later + * and at a higher time/processing cost. + */ exit (EXIT_SUCCESS); /* else fall through to legacy handling */ } @@ -1966,7 +1966,7 @@ int main(int argc, char **argv) if (cmd && !strcmp(cmd, SIGCMD_RELOAD_OR_ERROR)) #endif /* WIN32 */ { /* Not a signal, but a socket protocol action */ - int cmdret = -1; + ssize_t cmdret = -1; char buf[LARGEBUF]; struct timeval tv; @@ -1982,11 +1982,11 @@ int main(int argc, char **argv) upslog_with_errno(LOG_ERR, "Socket dialog with the other driver instance"); } else { /* TODO: handle buf reply contents */ - upslogx(LOG_INFO, "Request to reload-or-error returned code %d", cmdret); + upslogx(LOG_INFO, "Request to reload-or-error returned code %" PRIiSIZE, cmdret); } /* exit((cmdret == 0) ? EXIT_SUCCESS : EXIT_FAILURE); */ - exit((cmdret < 0) ? 255 : cmdret); + exit(((cmdret < 0) || (((uintmax_t)cmdret) > ((uintmax_t)INT_MAX))) ? 255 : (int)cmdret); } #ifndef WIN32 @@ -2257,6 +2257,12 @@ int main(int argc, char **argv) ) { #ifndef WIN32 int allOk = 1; + /* Use file descriptor, not name, to first check and then manipulate permissions: + * https://cwe.mitre.org/data/definitions/367.html + * https://wiki.sei.cmu.edu/confluence/display/c/FIO01-C.+Be+careful+using+functions+that+use+file+names+for+identification + */ + TYPE_FD fd = ERROR_FD; + /* Tune group access permission to the pipe, * so that upsd can access it (using the * specified or retained default group): @@ -2273,22 +2279,40 @@ int main(int argc, char **argv) group, strerror(errno) ); allOk = 0; + goto sockname_ownership_finished; } else { struct stat statbuf; mode_t mode; - if (chown(sockname, -1, grp->gr_gid)) { - upsdebugx(1, "WARNING: chown failed: %s", + + if (INVALID_FD((fd = open(sockname, O_RDWR | O_APPEND)))) { + upsdebugx(1, "WARNING: opening socket file for stat/chown failed: %s", strerror(errno) ); allOk = 0; + /* Can not proceed with ops below */ + goto sockname_ownership_finished; } - if (stat(sockname, &statbuf)) { + if (fstat(fd, &statbuf)) { + upsdebugx(1, "WARNING: stat for chown failed: %s", + strerror(errno) + ); + allOk = 0; + } else { + /* Here we do a portable chgrp() essentially: */ + if (fchown(fd, statbuf.st_uid, grp->gr_gid)) { + upsdebugx(1, "WARNING: chown failed: %s", + strerror(errno) + ); + allOk = 0; + } + } + + /* Refresh file info */ + if (fstat(fd, &statbuf)) { /* Logically we'd fail chown above if file - * does not exist or is not accessible, but - * practically we only need stat for chmod - */ - upsdebugx(1, "WARNING: stat failed: %s", + * does not exist or is not accessible */ + upsdebugx(1, "WARNING: stat for chmod failed: %s", strerror(errno) ); allOk = 0; @@ -2297,7 +2321,7 @@ int main(int argc, char **argv) mode = statbuf.st_mode; mode |= S_IWGRP; mode |= S_IRGRP; - if (chmod(sockname, mode)) { + if (fchmod(fd, mode)) { upsdebugx(1, "WARNING: chmod failed: %s", strerror(errno) ); @@ -2306,6 +2330,12 @@ int main(int argc, char **argv) } } +sockname_ownership_finished: + if (VALID_FD(fd)) { + close(fd); + fd = ERROR_FD; + } + if (allOk) { upsdebugx(1, "Group access for this driver successfully fixed"); } else { diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index 3f273e5d19..05f54564ce 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -324,7 +324,7 @@ ssize_t upsdrvquery_read_timeout(udq_pipe_conn_t *conn, struct timeval tv) { ssize_t upsdrvquery_write(udq_pipe_conn_t *conn, const char *buf) { size_t buflen = strlen(buf); #ifndef WIN32 - int ret; + ssize_t ret; #else DWORD bytesWritten = 0; BOOL result = FALSE; @@ -384,7 +384,7 @@ ssize_t upsdrvquery_prepare(udq_pipe_conn_t *conn, struct timeval tv) { char *buf; upsdrvquery_read_timeout(conn, tv); gettimeofday(&now, NULL); - if (difftimeval(now, start) > (tv.tv_sec + 0.000001 * tv.tv_usec)) { + if (difftimeval(now, start) > ((double)(tv.tv_sec) + 0.000001 * (double)(tv.tv_usec))) { upsdebugx(5, "%s: requested timeout expired", __func__); break; } @@ -414,7 +414,7 @@ ssize_t upsdrvquery_prepare(udq_pipe_conn_t *conn, struct timeval tv) { } /* Diminishing timeouts for read() */ - tv.tv_usec -= difftimeval(now, start); + tv.tv_usec -= (suseconds_t)(difftimeval(now, start)); while (tv.tv_usec < 0) { tv.tv_sec--; tv.tv_usec = 1000000 + tv.tv_usec; // Note it is negative @@ -563,7 +563,7 @@ ssize_t upsdrvquery_request( continue; } - if (difftimeval(now, start) > (tv.tv_sec + 0.000001 * tv.tv_usec)) { + if (difftimeval(now, start) > ((double)(tv.tv_sec) + 0.000001 * (double)(tv.tv_usec))) { upsdebugx(5, "%s: timed out waiting for expected response", __func__); return -1; diff --git a/include/wincompat.h b/include/wincompat.h index c2fa2f8c1c..c5178d05c9 100644 --- a/include/wincompat.h +++ b/include/wincompat.h @@ -95,10 +95,14 @@ int sktclose(int fh); */ const char* inet_ntop(int af, const void* src, char* dst, int cnt); # else -const char* inet_ntop(int af, const void* src, char* dst, size_t cnt); +const char* inet_ntop(int af, const void* src, char* dst, size_t /* socklen_t */ cnt); # endif #endif +#if ! HAVE_INET_PTON +int inet_pton(int af, const char *src, void *dst); +#endif + /* from the MSDN getaddrinfo documentation : */ #define EAI_AGAIN WSATRY_AGAIN #define EAI_BADFLAGS WSAEINVAL diff --git a/m4/ax_c_pragmas.m4 b/m4/ax_c_pragmas.m4 index 14ecd596d3..070d82beee 100644 --- a/m4/ax_c_pragmas.m4 +++ b/m4/ax_c_pragmas.m4 @@ -674,6 +674,33 @@ dnl ### [CFLAGS="${CFLAGS_SAVED} -Werror=pragmas -Werror=unknown-warning" AC_DEFINE([HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_CAST_ALIGN_BESIDEFUNC], 1, [define if your compiler has #pragma GCC diagnostic ignored "-Wcast-align" (outside functions)]) ]) + AC_CACHE_CHECK([for pragma GCC diagnostic ignored "-Wcast-function-type-strict"], + [ax_cv__pragma__gcc__diags_ignored_cast_function_type_strict], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[void func(void) { +#pragma GCC diagnostic ignored "-Wcast-function-type-strict" +} +]], [])], + [ax_cv__pragma__gcc__diags_ignored_cast_function_type_strict=yes], + [ax_cv__pragma__gcc__diags_ignored_cast_function_type_strict=no] + )] + ) + AS_IF([test "$ax_cv__pragma__gcc__diags_ignored_cast_function_type_strict" = "yes"],[ + AC_DEFINE([HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_CAST_FUNCTION_TYPE_STRICT], 1, [define if your compiler has #pragma GCC diagnostic ignored "-Wcast-function-type-strict"]) + ]) + + AC_CACHE_CHECK([for pragma GCC diagnostic ignored "-Wcast-function-type-strict" (outside functions)], + [ax_cv__pragma__gcc__diags_ignored_cast_function_type_strict_besidefunc], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[#pragma GCC diagnostic ignored "-Wcast-function-type-strict"]], [])], + [ax_cv__pragma__gcc__diags_ignored_cast_function_type_strict_besidefunc=yes], + [ax_cv__pragma__gcc__diags_ignored_cast_function_type_strict_besidefunc=no] + )] + ) + AS_IF([test "$ax_cv__pragma__gcc__diags_ignored_cast_function_type_strict_besidefunc" = "yes"],[ + AC_DEFINE([HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_CAST_FUNCTION_TYPE_STRICT_BESIDEFUNC], 1, [define if your compiler has #pragma GCC diagnostic ignored "-Wcast-function-type-strict" (outside functions)]) + ]) + AC_CACHE_CHECK([for pragma GCC diagnostic ignored "-Wstrict-prototypes"], [ax_cv__pragma__gcc__diags_ignored_strict_prototypes], [AC_COMPILE_IFELSE( diff --git a/m4/ax_run_or_link_ifelse.m4 b/m4/ax_run_or_link_ifelse.m4 index 0e36c7efa2..994994b015 100644 --- a/m4/ax_run_or_link_ifelse.m4 +++ b/m4/ax_run_or_link_ifelse.m4 @@ -12,10 +12,16 @@ dnl # [ACTION-IF-CROSS-COMPILING = RUNTIME-ERROR]) dnl # ------------------------------------------------------- AC_DEFUN([AX_RUN_OR_LINK_IFELSE], [ + myCFLAGS="$CFLAGS" + myCXXFLAGS="$CXXFLAGS" + CFLAGS="$myCFLAGS -Werror -Werror=implicit-function-declaration" + CXXFLAGS="$myCXXFLAGS -Werror -Werror=implicit-function-declaration" AC_RUN_IFELSE([$1], [$2], [$3], [ AC_MSG_WARN([Current build is a cross-build, so not running test binaries, just linking them]) AC_LINK_IFELSE([$1], [$2], [$3]) ] ) + CFLAGS="$myCFLAGS" + CXXFLAGS="$myCXXFLAGS" ]) diff --git a/server/netssl.c b/server/netssl.c index 7557f26624..79c5d3175f 100644 --- a/server/netssl.c +++ b/server/netssl.c @@ -356,6 +356,10 @@ void net_starttls(nut_ctype_t *client, size_t numarg, const char **arg) return; } +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_CAST_FUNCTION_TYPE_STRICT) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-function-type-strict" +#endif /* Note cast to SSLAuthCertificate to prevent warning due to * bad function prototype in NSS. */ @@ -386,6 +390,9 @@ void net_starttls(nut_ctype_t *client, size_t numarg, const char **arg) nss_error("net_starttls / SSL_ConfigSecureServer"); return; } +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_CAST_FUNCTION_TYPE_STRICT) +#pragma GCC diagnostic pop +#endif status = SSL_ResetHandshake(client->ssl, PR_TRUE); if (status != SECSuccess) { diff --git a/tests/Makefile.am b/tests/Makefile.am index c063f6dca2..da1c03e4bf 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -24,9 +24,9 @@ nutlogtest_LDADD = $(top_builddir)/common/libcommon.la if REQUIRE_NUT_STRARG check_SCRIPTS += nutlogtest-nofail.sh -CLEANFILES += nutlogtest-nofail.sh nutlogtest +CLEANFILES += nutlogtest-nofail.sh nutlogtest$(EXEEXT) nutlogtest -nutlogtest-nofail.sh: nutlogtest +nutlogtest-nofail.sh: nutlogtest$(EXEEXT) @echo '#!/bin/sh' > $@ @echo 'echo "WARNING: Your C library requires workarounds to print NULL values!" >&2' >> $@ @echo 'echo "If nutlogtest below, or generally some NUT program, crashes with" >&2' >> $@ @@ -37,7 +37,7 @@ nutlogtest-nofail.sh: nutlogtest # NOTE: Keep the line above empty! else -TESTS += nutlogtest +TESTS += nutlogtest$(EXEEXT) endif TESTS += nuttimetest diff --git a/tests/generic_gpio_utest.c b/tests/generic_gpio_utest.c index 542438b021..07a06e6d9f 100644 --- a/tests/generic_gpio_utest.c +++ b/tests/generic_gpio_utest.c @@ -24,6 +24,7 @@ #include "main.h" #include "dstate.h" #include "attribute.h" +#include "nut_stdint.h" #include "generic_gpio_utest.h" #include @@ -54,48 +55,49 @@ void getWithoutUnderscores(char *var) { #define DESCRIPTION "modem and DNS server UPS" int get_test_status(struct gpioups_t *result, int on_fail_path) { - int expecting_failure; - int upsLinesCount; /* no of lines used in rules */ - int upsMaxLine; /* maximum line number referenced in rules */ - int rulesCount; /* rules subitem count: no of NUT states defined in rules*/ - char stateName[12]; /* NUT state name for rules in cRules */ - int subCount; /* element count in translated rules subitem */ - int ruleInt; + int expecting_failure; + int upsLinesCount; /* no of lines used in rules */ + int upsMaxLine; /* maximum line number referenced in rules */ + int rulesCount; /* rules subitem count: no of NUT states defined in rules*/ + char stateName[12]; /* NUT state name for rules in cRules */ + int subCount; /* element count in translated rules subitem */ + int ruleInt; + int i, j; - fEof=fscanf(testData, "%d", &expecting_failure); - if(on_fail_path) { + fEof = fscanf(testData, "%d", &expecting_failure); + if (on_fail_path) { if(expecting_failure) cases_failed++; else cases_passed++; return expecting_failure; } - if(!expecting_failure) { + if (!expecting_failure) { cases_failed++; printf("expecting case to fail\n"); return 1; } - fEof=fscanf(testData, "%d", &upsLinesCount); - if(result->upsLinesCount!=upsLinesCount) { + fEof = fscanf(testData, "%d", &upsLinesCount); + if (result->upsLinesCount!=upsLinesCount) { cases_failed++; printf("expecting upsLinesCount %d, got %d\n", upsLinesCount, result->upsLinesCount); return 1; } - fEof=fscanf(testData, "%d", &upsMaxLine); - if(result->upsMaxLine!=upsMaxLine) { + fEof = fscanf(testData, "%d", &upsMaxLine); + if (result->upsMaxLine!=upsMaxLine) { cases_failed++; printf("expecting rulesCount %d, got %d\n", upsMaxLine, result->upsMaxLine); return 1; } - fEof=fscanf(testData, "%d", &rulesCount); - if(result->rulesCount!=rulesCount) { + fEof = fscanf(testData, "%d", &rulesCount); + if (result->rulesCount!=rulesCount) { cases_failed++; printf("expecting rulesCount %d, got %d\n", rulesCount, result->rulesCount); return 1; } - for(int i=0; irulesCount; i++) { + for (i=0; irulesCount; i++) { fEof=fscanf(testData, "%s", stateName); if(!strcmp(result->rules[i]->stateName,stateName)) { cases_failed++; @@ -108,7 +110,7 @@ int get_test_status(struct gpioups_t *result, int on_fail_path) { printf("expecting subCount %d, got %d for rule %d\n", result->rules[i]->subCount, subCount, i); return 1; } - for(int j=0; jrules[i]->cRules[j]!=ruleInt) { cases_failed++; @@ -124,12 +126,12 @@ int get_test_status(struct gpioups_t *result, int on_fail_path) { void exit(int code) { - if (!done) { - longjmp(env_buffer, 1); - } - else { - _exit(code); - } + if (!done) { + longjmp(env_buffer, 1); + } + else { + _exit(code); + } } int main(int argc, char **argv) { @@ -137,7 +139,8 @@ int main(int argc, char **argv) { char rules[128]; char testType[128]; char testDescFileNameBuf[LARGEBUF]; - char *testDescFileName="generic_gpio_test.txt"; + char *testDescFileName = "generic_gpio_test.txt"; + unsigned int i; test_with_exit=0; @@ -176,42 +179,65 @@ int main(int argc, char **argv) { cases_passed=0; cases_failed=0; fEof = 1; - for(unsigned int i=0; fEof!=EOF; i++) { + for (i=0; fEof!=EOF; i++) { + char fmt[16]; +#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL +#pragma GCC diagnostic push +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL +#pragma GCC diagnostic ignored "-Wformat-nonliteral" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_SECURITY +#pragma GCC diagnostic ignored "-Wformat-security" +#endif + /* To avoid safety warnings, must provide a limit + * here (bufsize - 1), and use fixed format strings + * because scanf() does not support asterisk for + * width specifier; have to create it on the fly. + */ + snprintf(fmt, sizeof(fmt), "%%%" PRIuSIZE "s", sizeof(rules)-1); do { - fEof=fscanf(testData, "%s", rules); + fEof=fscanf(testData, fmt, rules); } while(strcmp("*", rules)); - fEof=fscanf(testData, "%s", testType); - fEof=fscanf(testData, "%s", rules); + snprintf(fmt, sizeof(fmt), "%%%" PRIuSIZE "s", sizeof(testType)-1); + fEof=fscanf(testData, fmt, testType); + snprintf(fmt, sizeof(fmt), "%%%" PRIuSIZE "s", sizeof(rules)-1); + fEof=fscanf(testData, fmt, rules); +#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL +#pragma GCC diagnostic pop +#endif if(fEof!=EOF) { if(!strcmp(testType, "rules")) { struct gpioups_t *upsfdtest=xcalloc(sizeof(*upsfdtest),1); jmp_result = setjmp(env_buffer); if(jmp_result) { /* test case exiting */ generic_gpio_close(upsfdtest); - printf("%s %s test rule %d [%s]\n", pass_fail[get_test_status(upsfdtest, 1)], testType, i, rules); + printf("%s %s test rule %u [%s]\n", pass_fail[get_test_status(upsfdtest, 1)], testType, i, rules); } else { /* run test case */ get_ups_rules(upsfdtest, (unsigned char *)rules); generic_gpio_close(upsfdtest); - printf("%s %s test rule %d [%s]\n", pass_fail[get_test_status(upsfdtest, 0)], testType, i, rules); + printf("%s %s test rule %u [%s]\n", pass_fail[get_test_status(upsfdtest, 0)], testType, i, rules); } } if(!strcmp(testType, "states")) { int expectedStateValue; int calculatedStateValue; struct gpioups_t *upsfdtest=xcalloc(sizeof(*upsfdtest),1); + int j; + get_ups_rules(upsfdtest, (unsigned char *)rules); upsfdtest->upsLinesStates=xcalloc(sizeof(int),upsfdtest->upsLinesCount); - for(int j=0; jupsLinesCount; j++) { + for (j=0; j < upsfdtest->upsLinesCount; j++) { fEof=fscanf(testData, "%d", &upsfdtest->upsLinesStates[j]); } - for(int j=0; jrulesCount; j++) { + for (j=0; j < upsfdtest->rulesCount; j++) { fEof=fscanf(testData, "%d", &expectedStateValue); calculatedStateValue=calc_rule_states(upsfdtest->upsLinesStates, upsfdtest->rules[j]->cRules, upsfdtest->rules[j]->subCount, 0); - if(expectedStateValue==calculatedStateValue) { - printf("%s %s test rule %d [%s]\n", pass_fail[0], testType, i, rules); + if (expectedStateValue==calculatedStateValue) { + printf("%s %s test rule %u [%s]\n", pass_fail[0], testType, i, rules); cases_passed++; } else { - printf("%s %s test rule %d [%s] %s", pass_fail[1], testType, i, rules, upsfdtest->rules[j]->stateName); + printf("%s %s test rule %u [%s] %s", pass_fail[1], testType, i, rules, upsfdtest->rules[j]->stateName); for(int k=0; kupsLinesCount; k++) { printf(" %d", upsfdtest->upsLinesStates[k]); } @@ -227,24 +253,30 @@ int main(int argc, char **argv) { char chargeLow[256]; char charge[256]; struct gpioups_t *upsfdtest=xcalloc(sizeof(*upsfdtest),1); - int failed = 0; - const char *currUpsStatus=NULL; - const char *currChargerStatus=NULL; - const char *currCharge=NULL; + int j; + + /* "volatile" trickery to avoid the likes of: + * error: variable 'failed' might be clobbered by 'longjmp' or 'vfork' [-Werror=clobbered] + * due to presence of setjmp(). + */ + int volatile failed = 0; + const char * volatile currUpsStatus = NULL; + const char * volatile currChargerStatus = NULL; + const char * volatile currCharge = NULL; get_ups_rules(upsfdtest, (unsigned char *)rules); upsfdtest->upsLinesStates=xcalloc(sizeof(int),upsfdtest->upsLinesCount); - for(int j=0; jupsLinesCount; j++) { + for (j = 0; j < upsfdtest->upsLinesCount; j++) { fEof=fscanf(testData, "%d", &upsfdtest->upsLinesStates[j]); } getWithoutUnderscores(upsStatus); getWithoutUnderscores(chargeStatus); getWithoutUnderscores(chargeLow); getWithoutUnderscores(charge); - if(strcmp(chargeLow, ".")) + if (strcmp(chargeLow, ".")) dstate_setinfo("battery.charge.low", "%s", chargeLow); jmp_result = setjmp(env_buffer); - if(jmp_result) { + if (jmp_result) { failed=1; generic_gpio_close(upsfdtest); } else { @@ -259,11 +291,13 @@ int main(int argc, char **argv) { if(!strcmp(chargeLow,".") && !strcmp(charge,".") && currCharge!=NULL) failed=1; generic_gpio_close(upsfdtest); } - printf("%s %s test rule %d [%s] ([%s] %s %s (%s)) ([%s] %s %s)\n", + printf("%s %s test rule %u [%s] ([%s] %s %s (%s)) ([%s] %s %s)\n", pass_fail[failed], testType, i, rules, upsStatus, chargeStatus, charge, chargeLow, - currUpsStatus, currChargerStatus, currCharge); - if(!failed) { + NUT_STRARG(currUpsStatus), + NUT_STRARG(currChargerStatus), + NUT_STRARG(currCharge)); + if (!failed) { cases_passed++; } else { cases_failed++; @@ -275,8 +309,27 @@ int main(int argc, char **argv) { int expecting_failure, failed; char subType[NUT_GPIO_SUBTYPEBUF]; fEof=fscanf(testData, "%d", &expecting_failure); - fEof=fscanf(testData, "%s", chipNameLocal); - fEof=fscanf(testData, "%s", subType); +#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL +#pragma GCC diagnostic push +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL +#pragma GCC diagnostic ignored "-Wformat-nonliteral" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_SECURITY +#pragma GCC diagnostic ignored "-Wformat-security" +#endif + /* To avoid safety warnings, must provide a limit + * here (bufsize - 1), and use fixed format strings + * because scanf() does not support asterisk for + * width specifier; have to create it on the fly. + */ + snprintf(fmt, sizeof(fmt), "%%%us", NUT_GPIO_CHIPNAMEBUF-1); + fEof=fscanf(testData, fmt, chipNameLocal); + snprintf(fmt, sizeof(fmt), "%%%us", NUT_GPIO_SUBTYPEBUF-1); + fEof=fscanf(testData, fmt, subType); +#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL +#pragma GCC diagnostic pop +#endif jmp_result = setjmp(env_buffer); failed = expecting_failure; if(jmp_result) { /* test case exiting */ @@ -304,30 +357,33 @@ int main(int argc, char **argv) { !dstate_getinfo("device.description") || strcmp(dstate_getinfo("device.description"), DESCRIPTION)) failed=1; } if(!strcmp(subType, "updateinfo")) { - for(int k=0; kupsLinesCount; k++) { + int k; + for(k=0; kupsLinesCount; k++) { gpioupsfd->upsLinesStates[k]=-1; } if(expecting_failure) setNextLinesReadToFail(); upsdrv_updateinfo(); - for(int k=0; kupsLinesCount && failed!=1; k++) { + for(k=0; kupsLinesCount && failed!=1; k++) { if(gpioupsfd->upsLinesStates[k]<0) failed=1; } } upsdrv_cleanup(); } - printf("%s %s %s test rule %d [%s] %s %d\n", + printf("%s %s %s test rule %u [%s] %s %d\n", pass_fail[failed], testType, subType, i, rules, chipNameLocal, expecting_failure); - if(!failed) { + if (!failed) { cases_passed++; } else { cases_failed++; } - vartab_free(); vartab_h = NULL; + vartab_free(); + vartab_h = NULL; } } } - printf("test_rules completed. Total cases %d, passed %d, failed %d\n", cases_passed+cases_failed, cases_passed, cases_failed); + printf("test_rules completed. Total cases %d, passed %d, failed %d\n", + cases_passed+cases_failed, cases_passed, cases_failed); fclose(testData); done = 1; } diff --git a/tests/nutlogtest.c b/tests/nutlogtest.c index 5aaad31ea8..b8b51dcf77 100644 --- a/tests/nutlogtest.c +++ b/tests/nutlogtest.c @@ -3,7 +3,7 @@ * do not crash). * * Copyright (C) - * 2020 Jim Klimov + * 2020-2023 Jim Klimov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,6 +19,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "config.h" #include "common.h" int main(void) { diff --git a/tools/nut-scanner/scan_xml_http.c b/tools/nut-scanner/scan_xml_http.c index b9ebcdb907..6348a9bad7 100644 --- a/tools/nut-scanner/scan_xml_http.c +++ b/tools/nut-scanner/scan_xml_http.c @@ -44,6 +44,9 @@ on Windows 2000 and older versions */ #include #include +# if ! HAVE_INET_PTON +# include "wincompat.h" /* fallback inet_ntop where needed */ +# endif #endif #include