Skip to content
Merged
3 changes: 3 additions & 0 deletions NEWS.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,9 @@ https://github.com/networkupstools/nut/milestone/12
to bumping the debug verbosity of `upsdrvctl` tool. [#3276]
* If we fail to stop a driver by signal (e.g. PID file was not saved),
retry to `INSTCMD driver.exit` it by socket protocol. [#3277]
* The NUT Integration Testing suite now also involves `upsdrvctl` to
run one driver instance indirectly, helping make check-NIT` catch
portability issues with different builds of the tool. [#2800, #3292]

- `upslog` tool updates:
* Updated `help()` and failure messages to suggest `-m '*,-'` for logging
Expand Down
5 changes: 4 additions & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -6708,10 +6708,13 @@ AS_CASE([${target_os}],
AC_MSG_NOTICE([FWIW, assuming ABS_TOP_SRCDIR="$ABS_TOP_SRCDIR" and ABS_TOP_BUILDDIR="$ABS_TOP_BUILDDIR"])
])

dnl Use these at best for tests (e.g. nutconf), not production code:
dnl Use these at best for tests (e.g. nutconf, NIT), not production code:
AC_DEFINE_UNQUOTED([ABS_TOP_SRCDIR], ["${ABS_TOP_SRCDIR}"], [NUT source directory when the build was configured])
AC_DEFINE_UNQUOTED([ABS_TOP_BUILDDIR], ["${ABS_TOP_BUILDDIR}"], [NUT build directory when the build was configured])

AC_SUBST(ABS_TOP_SRCDIR)
AC_SUBST(ABS_TOP_BUILDDIR)

dnl ---------------------------------------------------------------------
AC_MSG_CHECKING([whether to install External API integration script: Enphase Monitor])
nut_with_extapi_enphase="no"
Expand Down
28 changes: 23 additions & 5 deletions drivers/upsdrvctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -943,23 +943,38 @@ static void forkexec(char *const argv[], const ups_t *ups)
BOOL ret;
DWORD res;
DWORD exit_code = 0;
char commandline[SMALLBUF];
char commandline[LARGEBUF];
STARTUPINFO StartupInfo;
PROCESS_INFORMATION ProcessInformation;
int i = 1;

memset(&StartupInfo, 0, sizeof(STARTUPINFO));

/* the command line is made of the driver name followed by args */
snprintf(commandline, sizeof(commandline), "%s", ups->driver);
if (strstr(argv[0], ups->driver)) {
/* We already know whom to call (got a pointer to needle in the haystack) */
snprintf(commandline, sizeof(commandline), "%s", argv[0]);
} else {
/* Hope for the PATH based resolution to work, perhaps the
* driver program is located nearby (depends on configure
* options). Note that for builds tested in the workspace
* this may be misleading ("nearby" is under ".libs/" and
* fails to run directly without the tweaks of libtool
* wrapper provided in the directory just above).
*/
snprintf(commandline, sizeof(commandline), "%s%s", ups->driver, EXEEXT);
}

while (argv[i] != NULL) {
snprintfcat(commandline, sizeof(commandline), " %s", argv[i]);
i++;
}

upsdebugx(1, "%s[WIN32]: CreateProcess(argv0='%s' cmdline='%s')...",
__func__, argv[0], commandline);
ret = CreateProcess(
argv[0],
commandline,
argv[0], /* Application/Module name, often the program to run */
commandline, /* Full command line including the program to run and its args */
NULL,
NULL,
FALSE,
Expand Down Expand Up @@ -1237,7 +1252,10 @@ static void start_driver(const ups_t *ups)
#ifndef WIN32
snprintf(dfn, sizeof(dfn), "%s/%s", driverpath, ups->driver);
#else /* WIN32 */
snprintf(dfn, sizeof(dfn), "%s/%s.exe", driverpath, ups->driver);
if (driverpath && *driverpath == '/')
snprintf(dfn, sizeof(dfn), "%s/%s.exe", driverpath, ups->driver);
else /* Assume windows-style path with backslashes */
snprintf(dfn, sizeof(dfn), "%s\\%s.exe", driverpath, ups->driver);
#endif /* WIN32 */
ret = stat(dfn, &fs);

Expand Down
12 changes: 10 additions & 2 deletions tests/NIT/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,16 @@ EXTRA_DIST = nit.sh README.adoc

if WITH_CHECK_NIT
check: check-NIT
else
else !WITH_CHECK_NIT
check:
@echo "NO-OP: $@ in `pwd` is inactive by default. Run 'configure --enable-check-NIT' or 'make check-NIT' explicitly" >&2
endif
endif !WITH_CHECK_NIT

# Paths possibly different from what automake provides (POSIXish)
# when building on/for e.g. Windows. Matters where system() is used,
# such as NIT suite using/testing upsdrvctl:
ABS_TOP_SRCDIR = @ABS_TOP_SRCDIR@
ABS_TOP_BUILDDIR = @ABS_TOP_BUILDDIR@

# Run in builddir, use script from srcdir
# Avoid running "$<" - not all make implementations handle that
Expand All @@ -25,6 +31,7 @@ check-NIT: $(abs_srcdir)/nit.sh
BUILTIN_RUN_AS_USER='$(RUN_AS_USER)' BUILTIN_RUN_AS_GROUP='$(RUN_AS_GROUP)' \
abs_srcdir='$(abs_srcdir)' abs_builddir='$(abs_builddir)' \
abs_top_srcdir='$(abs_top_srcdir)' abs_top_builddir='$(abs_top_builddir)' \
ABS_TOP_SRCDIR='$(ABS_TOP_SRCDIR)' ABS_TOP_BUILDDIR='$(ABS_TOP_BUILDDIR)' \
EXEEXT='$(EXEEXT)' \
"$(abs_srcdir)/nit.sh"

Expand All @@ -48,6 +55,7 @@ check-NIT-sandbox: $(abs_srcdir)/nit.sh
BUILTIN_RUN_AS_USER='$(RUN_AS_USER)' BUILTIN_RUN_AS_GROUP='$(RUN_AS_GROUP)' \
abs_srcdir='$(abs_srcdir)' abs_builddir='$(abs_builddir)' \
abs_top_srcdir='$(abs_top_srcdir)' abs_top_builddir='$(abs_top_builddir)' \
ABS_TOP_SRCDIR='$(ABS_TOP_SRCDIR)' ABS_TOP_BUILDDIR='$(ABS_TOP_BUILDDIR)' \
EXEEXT='$(EXEEXT)' \
"$(abs_srcdir)/nit.sh"

Expand Down
28 changes: 22 additions & 6 deletions tests/NIT/nit.sh
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
# different value like "nobody" or "nogroup" would be defaulted for test.
#
# Copyright
# 2022-2025 Jim Klimov <jimklimov+nut@gmail.com>
# 2022-2026 Jim Klimov <jimklimov+nut@gmail.com>
#
# License: GPLv2+

Expand Down Expand Up @@ -427,7 +427,7 @@ else
fi

log_info "Locating NUT programs to test:"
for PROG in upsd upsc dummy-ups upsmon upslog upssched ; do
for PROG in upsd upsc dummy-ups upsdrvctl upsmon upslog upssched ; do
(command -v ${PROG}) || (command -v ${PROG}${EXEEXT-}) || die "Useless setup: ${PROG} not found in PATH: ${PATH}"
done

Expand Down Expand Up @@ -1000,9 +1000,24 @@ generatecfg_upsmon_secondary() {
generatecfg_ups_trivial() {
# Populate the configs for the run
( echo 'maxretry = 3' > "$NUT_CONFPATH/ups.conf" || exit
if [ x"${TOP_BUILDDIR}" != x ]; then
echo "driverpath = \"${TOP_BUILDDIR}/drivers\"" >> "$NUT_CONFPATH/ups.conf" || exit
if [ x"${ABS_TOP_BUILDDIR}" != x ]; then
# NOTE: Windows backslashes are pre-escaped in the configure-generated value
case "${ABS_TOP_BUILDDIR}" in
?":\\"*) PATHSEP='\\' ;;
*) PATHSEP="/" ;;
esac
echo "driverpath = \"${ABS_TOP_BUILDDIR}${PATHSEP}drivers\"" >> "$NUT_CONFPATH/ups.conf" || exit
else
# NOTE: Escaping presumed needed below, so for PATHSEP too
if [ x"${TOP_BUILDDIR}" != x ]; then
case "${TOP_BUILDDIR}" in
?":\\"*) PATHSEP='\' ;;
*) PATHSEP="/" ;;
esac
echo "driverpath = \"${TOP_BUILDDIR}${PATHSEP}drivers\"" | sed 's,\\,\\\\,g' >> "$NUT_CONFPATH/ups.conf" || exit
fi
fi
unset PATHSEP
if [ -n "${NUT_DEBUG_MIN-}" ] ; then
echo "debug_min = ${NUT_DEBUG_MIN}" >> "$NUT_CONFPATH/ups.conf" || exit
fi
Expand Down Expand Up @@ -1359,8 +1374,9 @@ sandbox_start_drivers() {
if [ -n "${NUT_DEBUG_LEVEL_DRIVERS-}" ]; then
NUT_DEBUG_LEVEL="${NUT_DEBUG_LEVEL_DRIVERS}"
fi
#execcmd upsdrvctl ${ARG_FG} ${ARG_USER} start dummy &
execcmd dummy-ups -a dummy ${ARG_USER} ${ARG_FG} &
# Run one driver instance indirectly, to test the upsdrvctl tool too:
execcmd upsdrvctl ${ARG_FG} ${ARG_USER} start dummy &
#execcmd dummy-ups -a dummy ${ARG_USER} ${ARG_FG} &
PID_DUMMYUPS="$!"
log_debug "Tried to start dummy-ups driver for 'dummy' as PID $PID_DUMMYUPS"

Expand Down
Loading