Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions NEWS.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@ https://github.com/networkupstools/nut/milestone/13
- `upsmon` client updates:
* Introduced support for `CERTFILE` option, so the client can identify
itself to the data server also in OpenSSL builds. [issue #3331]
* Failure of SSL connection setup (e.g. due to inability to load the
NSS library, a practical regression since NUT v2.8.4 release, now that
success of SSL initialization with both backends is more diligently
tracked) should now not cause exit of the client if secure connection
is not required by its configuration in the first place. [#3420]

- Introduced `ci_build.sh` settings and respective CI workflow settings
to optionally re-use a `config.cache` file from older runs, and similar
Expand Down
8 changes: 6 additions & 2 deletions clients/upsmon.c
Original file line number Diff line number Diff line change
Expand Up @@ -4188,8 +4188,12 @@ int main(int argc, char *argv[])
}

if (upscli_init2(certverify, certpath, certname, certpasswd, certfile) < 0) {
upsnotify(NOTIFY_STATE_STOPPING, "Failed upscli_init2()");
exit(EXIT_FAILURE);
if (certverify || certpath || certname || certpasswd || certfile) {
upslogx(LOG_WARNING, "Failed upscli_init2() while SSL was required");
upsnotify(NOTIFY_STATE_STOPPING, "Failed upscli_init2() while SSL was required");
exit(EXIT_FAILURE);
}
upslogx(LOG_WARNING, "Failed upscli_init2() but SSL ability was not required");
}

/* prep our signal handlers */
Expand Down
134 changes: 122 additions & 12 deletions scripts/Windows/dllldd.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,33 @@
# for Windows, bundled with open-source dependencies.
#
# Copyright (C)
# 2022-2025 Jim Klimov <jimklimov+nut@gmail.com>
# 2022-2026 Jim Klimov <jimklimov+nut@gmail.com>

# tools
[ -n "${GREP}" ] || { GREP="`command -v grep`" && [ x"${GREP}" != x ] || { echo "$0: FAILED to locate GREP tool" >&2 ; exit 1 ; } ; }
[ -n "${EGREP}" ] || { if ( [ x"`echo a | $GREP -E '(a|b)'`" = xa ] ) 2>/dev/null ; then EGREP="$GREP -E" ; else EGREP="`command -v egrep`" ; fi && [ x"${EGREP}" != x ] || { echo "$0: FAILED to locate EGREP tool" >&2 ; exit 1 ; } ; }

REGEX_WS="`printf '[\t ]'`"
REGEX_NOT_WS="`printf '[^\t ]'`"
dllldd() (

print_MSYS_DLL_PATH() {
echo "${PATH}:${LD_LIBRARY_PATH}" | tr ':' '\n' | \
while read D ; do
case "$D" in
""|/?/*|*/Windows*|*/System*|*/Progra*) continue ;;
"${MSYS_HOME}"/*|/mingw*/*|/usr/*|/clang*/*|/?bin/*|/ucrt*/*|/opt/*|/home/*|/var/*|/tmp/*)
[ -d "$D" ] && printf '%s:' "$D"
;;
esac
done | sed 's/:*$//'
}
SEARCH_DLL_PATH="`print_MSYS_DLL_PATH`"

filter_away_system_DLLs() {
${EGREP} -v -i '^(/.*/)?(msvcrt|userenv|bcrypt|rpcrt4|usp10|ntdll|api-ms-win-|(advapi|kernel|user|wsock|ws2_|gdi|ole|shell)(32|64))\.dll$'
}

dllldd_with_tools() (
# Traverse an EXE or DLL file for DLLs it needs directly,
# which are provided in the cross-build env (not system ones).
# Assume no whitespaces in paths and filenames of interest.
Expand All @@ -30,7 +48,7 @@ dllldd() (
for OD in objdump "$ARCH-objdump" ; do
(command -v "$OD" >/dev/null 2>/dev/null) || continue

ODOUT="`$OD -x \"$@\" 2>/dev/null | ${EGREP} -i \"DLL Name:\" | awk '{print $NF}' | sort | uniq | ${EGREP} -v -i '^(/.*/)?(msvcrt|userenv|bcrypt|rpcrt4|usp10|(advapi|kernel|user|wsock|ws2_|gdi|ole||shell)(32|64))\.dll$'`" \
ODOUT="`$OD -x \"$@\" 2>/dev/null | ${EGREP} -i \"DLL Name:\" | awk '{print $NF}' | sort | uniq | filter_away_system_DLLs`" \
&& [ -n "$ODOUT" ] || continue

for F in $ODOUT ; do
Expand Down Expand Up @@ -90,7 +108,7 @@ dllldd() (
done
fi

echo "WARNING: '$F' was not found in searched locations (system paths)!" >&2
echo "WARNING: '$F' was not found in searched locations (system paths) by tools matcher ($OD)!" >&2
done
done
if [ "$SEEN" != 0 ] ; then
Expand All @@ -105,17 +123,103 @@ dllldd() (
OUT="`ldd \"$@\" 2>/dev/null | ${EGREP} -i '\.dll' | ${EGREP} '/(bin|lib)/' | sed \"s,^${REGEX_WS}*\(${REGEX_NOT_WS}${REGEX_NOT_WS}*\)${REGEX_WS}${REGEX_WS}*=>${REGEX_WS}${REGEX_WS}*\(${REGEX_NOT_WS}${REGEX_NOT_WS}*\)${REGEX_WS}.*\$,\2,\" | sort | uniq | ${EGREP} -i '\.dll$'`" \
&& [ -n "$OUT" ] && { echo "$OUT" ; return 0 ; }

echo "WARNING: no suitable DLLs were found in $@ by tools matcher (ldd)!" >&2
return 1
)

dlllddrec() (
# Recurse to find the (mingw-provided) tree of dependencies
dllldd "$1" | while read D ; do
echo "$D"
dlllddrec "$D"
done | sort | uniq
dllldd_with_strings() (
strings "$@" | ${EGREP} -i '..*\.dll$' | sort | uniq | filter_away_system_DLLs | \
while read DLL ; do (
# Avoid looping on at least self-reference in a file
for S in "$@" ; do
# echo "=== Compare '$DLL' to '$S'" >&2
case "$DLL" in
"$S"|*/"$S") exit ;;
esac
case "$S" in
*/"$DLL") exit ;;
esac
done
# echo "=== '$DLL' not in '$@'" >&2
echo "$DLL"
) ; done
)

dllldd() (
# Did at least one method not-fail and return something?
RES=0
OUT_TOOLS="`dllldd_with_tools \"$@\"`" && [ -n "${OUT_TOOLS}" ] || RES=$?
OUT_STRINGS="`dllldd_with_strings \"$@\"`" && [ -n "${OUT_STRINGS}" ] && RES=0
( # Subshell to sort results in the end
if [ -n "${OUT_TOOLS}" ] ; then
echo "${OUT_TOOLS}"
fi
if [ -n "${OUT_STRINGS}" ] ; then
OUT_STRINGS_FULL="`echo \"${OUT_STRINGS}\" | ${EGREP} '[/\\]'`" || OUT_STRINGS_FULL=""
if [ -n "${OUT_STRINGS_FULL}" ] ; then
echo "${OUT_STRINGS_FULL}"
OUT_STRINGS="`echo \"${OUT_STRINGS}\" | ${EGREP} -v '[/\\]'`"
fi

for S in ${OUT_STRINGS} ; do
if (echo "${OUT_STRINGS_FULL}"; echo "${OUT_TOOLS}") | ${GREP} -i '[/\\]'"$S"'$' ; then
# Already a full path name (reported via grep to stdout above)
continue
fi

# Something new (e.g. something listed for dynamic loading)...

# Is it simply in PATH (and deemed executable)?
# WARNING: Can return things in system path
# command -v "$S" && continue

echo "${SEARCH_DLL_PATH}" | tr ':' '\n' | {
while read D ; do
if [ -s "$D/$S" ]; then
echo "$D/$S"
exit
fi
done

echo "WARNING: '$S' was not found in searched locations (system paths) by strings matcher!" >&2
}
done
fi
) | sort | uniq
return $RES
)

do_dlllddrec() (
# Skip out if we already reported this file
if [ -n "$TEMPFILE_REC" ] ; then
if ${EGREP} '^'"$1"'$' "$TEMPFILE_REC" >/dev/null 2>/dev/null ; then
exit
fi
fi

# Recurse to find the (mingw-provided) tree of dependencies - implem
echo "=== Recursing into '$1'..." >&2
dllldd "$1" | while read DLL_HIT ; do
[ -n "$DLL_HIT" ] || continue
echo "$DLL_HIT" >> "$TEMPFILE_REC"
echo "$DLL_HIT"
do_dlllddrec "$DLL_HIT"
done
)

dlllddrec() {
TEMPFILE_REC="`mktemp`" || TEMPFILE_REC=""
if [ -n "$TEMPFILE_REC" ] ; then
trap 'rm -f "$TEMPFILE_REC"' 0 1 2 3 15
fi

# Recurse to find the (mingw-provided) tree of dependencies for one file
do_dlllddrec "$1" | sort | uniq

rm -f "$TEMPFILE_REC"
trap - 0 1 2 3 15
}

# Alas, can't rely on having BASH, and dash fails to parse its syntax
# even if hidden by conditionals or separate method like this (might
# optionally source it from another file though?)
Expand Down Expand Up @@ -198,7 +302,13 @@ if [ x"${DLLLDD_SOURCED-}" != xtrue ] ; then
cat << EOF
Tool to find DLLs needed by an EXE or another DLL

Directly used libraries:
Directly used libraries, search with "proper tools":
$0 dllldd_with_tools ONEFILE.EXE

Directly used libraries, search with "strings" and "grep":
$0 dllldd_with_strings ONEFILE.EXE

Directly used libraries, combine the two methods above (default):
$0 dllldd ONEFILE.EXE

Recursively used libraries:
Expand All @@ -210,7 +320,7 @@ and list their set of required DLLs
$0 dllldddir_pedantic [DIRNAME...]
EOF
;;
dlllddrec|dllldd|dllldddir|dllldddir_pedantic) "$@" ;;
dlllddrec|dllldd|dllldd_with_tools|dllldd_with_strings|dllldddir|dllldddir_pedantic) "$@" ;;
*) dlllddrec "$1" ;;
esac

Expand Down
Loading