From c40e440b9a4a94332f92a2d422eba54e04163746 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 23 Jan 2026 09:58:52 +0100 Subject: [PATCH 001/198] docs/man/nut-ipmipsu.txt: add errata note about possible troubles when changing OS user accounts [#3193] Signed-off-by: Jim Klimov --- docs/man/nut-ipmipsu.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/man/nut-ipmipsu.txt b/docs/man/nut-ipmipsu.txt index e3ea950b97..9b94a10728 100644 --- a/docs/man/nut-ipmipsu.txt +++ b/docs/man/nut-ipmipsu.txt @@ -105,6 +105,16 @@ Here is an example output for a Dell r610 server: KNOWN ISSUES ------------ +According to the research in https://github.com/networkupstools/nut/issues/3193 +the driver (or technically the libfreeipmi used in it) may have troubles if it +changes the run-time user account, which NUT drivers usually do when started as +`root` by init scripts -- by default they drop privileges to the configured +user account such as `nut`, `ups` or `nobody`. If your driver fails to start, +possibly with a segmentation fault reported, try either changing the context +to the unprivileged user in init scripts (using `su` or `sudo`) or systemd unit +(using a drop-in file to set `User=...` in `[Service]` section) before starting +the actual driver program, or try setting `user=root` in its `ups.conf` section. + include::networked_hostnames.txt[] AUTHOR From 1fa967fe32a933c40d305a9678234d4c7ff3d46b Mon Sep 17 00:00:00 2001 From: Tim Niemueller Date: Fri, 23 Jan 2026 21:09:39 +0100 Subject: [PATCH 002/198] Add UPower driver Enables to read UPS data from UPower. This is useful if a UPS connected to a desktop system should be exposed over the network. It can also be used to expose laptop batteries. Signed-off-by: Tim Niemueller --- configure.ac | 42 ++++- docs/man/Makefile.am | 41 ++++- docs/man/upower_dbus.txt | 71 ++++++++ docs/nut.dict | 8 +- drivers/Makefile.am | 12 ++ drivers/upower_dbus.c | 355 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 523 insertions(+), 6 deletions(-) create mode 100644 docs/man/upower_dbus.txt create mode 100644 drivers/upower_dbus.c diff --git a/configure.ac b/configure.ac index cae2331c24..da830e1522 100644 --- a/configure.ac +++ b/configure.ac @@ -2316,6 +2316,7 @@ AC_ARG_WITH(drivers, if test -z "${with_powerman}"; then with_powerman="yes"; fi if test -z "${with_modbus}"; then with_modbus="yes"; fi if test -z "${with_ipmi}"; then with_ipmi="yes"; fi + if test -z "${with_upower}"; then with_upower="yes"; fi dnl Platform-dependent snowflakes that are required or auto: if test -z "${with_gpio}"; then @@ -2353,6 +2354,7 @@ AC_ARG_WITH(drivers, if test -z "${with_powerman}"; then with_powerman="${withval}"; fi if test -z "${with_modbus}"; then with_modbus="${withval}"; fi if test -z "${with_ipmi}"; then with_ipmi="${withval}"; fi + if test -z "${with_upower}"; then with_upower="${withval}"; fi if test -z "${with_gpio}"; then with_gpio="${withval}"; fi if test -z "${with_linux_i2c}"; then with_linux_i2c="${withval}"; fi if test -z "${with_macosx_ups}"; then with_macosx_ups="${withval}"; fi @@ -2369,7 +2371,8 @@ AC_ARG_WITH(drivers, SERIAL_DRIVERLIST USB_LIBUSB_DRIVERLIST SERIAL_USB_DRIVERLIST SNMP_DRIVERLIST NEONXML_DRIVERLIST MACOSX_DRIVERLIST MODBUS_DRIVERLIST LINUX_I2C_DRIVERLIST - POWERMAN_DRIVERLIST IPMI_DRIVERLIST GPIO_DRIVERLIST" + POWERMAN_DRIVERLIST IPMI_DRIVERLIST GPIO_DRIVERLIST + UPOWER_DRIVERLIST" dnl Gets ONE Makefile assignment value get_drivers_makefile_value() ( @@ -2520,6 +2523,11 @@ AC_ARG_WITH(drivers, [AC_MSG_NOTICE([Requiring --with-gpio=yes for driver "$DRV"]) with_gpio=yes] )], + [UPOWER_DRIVERLIST], [ + AS_IF([test -z "${with_upower}"], + [AC_MSG_NOTICE([Requiring --with-upower=yes for driver "$DRV"]) + with_upower=yes] + )], [AC_MSG_WARN([Unhandled DRVLIST_NAME=$DRVLIST_NAME])] ) @@ -2553,7 +2561,7 @@ dnl check for --with-all (or --without-all, or --with-all=auto) flag AC_MSG_CHECKING(for --with-all) AC_ARG_WITH(all, - AS_HELP_STRING([--with-all], [enable serial, usb, snmp, neon, ipmi, powerman, modbus, gpio (currently on Linux released after ~2018), linux_i2c (on Linux), macosx-ups (on MacOS), cgi, dev, avahi, nut-scanner, nutconf, dev-libnutconf, pynut]), + AS_HELP_STRING([--with-all], [enable serial, usb, snmp, neon, ipmi, powerman, modbus, gpio (currently on Linux released after ~2018), linux_i2c (on Linux), upower, macosx-ups (on MacOS), cgi, dev, avahi, nut-scanner, nutconf, dev-libnutconf, pynut]), [ if test -n "${withval}"; then dnl Note: we allow "no" as a positive value, because @@ -2567,6 +2575,7 @@ AC_ARG_WITH(all, if test -z "${with_powerman}"; then with_powerman="${withval}"; fi if test -z "${with_modbus}"; then with_modbus="${withval}"; fi if test -z "${with_ipmi}"; then with_ipmi="${withval}"; fi + if test -z "${with_upower}"; then with_upower="${withval}"; fi dnl Platform-dependent snowflakes that are required or auto: if test -z "${with_gpio}"; then @@ -2845,6 +2854,7 @@ dnl Platform-dependent drivers, currently their detection code is directly dnl spelled out in configure.ac NUT_ARG_WITH([macosx_ups], [build and install Mac OS X Power Sources meta-driver], [auto]) NUT_ARG_WITH([linux_i2c], [build and install i2c drivers], [auto]) +NUT_ARG_WITH([upower], [build and install UPower driver (requires GLib/GIO)], [auto]) dnl A Python GUI client application for the sysadmin desktop dnl (not necessarily on the NUT server itself): @@ -5432,6 +5442,34 @@ AS_IF([test x"$have_PKG_CONFIG" = xyes], ) AC_MSG_RESULT(${have_cppunit}) +dnl ---------------------------------------------------------------------- +dnl Check for GLib / GIO (Required for UPower driver) +dnl ---------------------------------------------------------------------- + +have_glib=no + +if test "${with_upower}" != "no"; then +AS_IF([test x"$have_PKG_CONFIG" = xyes], + [ifdef([PKG_CHECK_MODULES], + [PKG_CHECK_MODULES(GLIB, [glib-2.0 gio-2.0], [have_glib=yes], [have_glib=no])], + [have_glib=no]) + ], + [AC_MSG_WARN([pkg-config not found, cannot look properly for glib-2.0/gio-2.0])] +) +fi + +if test "${have_glib}" = "yes"; then + AC_DEFINE(HAVE_GLIB, 1, [Define to 1 if GLib and GIO are available]) +else + if test "${with_upower}" = "yes"; then + AC_MSG_ERROR([GLib/GIO not found but requested via --with-upower]) + fi + AC_MSG_WARN([GLib/GIO not found. The 'upower' driver will not be built.]) +fi + +AM_CONDITIONAL(HAVE_GLIB, test "${have_glib}" = "yes") +AC_MSG_RESULT(${have_glib}) + dnl On some systems, CppUnit inexplicably fails with trivial assertions dnl so it should not be enabled with those environments, corrupting the dnl test results with misleading errors. diff --git a/docs/man/Makefile.am b/docs/man/Makefile.am index 7724634bc3..c16949759d 100644 --- a/docs/man/Makefile.am +++ b/docs/man/Makefile.am @@ -1463,6 +1463,38 @@ else !DOC_INSTALL_SELECTED_MANS_PROGS_BUILT LINKMAN_PAGES_DRIVERS += $(SRC_GPIO_PAGES) endif !DOC_INSTALL_SELECTED_MANS_PROGS_BUILT +# (--with-upower) +SRC_UPOWER_PAGES = upower_dbus.txt +INST_MAN_UPOWER_PAGES = upower_dbus.$(MAN_SECTION_CMD_SYS) +DIST_ALL_MAN_PAGES += $(INST_MAN_UPOWER_PAGES) + +if ! SOME_DRIVERS +if WITH_MANS +MAN_UPOWER_PAGES = $(INST_MAN_UPOWER_PAGES) +endif WITH_MANS + +if HAVE_GLIB +mansys_DATA += $(MAN_UPOWER_PAGES) +endif HAVE_GLIB +endif ! SOME_DRIVERS + +INST_HTML_UPOWER_MANS = \ + upower_dbus.html +DIST_ALL_HTML_PAGES += $(INST_HTML_UPOWER_MANS) + +if ! SOME_DRIVERS +HTML_UPOWER_MANS = $(INST_HTML_UPOWER_MANS) +endif ! SOME_DRIVERS + +# FIXME? Refine for HTML etc.? +if DOC_INSTALL_SELECTED_MANS_PROGS_BUILT +if HAVE_GLIB +LINKMAN_PAGES_DRIVERS += $(SRC_UPOWER_PAGES) +endif HAVE_GLIB +else !DOC_INSTALL_SELECTED_MANS_PROGS_BUILT +LINKMAN_PAGES_DRIVERS += $(SRC_UPOWER_PAGES) +endif !DOC_INSTALL_SELECTED_MANS_PROGS_BUILT + # Summarize which pages we ultimately install: MAN_MANS = if WITH_MANS @@ -1486,7 +1518,8 @@ MAN_MANS += \ $(MAN_MACOSX_PAGES) \ $(MAN_MODBUS_PAGES) \ $(MAN_LINUX_I2C_PAGES) \ - $(MAN_GPIO_PAGES) + $(MAN_GPIO_PAGES) \ + $(MAN_UPOWER_PAGES) endif WITH_MANS SRC_DRIVERS_PAGES = \ @@ -1500,7 +1533,8 @@ SRC_DRIVERS_PAGES = \ $(SRC_MACOSX_PAGES) \ $(SRC_MODBUS_PAGES) \ $(SRC_LINUX_I2C_PAGES) \ - $(SRC_GPIO_PAGES) + $(SRC_GPIO_PAGES) \ + $(SRC_UPOWER_PAGES) if SOME_DRIVERS # (Legacy note) The list above probably came up empty in this case, so make sure @@ -1576,7 +1610,8 @@ HTML_MANS = \ $(HTML_MACOSX_MANS) \ $(HTML_MODBUS_MANS) \ $(HTML_LINUX_I2C_MANS) \ - $(HTML_GPIO_MANS) + $(HTML_GPIO_MANS) \ + $(HTML_UPOWER_MANS) # htmlmandir is set by autoconf/automake htmlman_DATA = diff --git a/docs/man/upower_dbus.txt b/docs/man/upower_dbus.txt new file mode 100644 index 0000000000..80833d8a82 --- /dev/null +++ b/docs/man/upower_dbus.txt @@ -0,0 +1,71 @@ +UPOWER_DBUS(8) +============== + +NAME +---- +upower_dbus - Driver for UPower devices via D-Bus + +SYNOPSIS +-------- +*upower_dbus* -h + +*upower_dbus* -a 'UPS_NAME' ['OPTIONS'] + +NOTE: This man page only documents the specific features of the +*upower_dbus* driver. For information about the core driver, see +linkman:nutupsdrv[8]. + +DESCRIPTION +----------- +This driver allows the monitoring of power devices (UPS, batteries) that are +managed by the UPower daemon via the D-Bus system bus. + +It maps UPower properties (state, percentage, voltage, etc.) to standard NUT +variables, allowing NUT clients to monitor devices that are natively supported +by the OS desktop environment but not directly by other NUT drivers. + +EXTRA ARGUMENTS +--------------- +This driver supports the following optional settings in linkman:ups.conf[5]: + +*port*:: +The UPower Object Path of the device to monitor. + +If set to `auto` (the default), the driver will scan for the first UPower device +whose object path contains the string "ups_". + +If set to a specific path (e.g., `/org/freedesktop/UPower/devices/ups_hiddev0`), +the driver will attempt to monitor that specific device. + +*lowbatt*:: +The battery percentage threshold below which the `LB` (Low Battery) status +flag is set. The default value is 20.0. + +INSTALLATION +------------ +To use this driver, add a section to your *ups.conf*: + +---- +[myups] + driver = upower_dbus + port = auto + lowbatt = 20 + desc = "Laptop Battery or generic UPS via UPower" +---- + +REQUIREMENTS +------------ +This driver requires the `upower` daemon to be running and accessible via the +D-Bus system bus. It also requires GLib 2.0 and GIO libraries. + +AUTHOR +------ +Tim Niemueller + +SEE ALSO +-------- +linkman:ups.conf[5], linkman:nutupsdrv[8], linkman:upsc[8] + +Internet Resources: +~~~~~~~~~~~~~~~~~~~ +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/nut.dict b/docs/nut.dict index 1733c0a17f..3343fd1e38 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3632 utf-8 +personal_ws-1.1 en 3638 utf-8 AAC AAS ABI @@ -241,6 +241,7 @@ Cygwin DATACABLE DATAPATH DBCF +DBUS DCE DCF DCO @@ -434,7 +435,9 @@ GES GETADDRINFO GETPID GID +GIO GITREV +GLib GND GNUmakefile GObject @@ -850,6 +853,7 @@ Netman NetworkUPSTools Neus Niels +Niemueller Niklas Niro NixOS @@ -1925,6 +1929,7 @@ datasheet datasize datastale dblatex +dbus dcd dcn ddk @@ -2133,6 +2138,7 @@ formatstring fosshost fp freebsd +freedesktop freeipmi freetype frob diff --git a/drivers/Makefile.am b/drivers/Makefile.am index b9658bb51a..ebad5fb9ea 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -167,6 +167,7 @@ LINUX_I2C_DRIVERLIST = asem pijuice hwmon_ina219 POWERMAN_DRIVERLIST = powerman-pdu IPMI_DRIVERLIST = nut-ipmipsu GPIO_DRIVERLIST = generic_gpio_libgpiod +UPOWER_DRIVERLIST = upower_dbus # distribute all drivers, even ones that are not built by default EXTRA_PROGRAMS = $(SERIAL_DRIVERLIST) $(USB_DRIVERLIST) $(SERIAL_USB_DRIVERLIST) @@ -174,6 +175,7 @@ EXTRA_PROGRAMS += $(SNMP_DRIVERLIST) $(NEONXML_DRIVERLIST) $(MACOSX_DRIVERLIST) EXTRA_PROGRAMS += $(LINUX_I2C_DRIVERLIST) EXTRA_PROGRAMS += $(NUTSW_DRIVERLIST) EXTRA_PROGRAMS += $(GPIO_DRIVERLIST) +EXTRA_PROGRAMS += $(UPOWER_DRIVERLIST) # construct the list of drivers to build if SOME_DRIVERS @@ -364,6 +366,16 @@ mge_shut_SOURCES = usbhid-ups.c libshut.c libhid.c hidparser.c mge-hid.c mge_shut_CFLAGS = $(AM_CFLAGS) -DSHUT_MODE=1 mge_shut_LDADD = $(LDADD_DRIVERS_SERIAL) -lm +# UPower +if HAVE_GLIB + # Only build upower if GLib was found + driverexec_PROGRAMS += $(UPOWER_DRIVERLIST) + + upower_dbus_SOURCES = upower_dbus.c + upower_dbus_LDADD = $(LDADD_DRIVERS) $(GLIB_LIBS) + upower_dbus_CFLAGS = $(AM_CFLAGS) $(GLIB_CFLAGS) +endif + # SNMP # Please keep the MIB table below sorted roughly alphabetically (incidentally # by vendor too) to ease maintenance and codebase fork resynchronisations diff --git a/drivers/upower_dbus.c b/drivers/upower_dbus.c new file mode 100644 index 0000000000..3bdea42bd8 --- /dev/null +++ b/drivers/upower_dbus.c @@ -0,0 +1,355 @@ +/* drivers/upower_dbus.c - Driver for UPower via D-Bus + * + * Copyright (C) 2026 Tim Niemueller + * + * Links against standard NUT driver core. + * Requires: glib-2.0, gio-2.0 + */ + +#include "main.h" +#include "dstate.h" + +#include +#include +#include +#include + +#define DRIVER_NAME "UPower D-Bus Driver" +#define DRIVER_VERSION "0.1" + +/* UPower Constants */ +#define UPOWER_BUS "org.freedesktop.UPower" +#define UPOWER_PATH "/org/freedesktop/UPower" +#define UPOWER_IFACE "org.freedesktop.UPower" +#define DEVICE_IFACE "org.freedesktop.UPower.Device" +#define PROPS_IFACE "org.freedesktop.DBus.Properties" + +/* Global DBus Connection Objects */ +static GDBusConnection *connection = NULL; +static char *ups_object_path = NULL; +static double lowbatt_pct = 20.0; + +/* NUT Driver Info Structure */ +upsdrv_info_t upsdrv_info = { + DRIVER_NAME, + DRIVER_VERSION, + "Tim Niemueller ", + DRV_EXPERIMENTAL, + { NULL } +}; + +/* -------------------------------------------------------------------------- */ +/* Map UPower State to NUT Status */ +/* -------------------------------------------------------------------------- */ +static void set_nut_status(guint state, gdouble percentage) +{ + /* Clear previous status */ + status_init(); + + /* UPower States: + * 1: Charging + * 2: Discharging + * 3: Empty + * 4: Fully Charged + * 5: Pending Charge + * 6: Pending Discharge + */ + + switch (state) { + case 1: /* Charging */ + status_set("OL CHRG"); + break; + case 2: /* Discharging */ + status_set("OB DISCHRG"); + break; + case 4: /* Full */ + status_set("OL"); + break; + case 3: /* Empty */ + status_set("OB LB"); + break; + default: /* Unknown / Pending */ + status_set("OL"); /* Default to Online to prevent shutdowns */ + break; + } + + /* Override for Low Battery based on percentage */ + if (percentage < lowbatt_pct) { + status_set("LB"); + } + + status_commit(); +} + +/* -------------------------------------------------------------------------- */ +/* Find the First UPS Device (auto) or a specific one (device_path not auto) */ +/* -------------------------------------------------------------------------- */ +static int find_ups_device(void) +{ + GError *error = NULL; + GVariant *result; + GVariantIter iter; + gchar *obj_path; + int found = 0; + + /* Call EnumerateDevices on the main UPower object */ + result = g_dbus_connection_call_sync( + connection, + UPOWER_BUS, UPOWER_PATH, UPOWER_IFACE, + "EnumerateDevices", + NULL, /* No params */ + G_VARIANT_TYPE("(ao)"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error + ); + + if (error) { + fatalx(EXIT_FAILURE, "DBus Error enumerating devices: %s", error->message); + } + + /* Iterate the result array of object paths */ + g_variant_iter_init(&iter, g_variant_get_child_value(result, 0)); + + while (g_variant_iter_loop(&iter, "o", &obj_path)) { + upsdebugx(2, "Enumerated UPower device: %s", obj_path); + + /* Check if we are looking for a specific path */ + if (device_path && strcmp(device_path, "auto") != 0 && *device_path != '\0') { + if (strstr(obj_path, device_path)) { + upsdebugx(1, "Match found for specific path '%s': %s", device_path, obj_path); + ups_object_path = strdup(obj_path); + found = 1; + break; + } + } else { + /* Auto-detection: Check for substring "ups_" */ + if (strstr(obj_path, "ups_")) { + upsdebugx(1, "Auto-detected UPS device: %s", obj_path); + ups_object_path = strdup(obj_path); + found = 1; + break; + } + } + } + + g_variant_unref(result); + return found; +} + +/* -------------------------------------------------------------------------- */ +/* List Available UPower Devices */ +/* -------------------------------------------------------------------------- */ +static void list_upower_devices(void) +{ + GError *error = NULL; + GDBusConnection *conn; + GVariant *result; + GVariantIter iter; + gchar *obj_path; + + /* Initialize GLib type system */ + #if !GLIB_CHECK_VERSION(2, 36, 0) + g_type_init(); + #endif + + conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (!conn) { + printf("Error: Failed to connect to System Bus: %s\n", error->message); + g_error_free(error); + return; + } + + result = g_dbus_connection_call_sync( + conn, + UPOWER_BUS, UPOWER_PATH, UPOWER_IFACE, + "EnumerateDevices", + NULL, + G_VARIANT_TYPE("(ao)"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error + ); + + if (error) { + printf("Error enumerating devices: %s\n", error->message); + g_error_free(error); + g_object_unref(conn); + return; + } + + printf("\nAvailable UPower devices:\n"); + g_variant_iter_init(&iter, g_variant_get_child_value(result, 0)); + + while (g_variant_iter_loop(&iter, "o", &obj_path)) { + printf(" %s\n", obj_path); + } + + g_variant_unref(result); + g_object_unref(conn); +} + +/* -------------------------------------------------------------------------- */ +/* NUT Hook: Help / Usage */ +/* -------------------------------------------------------------------------- */ +void upsdrv_help(void) +{ + list_upower_devices(); +} +/* -------------------------------------------------------------------------- */ +/* NUT Hook: Initialize Command Line Args */ +/* -------------------------------------------------------------------------- */ +void upsdrv_makevartable(void) +{ + addvar(VAR_VALUE, "lowbatt", "Low battery threshold (default: 20%)"); +} + +/* -------------------------------------------------------------------------- */ +/* NUT Hook: Initialize UPS Connection */ +/* -------------------------------------------------------------------------- */ +void upsdrv_initups(void) +{ + GError *error = NULL; + const char *val; + + /* Initialize GLib type system */ + #if !GLIB_CHECK_VERSION(2, 36, 0) + g_type_init(); + #endif + + /* Connect to System Bus */ + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (!connection) { + fatalx(EXIT_FAILURE, "Failed to connect to System Bus: %s", error->message); + } + + /* Find the UPS */ + if (!find_ups_device()) { + fatalx(EXIT_FAILURE, "No UPower device found containing 'ups_' in path."); + } + + upslogx(LOG_INFO, "Connected to UPower Device: %s", ups_object_path); + dstate_setinfo("driver.parameter.port", "%s", ups_object_path); + + /* Handle low battery threshold */ + if ((val = getval("lowbatt"))) { + lowbatt_pct = atof(val); + upsdebugx(1, "Low battery threshold set to: %.1f%%", lowbatt_pct); + } +} + +/* -------------------------------------------------------------------------- */ +/* NUT Hook: Update Info (The Main Loop) */ +/* -------------------------------------------------------------------------- */ +void upsdrv_updateinfo(void) +{ + GError *error = NULL; + GVariant *result, *props; + GVariantIter iter; + gchar *key; + GVariant *value; + + /* Fetch All Properties */ + result = g_dbus_connection_call_sync( + connection, + UPOWER_BUS, ups_object_path, PROPS_IFACE, + "GetAll", + g_variant_new("(s)", DEVICE_IFACE), + G_VARIANT_TYPE("(a{sv})"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error + ); + + if (error) { + dstate_datastale(); + upslogx(LOG_WARNING, "Failed to get properties: %s", error->message); + g_error_free(error); + return; + } + + /* Parse Dictionary */ + props = g_variant_get_child_value(result, 0); + g_variant_iter_init(&iter, props); + + gdouble voltage = 0.0, percentage = 0.0; + gint64 time_empty = 0; + guint state = 0; + const gchar *model = "Unknown"; + const gchar *vendor = "Unknown"; + const gchar *serial = "Unknown"; + + while (g_variant_iter_loop(&iter, "{sv}", &key, &value)) { + if (g_strcmp0(key, "Voltage") == 0) { + voltage = g_variant_get_double(value); + } else if (g_strcmp0(key, "Percentage") == 0) { + percentage = g_variant_get_double(value); + } else if (g_strcmp0(key, "State") == 0) { + state = g_variant_get_uint32(value); + } else if (g_strcmp0(key, "TimeToEmpty") == 0) { + time_empty = g_variant_get_int64(value); + } else if (g_strcmp0(key, "Model") == 0) { + model = g_variant_get_string(value, NULL); + } else if (g_strcmp0(key, "Vendor") == 0) { + vendor = g_variant_get_string(value, NULL); + } else if (g_strcmp0(key, "Serial") == 0) { + serial = g_variant_get_string(value, NULL); + } + } + + /* Update NUT Data Store (dstate) */ + dstate_setinfo("battery.charge", "%.1f", percentage); + dstate_setinfo("battery.voltage", "%.1f", voltage); + + if (time_empty > 0) { + dstate_setinfo("battery.runtime", "%lld", (long long)time_empty); + } + + dstate_setinfo("device.mfr", "%s", vendor); + dstate_setinfo("device.model", "%s", model); + dstate_setinfo("device.serial", "%s", serial); + + /* Update Status Flags */ + set_nut_status(state, percentage); + + /* Commit data */ + dstate_dataok(); + + g_variant_unref(props); + g_variant_unref(result); +} + +/* -------------------------------------------------------------------------- */ +/* NUT Hook: Tweak Program Names */ +/* -------------------------------------------------------------------------- */ +void upsdrv_tweak_prognames(void) +{ +} + +/* -------------------------------------------------------------------------- */ +/* NUT Hook: Initialize Info */ +/* -------------------------------------------------------------------------- */ +void upsdrv_initinfo(void) +{ + upsdrv_updateinfo(); +} + +/* -------------------------------------------------------------------------- */ +/* NUT Hook: Shutdown */ +/* -------------------------------------------------------------------------- */ +void upsdrv_shutdown(void) +{ + upslogx(LOG_ERR, "shutdown not supported"); +} + +/* -------------------------------------------------------------------------- */ +/* NUT Hook: Cleanup */ +/* -------------------------------------------------------------------------- */ +void upsdrv_cleanup(void) +{ + if (ups_object_path) free(ups_object_path); + if (connection) g_object_unref(connection); +} From f0b2e3e7e225f5a948fff55be91ef4622149d897 Mon Sep 17 00:00:00 2001 From: Tim Niemueller Date: Sat, 24 Jan 2026 00:25:26 +0100 Subject: [PATCH 003/198] Add libglib2.0-dev to github action builder Required to also test upower_dbus driver. Signed-off-by: Tim Niemueller --- .github/workflows/01-make-dist.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/01-make-dist.yml b/.github/workflows/01-make-dist.yml index 5dad7a7122..863420c565 100644 --- a/.github/workflows/01-make-dist.yml +++ b/.github/workflows/01-make-dist.yml @@ -141,6 +141,7 @@ jobs: libfreeipmi-dev libipmimonitoring-dev \ libavahi-common-dev libavahi-core-dev libavahi-client-dev \ libgpiod-dev \ + libglib2.0-dev \ bash dash ksh busybox \ libneon27-gnutls-dev \ build-essential git-core libi2c-dev i2c-tools lm-sensors \ From 83b04d164b7e57a4799ae8b5b0928f2f110b1e0c Mon Sep 17 00:00:00 2001 From: Tim Niemueller Date: Sat, 24 Jan 2026 13:18:55 +0100 Subject: [PATCH 004/198] Address upower driver immediate review comments Signed-off-by: Tim Niemueller --- NEWS.adoc | 5 +++++ UPGRADING.adoc | 5 +++++ docs/config-prereqs.txt | 15 +++++++++++++-- docs/configure.txt | 14 ++++++++++++++ drivers/upower_dbus.c | 17 ++++++++--------- 5 files changed, 45 insertions(+), 11 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index c30766204a..62ebe8d5ff 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -189,6 +189,11 @@ https://github.com/networkupstools/nut/milestone/12 * Fixed default `unit_id`, apparently broken by changes in NUT v2.8.1. [issue #3191, PR #3192] + - Introduced a new NUT driver named `upower_dbus` which provides support + for monitoring UPS and battery devices managed by the UPower daemon + via D-Bus. This also introduces a new category of drivers that talk to + operating system services to obtain power state information. + - `usbhid-ups` driver updates: * Declared support for APC with USB ID `051d:0005` (details may evolve as the devices become better known). [issue #3047, PR #3081] diff --git a/UPGRADING.adoc b/UPGRADING.adoc index fdfcdabd60..da2b375d5b 100644 --- a/UPGRADING.adoc +++ b/UPGRADING.adoc @@ -119,6 +119,11 @@ Changes from 2.8.4 to 2.8.5 updated, either to explicitly package the binding for several versions, or to not-deliver files no longer installed into the prototype area. [#1792] +- Introduced a new driver category for interaction with OS-reported UPS + devices via D-Bus, with the `upower_dbus` driver as the first implementation. + This driver requires `glib-2.0` and `gio-2.0` development libraries to be + available at build time. For packagers, this adds new dependencies if the + build should include this driver. Changes from 2.8.3 to 2.8.4 --------------------------- diff --git a/docs/config-prereqs.txt b/docs/config-prereqs.txt index b2b63991a1..59d8b4eae7 100644 --- a/docs/config-prereqs.txt +++ b/docs/config-prereqs.txt @@ -259,6 +259,7 @@ metadata about recently published package revisions: libssl-dev libnss3-dev \ augeas-tools libaugeas-dev augeas-lenses \ libusb-dev libusb-1.0-0-dev \ + libglib2.0-dev \ libi2c-dev \ libmodbus-dev \ libsnmp-dev \ @@ -459,6 +460,7 @@ drivers in distro packaging of NUT. Resolution and doc PRs are welcome. openssl-devel nss-devel \ augeas augeas-devel \ libusb-devel libusbx-devel \ + glib2-devel \ i2c-tools \ libmodbus-devel \ net-snmp-devel \ @@ -561,6 +563,7 @@ Install tools and prerequisites for NUT: openssl nss \ augeas \ libusb \ + glib2 \ neon \ net-snmp \ freeipmi \ @@ -732,6 +735,7 @@ For NUT dependencies and build tools: :; slackpkg-install \ openssl openssl-solibs mozilla-nss \ libusb \ + glib2 \ net-snmp \ neon @@ -870,6 +874,8 @@ below. cppunit \ nss \ augeas \ + libusb \ + glib \ libmodbus \ neon \ net-snmp \ @@ -1041,6 +1047,7 @@ Finally, as `root` add the packages: openssl nss \ augeas \ libusb1 \ + glib2 \ net-snmp \ avahi @@ -1232,6 +1239,7 @@ but can be created in `/etc/` and is honoured by `pkgin`: openssl nss \ augeas \ libusb libusb1 \ + glib2 \ neon \ net-snmp \ avahi @@ -1366,6 +1374,7 @@ Typical tooling would include: library/augeas python/augeas \ libusb-1 libusbugen system/library/usb/libusb \ system/header/header-usb driver/usb/ugen \ + glib2 \ libmodbus \ library/neon \ system/management/snmp/net-snmp \ @@ -1508,6 +1517,7 @@ site for setup details. developer/build/libtool library/libtool/libltdl \ build-essential ccache git developer/pkg-config \ runtime/perl \ + glib \ asciidoc \ libgd @@ -1725,7 +1735,7 @@ Currently known dependencies for basic build include: # Required: :; brew install ccache bash libtool binutils autoconf automake git m4 \ pkg-config aspell asciidoc docbook-xsl cppunit gd \ - libusb neon net-snmp \ + libusb glib neon net-snmp \ nss openssl \ libmodbus freeipmi powerman @@ -1935,7 +1945,8 @@ export PATH # This also pulls *-devel of several other projects: :; pacman -S --needed \ - mingw-w64-x86_64-neon libneon-devel + mingw-w64-x86_64-neon libneon-devel \ + mingw-w64-x86_64-glib2 # Other dependencies: :; pacman -S --needed \ diff --git a/docs/configure.txt b/docs/configure.txt index 58529295cf..f5d4cfd832 100644 --- a/docs/configure.txt +++ b/docs/configure.txt @@ -209,6 +209,20 @@ This allows to monitor numerous Power Supply Units (PSU) found on servers. Note that you need to install freeipmi (0.8.5 or higher, for nut-scanner; and 1.0.1 or higher, for nut-ipmipsu) development package or files. +UPower/D-Bus drivers +~~~~~~~~~~~~~~~~~~~~ + + --with-upower (default: auto-detect) + +Build and install the `upower_dbus` driver. + +This allows to monitor UPS and battery devices managed by the UPower daemon +via D-Bus. This introduces a new category of drivers that talk to operating +system services to obtain power state information. + +Note that you need to install `glib-2.0` and `gio-2.0` development packages +or files. + I2C bus drivers ~~~~~~~~~~~~~~~ diff --git a/drivers/upower_dbus.c b/drivers/upower_dbus.c index 3bdea42bd8..c8b120da67 100644 --- a/drivers/upower_dbus.c +++ b/drivers/upower_dbus.c @@ -15,7 +15,7 @@ #include #define DRIVER_NAME "UPower D-Bus Driver" -#define DRIVER_VERSION "0.1" +#define DRIVER_VERSION "0.01" /* UPower Constants */ #define UPOWER_BUS "org.freedesktop.UPower" @@ -203,7 +203,7 @@ void upsdrv_help(void) /* -------------------------------------------------------------------------- */ void upsdrv_makevartable(void) { - addvar(VAR_VALUE, "lowbatt", "Low battery threshold (default: 20%)"); + addvar(VAR_VALUE, "lowbatt", "Low battery threshold, in percent (default: 20)"); } /* -------------------------------------------------------------------------- */ @@ -250,6 +250,12 @@ void upsdrv_updateinfo(void) GVariantIter iter; gchar *key; GVariant *value; + gdouble voltage = 0.0, percentage = 0.0; + gint64 time_empty = 0; + guint state = 0; + const gchar *model = "Unknown"; + const gchar *vendor = "Unknown"; + const gchar *serial = "Unknown"; /* Fetch All Properties */ result = g_dbus_connection_call_sync( @@ -275,13 +281,6 @@ void upsdrv_updateinfo(void) props = g_variant_get_child_value(result, 0); g_variant_iter_init(&iter, props); - gdouble voltage = 0.0, percentage = 0.0; - gint64 time_empty = 0; - guint state = 0; - const gchar *model = "Unknown"; - const gchar *vendor = "Unknown"; - const gchar *serial = "Unknown"; - while (g_variant_iter_loop(&iter, "{sv}", &key, &value)) { if (g_strcmp0(key, "Voltage") == 0) { voltage = g_variant_get_double(value); From a2699f2d0c8bb9b87dda1664880a23cfc5135d38 Mon Sep 17 00:00:00 2001 From: Tim Niemueller Date: Sat, 24 Jan 2026 13:53:50 +0100 Subject: [PATCH 005/198] Rename upower_dbus driver to nut-upower Signed-off-by: Tim Niemueller --- NEWS.adoc | 2 +- UPGRADING.adoc | 2 +- docs/configure.txt | 2 +- docs/man/Makefile.am | 6 +++--- docs/man/{upower_dbus.txt => nut-upower.txt} | 14 +++++++------- drivers/Makefile.am | 8 ++++---- drivers/{upower_dbus.c => nut-upower.c} | 2 +- 7 files changed, 18 insertions(+), 18 deletions(-) rename docs/man/{upower_dbus.txt => nut-upower.txt} (87%) rename drivers/{upower_dbus.c => nut-upower.c} (99%) diff --git a/NEWS.adoc b/NEWS.adoc index 62ebe8d5ff..cd25672bf9 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -189,7 +189,7 @@ https://github.com/networkupstools/nut/milestone/12 * Fixed default `unit_id`, apparently broken by changes in NUT v2.8.1. [issue #3191, PR #3192] - - Introduced a new NUT driver named `upower_dbus` which provides support + - Introduced a new NUT driver named `nut-upower` which provides support for monitoring UPS and battery devices managed by the UPower daemon via D-Bus. This also introduces a new category of drivers that talk to operating system services to obtain power state information. diff --git a/UPGRADING.adoc b/UPGRADING.adoc index da2b375d5b..41a301cc63 100644 --- a/UPGRADING.adoc +++ b/UPGRADING.adoc @@ -120,7 +120,7 @@ Changes from 2.8.4 to 2.8.5 or to not-deliver files no longer installed into the prototype area. [#1792] - Introduced a new driver category for interaction with OS-reported UPS - devices via D-Bus, with the `upower_dbus` driver as the first implementation. + devices via D-Bus, with the `nut-upower` driver as the first implementation. This driver requires `glib-2.0` and `gio-2.0` development libraries to be available at build time. For packagers, this adds new dependencies if the build should include this driver. diff --git a/docs/configure.txt b/docs/configure.txt index f5d4cfd832..595763fb5c 100644 --- a/docs/configure.txt +++ b/docs/configure.txt @@ -214,7 +214,7 @@ UPower/D-Bus drivers --with-upower (default: auto-detect) -Build and install the `upower_dbus` driver. +Build and install the `nut-upower` driver. This allows to monitor UPS and battery devices managed by the UPower daemon via D-Bus. This introduces a new category of drivers that talk to operating diff --git a/docs/man/Makefile.am b/docs/man/Makefile.am index c16949759d..98d87c4adc 100644 --- a/docs/man/Makefile.am +++ b/docs/man/Makefile.am @@ -1464,8 +1464,8 @@ LINKMAN_PAGES_DRIVERS += $(SRC_GPIO_PAGES) endif !DOC_INSTALL_SELECTED_MANS_PROGS_BUILT # (--with-upower) -SRC_UPOWER_PAGES = upower_dbus.txt -INST_MAN_UPOWER_PAGES = upower_dbus.$(MAN_SECTION_CMD_SYS) +SRC_UPOWER_PAGES = nut-upower.txt +INST_MAN_UPOWER_PAGES = nut-upower.$(MAN_SECTION_CMD_SYS) DIST_ALL_MAN_PAGES += $(INST_MAN_UPOWER_PAGES) if ! SOME_DRIVERS @@ -1479,7 +1479,7 @@ endif HAVE_GLIB endif ! SOME_DRIVERS INST_HTML_UPOWER_MANS = \ - upower_dbus.html + nut-upower.html DIST_ALL_HTML_PAGES += $(INST_HTML_UPOWER_MANS) if ! SOME_DRIVERS diff --git a/docs/man/upower_dbus.txt b/docs/man/nut-upower.txt similarity index 87% rename from docs/man/upower_dbus.txt rename to docs/man/nut-upower.txt index 80833d8a82..172a6fdfeb 100644 --- a/docs/man/upower_dbus.txt +++ b/docs/man/nut-upower.txt @@ -1,18 +1,18 @@ -UPOWER_DBUS(8) -============== +NUT-UPOWER(8) +============= NAME ---- -upower_dbus - Driver for UPower devices via D-Bus +nut-upower - Driver for UPower devices via D-Bus SYNOPSIS -------- -*upower_dbus* -h +*nut-upower* -h -*upower_dbus* -a 'UPS_NAME' ['OPTIONS'] +*nut-upower* -a 'UPS_NAME' ['OPTIONS'] NOTE: This man page only documents the specific features of the -*upower_dbus* driver. For information about the core driver, see +*nut-upower* driver. For information about the core driver, see linkman:nutupsdrv[8]. DESCRIPTION @@ -47,7 +47,7 @@ To use this driver, add a section to your *ups.conf*: ---- [myups] - driver = upower_dbus + driver = nut-upower port = auto lowbatt = 20 desc = "Laptop Battery or generic UPS via UPower" diff --git a/drivers/Makefile.am b/drivers/Makefile.am index ebad5fb9ea..babcc9f1a9 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -167,7 +167,7 @@ LINUX_I2C_DRIVERLIST = asem pijuice hwmon_ina219 POWERMAN_DRIVERLIST = powerman-pdu IPMI_DRIVERLIST = nut-ipmipsu GPIO_DRIVERLIST = generic_gpio_libgpiod -UPOWER_DRIVERLIST = upower_dbus +UPOWER_DRIVERLIST = nut-upower # distribute all drivers, even ones that are not built by default EXTRA_PROGRAMS = $(SERIAL_DRIVERLIST) $(USB_DRIVERLIST) $(SERIAL_USB_DRIVERLIST) @@ -371,9 +371,9 @@ if HAVE_GLIB # Only build upower if GLib was found driverexec_PROGRAMS += $(UPOWER_DRIVERLIST) - upower_dbus_SOURCES = upower_dbus.c - upower_dbus_LDADD = $(LDADD_DRIVERS) $(GLIB_LIBS) - upower_dbus_CFLAGS = $(AM_CFLAGS) $(GLIB_CFLAGS) + nut_upower_SOURCES = nut-upower.c + nut_upower_LDADD = $(LDADD_DRIVERS) $(GLIB_LIBS) + nut_upower_CFLAGS = $(AM_CFLAGS) $(GLIB_CFLAGS) endif # SNMP diff --git a/drivers/upower_dbus.c b/drivers/nut-upower.c similarity index 99% rename from drivers/upower_dbus.c rename to drivers/nut-upower.c index c8b120da67..7ac799338f 100644 --- a/drivers/upower_dbus.c +++ b/drivers/nut-upower.c @@ -1,4 +1,4 @@ -/* drivers/upower_dbus.c - Driver for UPower via D-Bus +/* drivers/nut-upower.c - Driver for UPower via D-Bus * * Copyright (C) 2026 Tim Niemueller * From 6cfa1a6e910079199301ae4742f1efa2da35c6b7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 24 Jan 2026 20:00:58 +0100 Subject: [PATCH 006/198] tools/nut-scanner/scan_ipmi.c, drivers/nut-ipmipsu.c: fixed an issue where multiple calls to clean-up crashed the program [#3193] Special thanks to maintainer of libfreeipmi for helping catch it! Signed-off-by: Jim Klimov Co-authored-by: Albert Chu --- NEWS.adoc | 4 ++++ docs/man/nut-ipmipsu.txt | 10 ---------- drivers/nut-ipmipsu.c | 2 +- drivers/nut-libfreeipmi.c | 7 +++++++ tools/nut-scanner/scan_ipmi.c | 5 +++++ 5 files changed, 17 insertions(+), 11 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index c30766204a..8a6a7b2b43 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -127,6 +127,10 @@ https://github.com/networkupstools/nut/milestone/12 referenced by this table, so now several higher speeds would be compiled conditionally. [issue #3163] + - `nut-ipmipsu` driver updates: + * Fixed an issue where multiple calls to clean-up crashed the program. + Special thanks to maintainer of libfreeipmi for helping catch it. [#3193] + - `nutdrv_qx` driver updates: * Define an internal `QX_FLAG_MAPPING_HANDLED` to check if the subdriver code (mapping table) and the data found from device walk sit together diff --git a/docs/man/nut-ipmipsu.txt b/docs/man/nut-ipmipsu.txt index 9b94a10728..e3ea950b97 100644 --- a/docs/man/nut-ipmipsu.txt +++ b/docs/man/nut-ipmipsu.txt @@ -105,16 +105,6 @@ Here is an example output for a Dell r610 server: KNOWN ISSUES ------------ -According to the research in https://github.com/networkupstools/nut/issues/3193 -the driver (or technically the libfreeipmi used in it) may have troubles if it -changes the run-time user account, which NUT drivers usually do when started as -`root` by init scripts -- by default they drop privileges to the configured -user account such as `nut`, `ups` or `nobody`. If your driver fails to start, -possibly with a segmentation fault reported, try either changing the context -to the unprivileged user in init scripts (using `su` or `sudo`) or systemd unit -(using a drop-in file to set `User=...` in `[Service]` section) before starting -the actual driver program, or try setting `user=root` in its `ups.conf` section. - include::networked_hostnames.txt[] AUTHOR diff --git a/drivers/nut-ipmipsu.c b/drivers/nut-ipmipsu.c index c9229f8e7a..6906c7ed02 100644 --- a/drivers/nut-ipmipsu.c +++ b/drivers/nut-ipmipsu.c @@ -27,7 +27,7 @@ #include "nut-ipmi.h" #define DRIVER_NAME "IPMI PSU driver" -#define DRIVER_VERSION "0.36" +#define DRIVER_VERSION "0.37" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/nut-libfreeipmi.c b/drivers/nut-libfreeipmi.c index 8e37414772..53eebf86a7 100644 --- a/drivers/nut-libfreeipmi.c +++ b/drivers/nut-libfreeipmi.c @@ -336,25 +336,30 @@ static void libfreeipmi_cleanup(void) if (fru_ctx) { ipmi_fru_close_device_id (fru_ctx); ipmi_fru_ctx_destroy (fru_ctx); + fru_ctx = NULL; } if (sdr_ctx) { ipmi_sdr_ctx_destroy (sdr_ctx); + sdr_ctx = NULL; } #ifndef HAVE_FREEIPMI_11X_12X if (sdr_parse_ctx) { ipmi_sdr_parse_ctx_destroy (sdr_parse_ctx); + sdr_parse_ctx = NULL; } #endif if (ipmi_ctx) { ipmi_ctx_close (ipmi_ctx); ipmi_ctx_destroy (ipmi_ctx); + ipmi_ctx = NULL; } if (mon_ctx) { ipmi_monitoring_ctx_destroy (mon_ctx); + mon_ctx = NULL; } } @@ -808,11 +813,13 @@ static int libfreeipmi_get_sensors_info (IPMIDevice_t *ipmi_dev) /* Cleanup */ if (sdr_ctx) { ipmi_sdr_ctx_destroy (sdr_ctx); + sdr_ctx = NULL; } #ifndef HAVE_FREEIPMI_11X_12X if (sdr_parse_ctx) { ipmi_sdr_parse_ctx_destroy (sdr_parse_ctx); + sdr_parse_ctx = NULL; } #endif /* HAVE_FREEIPMI_11X_12X */ diff --git a/tools/nut-scanner/scan_ipmi.c b/tools/nut-scanner/scan_ipmi.c index 9764be8a6d..f847a5e931 100644 --- a/tools/nut-scanner/scan_ipmi.c +++ b/tools/nut-scanner/scan_ipmi.c @@ -306,22 +306,26 @@ static void nut_freeipmi_cleanup(ipmi_fru_parse_ctx_t fru_parse_ctx, if (fru_parse_ctx) { (*nut_ipmi_fru_close_device_id) (fru_parse_ctx); (*nut_ipmi_fru_ctx_destroy) (fru_parse_ctx); + fru_parse_ctx = NULL; } #ifdef HAVE_FREEIPMI_11X_12X if (sdr_ctx) { (*nut_ipmi_sdr_ctx_destroy) (sdr_ctx); + sdr_ctx = NULL; } #else /* HAVE_FREEIPMI_11X_12X */ if (sdr_cache_ctx) { (*nut_ipmi_sdr_cache_ctx_destroy) (sdr_cache_ctx); + sdr_cache_ctx = NULL; } if (sdr_parse_ctx) { (*nut_ipmi_sdr_parse_ctx_destroy) (sdr_parse_ctx); + sdr_parse_ctx = NULL; } #endif /* HAVE_FREEIPMI_11X_12X */ @@ -641,6 +645,7 @@ nutscan_device_t * nutscan_scan_ipmi_device(const char * IPaddr, nutscan_ipmi_t if (ipmi_ctx) { (*nut_ipmi_ctx_close) (ipmi_ctx); (*nut_ipmi_ctx_destroy) (ipmi_ctx); + ipmi_ctx = NULL; } return current_nut_dev; From 18752eb6fb822b36a10d8abaaeb0fff2ca7a2e72 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 24 Jan 2026 20:04:22 +0100 Subject: [PATCH 007/198] .github/workflows/01-make-dist.yml, .github/workflows/05-codeql.yml: add libglib2.0-dev [#3279] Signed-off-by: Jim Klimov --- .github/workflows/01-make-dist.yml | 1 + .github/workflows/05-codeql.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/01-make-dist.yml b/.github/workflows/01-make-dist.yml index 5dad7a7122..863420c565 100644 --- a/.github/workflows/01-make-dist.yml +++ b/.github/workflows/01-make-dist.yml @@ -141,6 +141,7 @@ jobs: libfreeipmi-dev libipmimonitoring-dev \ libavahi-common-dev libavahi-core-dev libavahi-client-dev \ libgpiod-dev \ + libglib2.0-dev \ bash dash ksh busybox \ libneon27-gnutls-dev \ build-essential git-core libi2c-dev i2c-tools lm-sensors \ diff --git a/.github/workflows/05-codeql.yml b/.github/workflows/05-codeql.yml index 1bcb5d5f78..b9c5ffba73 100644 --- a/.github/workflows/05-codeql.yml +++ b/.github/workflows/05-codeql.yml @@ -88,7 +88,7 @@ jobs: sudo dpkg-reconfigure man-db sudo apt update case x"${{matrix.compiler}}" in x*clang*) sudo apt install clang ;; x*) sudo apt install gcc g++ ;; esac - sudo apt install libltdl-dev libtool libtool-bin cppcheck ccache libgd-dev libcppunit-dev libsystemd-dev libssl-dev libnss3-dev augeas-tools libaugeas-dev augeas-lenses libusb-dev libusb-1.0-0-dev libmodbus-dev libsnmp-dev libpowerman0-dev libfreeipmi-dev libipmimonitoring-dev libavahi-common-dev libavahi-core-dev libavahi-client-dev libgpiod-dev libneon27-dev libi2c-dev i2c-tools lm-sensors ccache + sudo apt install libltdl-dev libtool libtool-bin cppcheck ccache libgd-dev libcppunit-dev libsystemd-dev libssl-dev libnss3-dev augeas-tools libaugeas-dev augeas-lenses libusb-dev libusb-1.0-0-dev libmodbus-dev libsnmp-dev libpowerman0-dev libfreeipmi-dev libipmimonitoring-dev libavahi-common-dev libavahi-core-dev libavahi-client-dev libgpiod-dev libglib2.0-dev libneon27-dev libi2c-dev i2c-tools lm-sensors ccache date > .timestamp-init - name: Prepare ccache From 49060909f6a99ecb75075849a64be68f86bb8e52 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 24 Jan 2026 15:57:19 +0100 Subject: [PATCH 008/198] scripts/obs/_service: survive git tags with a dash [#1209] Avoid RPM build error like: line 121: Illegal char '-' (0x2d) in: Version: 2.8.5-rc1.12+g3501cd37 Signed-off-by: Jim Klimov --- scripts/obs/_service | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/obs/_service b/scripts/obs/_service index 81a37d0ecf..2f1fd332ae 100644 --- a/scripts/obs/_service +++ b/scripts/obs/_service @@ -7,7 +7,9 @@ @PARENT_TAG@.@TAG_OFFSET@ - v(.*) + + v([^-]*)-*(.*) + \1\2 .git nut From c957880360a8f7d3ed5796b2d59046e6f8ec502b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 23 Jan 2026 11:12:25 +0100 Subject: [PATCH 009/198] drivers/upsdrvctl.c, NEWS.adoc, conf/ups.conf.sample, docs: apply global debug_min from ups.conf also to upsdrvctl tool itself [#3276] Signed-off-by: Jim Klimov --- NEWS.adoc | 2 ++ conf/ups.conf.sample | 7 ++-- docs/man/ups.conf.txt | 5 +-- docs/man/upsdrvctl.txt | 5 +++ drivers/upsdrvctl.c | 82 ++++++++++++++++++++++++++++++++++-------- 5 files changed, 82 insertions(+), 19 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index 8a6a7b2b43..65ec699e57 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -246,6 +246,8 @@ https://github.com/networkupstools/nut/milestone/12 - `upsdrvctl` tool updates: * Make use of `setproctag()` and `getproctag()` to report parent/child process names. [#3084] + * The global-level `debug_min` setting in `ups.conf` now also applies + to bumping the debug verbosity of `upsdrvctl` tool. [#3276] - `upslog` tool updates: * Updated `help()` and failure messages to suggest `-m '*,-'` for logging diff --git a/conf/ups.conf.sample b/conf/ups.conf.sample index d9eabf1853..4d04554001 100644 --- a/conf/ups.conf.sample +++ b/conf/ups.conf.sample @@ -113,9 +113,10 @@ maxretry = 3 # The default is 75 seconds. # # debug_min: OPTIONAL. Specify a minimum debug level for all driver daemons -# (when specified at global level), or for this driver daemon -# (when specified in a driver section), e.g. for troubleshooting -# a deployment. This does not directly impact the foreground or +# and for the upsdrvctl tool (when specified at global level), +# or for this driver daemon (when specified in a driver section), +# e.g. for troubleshooting a deployment without changing init +# scripts. This does not directly impact the foreground or # background running mode. If both the global and driver level # `debug_min` are set, the driver-level setting takes precedence. # Command-line option `-D` can only increase this verbosity level. diff --git a/docs/man/ups.conf.txt b/docs/man/ups.conf.txt index d083b091af..9211df7121 100644 --- a/docs/man/ups.conf.txt +++ b/docs/man/ups.conf.txt @@ -183,8 +183,9 @@ or with device filesystems re-generated by an OS for every reboot. *debug_min* 'INTEGER':: -Optional. Specify a minimum debug level for all driver daemons, e.g. for -troubleshooting a deployment, without impacting foreground or background +Optional. Specify a minimum debug level for all driver daemons and +for the linkman:upsdrvctl[8] tool, e.g. for troubleshooting a deployment +without changing init scripts, without impacting foreground or background running mode directly. Command-line option `-D` can only increase this verbosity level. diff --git a/docs/man/upsdrvctl.txt b/docs/man/upsdrvctl.txt index cdd31deb77..dee0488f47 100644 --- a/docs/man/upsdrvctl.txt +++ b/docs/man/upsdrvctl.txt @@ -81,6 +81,11 @@ global section. *-D*:: Raise the debug level. Use this multiple times for additional details. +Alternatively the value can be set via +debug_min+ in global section of +linkman:ups.conf[5]. Note the global setting applies to both the tool +and a started driver; but another line in a driver's individual section +can override that with a larger or smaller value (including a `debug_min=0` +to disable tracing the driver by default). + Note that this does not preclude the `upsdrvctl` tool from exiting after its job is done (however an explicit *-F* option does). diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index 08bbf12e26..2a1bc7706e 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -92,6 +92,17 @@ static char *pt_root = NULL, *pt_user = NULL, *pt_cmd = NULL; static int nut_debug_level_passthrough = 0; static int nut_foreground_passthrough = -1; +/* Users can pass a -D[...] option to enable debugging. + * For the service tracing purposes, also the ups.conf + * can define a debug_min value in the global or device + * section, to set the minimal debug level (CLI provided + * value less than that would not have effect, can only + * have more). Finally, it can also be set over socket + * protocol, taking precedence over other inputs. + */ +static int nut_debug_level_args = -1; +static int nut_debug_level_global = -1; + /* Keep track of requested operation (function pointer) */ static void (*command)(const ups_t *) = NULL; @@ -107,6 +118,28 @@ static int signal_flag = 0; static char *signal_flag = NULL; #endif /* WIN32 */ +/* Reduced version of code from drivers/main.c */ +static void assign_debug_level(void) { + /* CLI debug level can not be smaller than debug_min specified + * in ups.conf, and for upsdrvctl tool we care about the global + * value (not any specified for a driver config section). + * Note that a non-zero debug_min does not impact foreground + * running mode. + */ + + /* At minimum, use the verbosity we started with - via CLI + * arguments; but maybe a greater debug_min is set in current + * config file. + */ + nut_debug_level = nut_debug_level_args; + if (nut_debug_level_global > nut_debug_level) { + /* Applying debug_min=%d from ups.conf global section */ + nut_debug_level = nut_debug_level_global; + } + + upsdebugx(1, "debug level for upsdrvctl is '%d'", nut_debug_level); +} + void do_upsconf_args(char *arg_upsname, char *var, char *val) { ups_t *tmp, *last; @@ -141,6 +174,22 @@ void do_upsconf_args(char *arg_upsname, char *var, char *val) } } + /* Allow to specify its minimal debugging level for all drivers - + * or the upsdrvctl tool here - and admins can set more with + * command-line args, but can't set less without changing config. + * Should help debug of services. + */ + if (!strcasecmp(var, "debug_min")) { + int lvl = -1; /* typeof common/common.c: int nut_debug_level */ + if ( str_to_int (val, &lvl, 10) && lvl >= 0 ) { + nut_debug_level_global = lvl; + } else { + upslogx(LOG_INFO, "WARNING : Invalid debug_min value found in ups.conf global settings"); + } + + return; + } + /* ignore anything else - it's probably for main */ return; @@ -897,7 +946,8 @@ static void status_driver(const ups_t *ups) #ifndef WIN32 snprintf(pidfn, sizeof(pidfn), "%s/%s-%s.pid", altpidpath(), ups->driver, ups->upsname); pidFromFile = parsepidfile(pidfn); - if (pidFromFile >= 0) { /* this method actively reports errors, if any */ + if (pidFromFile >= 0) { + /* this method actively reports errors, if any */ cmdret = sendsignalpid(pidFromFile, 0, ups->driver, 1); /* returns zero for a successfully sent signal */ if (cmdret == 0) @@ -1509,7 +1559,9 @@ int main(int argc, char **argv) exit(EXIT_SUCCESS); case 'D': - nut_debug_level++; + if (nut_debug_level_args < 0) + nut_debug_level_args = 0; + nut_debug_level_args++; break; case 'd': @@ -1607,10 +1659,10 @@ int main(int argc, char **argv) char *s = getenv("NUT_DEBUG_LEVEL"); int l; if (s && str_to_int(s, &l, 10)) { - if (l > 0 && nut_debug_level < 1) { + if (l > 0 && nut_debug_level_args < 1) { upslogx(LOG_INFO, "Defaulting debug verbosity to NUT_DEBUG_LEVEL=%d " "since none was requested by command-line options", l); - nut_debug_level = l; + nut_debug_level_args = l; } /* else follow -D settings */ } /* else nothing to bother about */ } @@ -1660,6 +1712,18 @@ int main(int argc, char **argv) if (!command) fatalx(EXIT_FAILURE, "Error: unrecognized command [%s]", argv[0]); +#ifndef WIN32 + driverpath = xstrdup(DRVPATH); /* set default */ +#else /* WIN32 */ + driverpath = getfullpath2(DRVPATH, PATH_BIN); /* Can get converted to relative path in WIN32 */ +#endif /* WIN32 */ + + atexit(exit_cleanup); + + read_upsconf(1); + + assign_debug_level(); + if (nut_debug_level_passthrough == 0 && (command == &start_driver || command == &shutdown_driver)) { upsdebugx(2, "\n" "If you're not a NUT core developer, chances are that you're told to enable debugging\n" @@ -1673,16 +1737,6 @@ int main(int argc, char **argv) "pass its current debug level to the launched driver, and '-B' keeps it backgrounded.\n"); } -#ifndef WIN32 - driverpath = xstrdup(DRVPATH); /* set default */ -#else /* WIN32 */ - driverpath = getfullpath2(DRVPATH, PATH_BIN); /* Can get converted to relative path in WIN32 */ -#endif /* WIN32 */ - - atexit(exit_cleanup); - - read_upsconf(1); - if (argc == lastarg) { ups_t *tmp = upstable; char tag[SMALLBUF]; From 034cf8bc4e61027823725c661459af23ce064fc8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 23 Jan 2026 12:59:08 +0100 Subject: [PATCH 010/198] drivers/upsdrvctl.c: if we fail to stop a driver by signal, retry to "exit" it by protocol [#3277] Signed-off-by: Jim Klimov --- NEWS.adoc | 2 ++ drivers/upsdrvctl.c | 32 +++++++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/NEWS.adoc b/NEWS.adoc index 65ec699e57..d2076b68ea 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -248,6 +248,8 @@ https://github.com/networkupstools/nut/milestone/12 process names. [#3084] * The global-level `debug_min` setting in `ups.conf` now also applies 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] - `upslog` tool updates: * Updated `help()` and failure messages to suggest `-m '*,-'` for logging diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index 2a1bc7706e..3c9091f9c9 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -437,8 +437,38 @@ static void stop_driver(const ups_t *ups) } if (ret != 0) { + ssize_t udq_ret; + udq_pipe_conn_t *udq_pipe; + upslog_with_errno(LOG_ERR, "Can't open %s either", pidfn); - exec_error++; + + udq_pipe = upsdrvquery_connect_drvname_upsname(ups->driver, ups->upsname); + if (udq_pipe) + upslogx(LOG_ERR, "At least could open the driver socket"); + if (testmode) { + udq_ret = (udq_pipe == NULL ? -1 : 0); + } else { + char buf[LARGEBUF]; + struct timeval tv; + + memset(buf, 0, sizeof(buf)); + /* Post the query and wait for reply */ + /* FIXME: coordinate with pollfreq? */ + tv.tv_sec = 15; + tv.tv_usec = 0; + udq_ret = upsdrvquery_oneshot_conn(udq_pipe, "INSTCMD driver.exit\n", buf, sizeof(buf), &tv); + upsdebugx(1, "%s: upsdrvquery_oneshot_conn() replied to 'exit': '%s'", __func__, buf); + } + upsdrvquery_close(udq_pipe); + + upslogx(LOG_ERR, "%s to %s the 'exit' command to the driver socket", + udq_ret < 0 ? "Failed" : "Succeeded", + testmode ? "emulate" : "send"); + + if (udq_ret < 0) { + exec_error++; + } + return; } } else { From ed67ebedb568a896dc7d82ced0426ac49b1d9918 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 23 Jan 2026 15:48:14 +0100 Subject: [PATCH 011/198] drivers/upsdrvquery.c: protect upsdrvquery_close() from SIGPIPE crash if the other side exited [#3277] Signed-off-by: Jim Klimov --- drivers/upsdrvquery.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index 0fc348ec5f..a011d2cc7e 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -187,8 +187,39 @@ void upsdrvquery_close(udq_pipe_conn_t *conn) { if (VALID_FD(conn->sockfd)) { int nudl = nut_upsdrvquery_debug_level; ssize_t ret; + + /* The connection may be closed on the other side, + * so send() can issue SIGPIPE and by default the + * process crashes. Try to work around that here. + * https://stackoverflow.com/questions/108183/how-to-prevent-sigpipes-or-handle-them-properly + * TODO: Consider mixing send() and MSG_NOSIGNAL + * where available. + */ +#ifndef WIN32 + sigset_t old_state, set; + + /* get the current state */ + sigprocmask(SIG_BLOCK, NULL, &old_state); + + /* add signal_to_block to that existing state */ + set = old_state; + sigaddset(&set, SIGPIPE); + + /* block that signal also */ + sigprocmask(SIG_BLOCK, &set, NULL); +# ifdef SO_NOSIGPIPE + setsockopt(conn->sockfd, SO_NOSIGPIPE); +# endif /* SO_NOSIGPIPE */ +#endif /* !WIN32 */ + upsdebugx(5, "%s: closing driver socket, try to say goodbye", __func__); + ret = upsdrvquery_write(conn, "LOGOUT\n"); + +#ifndef WIN32 + sigprocmask(SIG_BLOCK, &old_state, NULL); +#endif /* !WIN32 */ + if (7 <= ret) { upsdebugx(5, "%s: okay", __func__); #ifdef WIN32 From 4335c2932553e6aa6b05adbd586253836ffa488c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 23 Jan 2026 15:48:52 +0100 Subject: [PATCH 012/198] drivers/upsdrvquery.{c,h}: separate upsdrvquery_ping() from upsdrvquery_prepare() [#3277] Signed-off-by: Jim Klimov --- drivers/upsdrvquery.c | 72 +++++++++++++++++++++++++++---------------- drivers/upsdrvquery.h | 3 ++ 2 files changed, 49 insertions(+), 26 deletions(-) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index a011d2cc7e..f922a5acac 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -455,35 +455,29 @@ ssize_t upsdrvquery_write(udq_pipe_conn_t *conn, const char *buf) { return -1; } -ssize_t upsdrvquery_prepare(udq_pipe_conn_t *conn, struct timeval tv) { - struct timeval start, now; - - if (!conn || INVALID_FD(conn->sockfd)) - return -1; +/* Return 1 if we had a reply, 0 if not, -1 on socket errors */ +ssize_t upsdrvquery_ping(udq_pipe_conn_t *conn, struct timeval *ptv, useconds_t read_interval) { + struct timeval start, now, tv; - /* Avoid noise */ - if (upsdrvquery_write(conn, "NOBROADCAST\n") < 0) - goto socket_error; - - if (tv.tv_sec < 1 && tv.tv_usec < 1) { - upsdebugx(5, "%s: proclaiming readiness for tracked commands without flush of server messages", __func__); - return 1; + if (!ptv) { + tv.tv_sec = 5; + tv.tv_usec = 0; + ptv = &tv; } - /* flush incoming, if any */ gettimeofday(&start, NULL); if (upsdrvquery_write(conn, "PING\n") < 0) - goto socket_error; + return -1; - upsdebugx(5, "%s: waiting for a while to flush server messages", __func__); while (1) { - char *buf; - upsdrvquery_read_timeout(conn, tv); + char *buf; + + upsdrvquery_read_timeout(conn, *ptv); gettimeofday(&now, NULL); - if (difftimeval(now, start) > ((double)(tv.tv_sec) + 0.000001 * (double)(tv.tv_usec))) { + if (difftimeval(now, start) > ((double)(ptv->tv_sec) + 0.000001 * (double)(ptv->tv_usec))) { upsdebugx(5, "%s: requested timeout expired", __func__); - break; + return 0; } /* Await a PONG for quick confirmation of achieved quietness @@ -498,7 +492,7 @@ ssize_t upsdrvquery_prepare(udq_pipe_conn_t *conn, struct timeval tv) { while (buf && *buf) { if (!strncmp(buf, "PONG\n", 5)) { upsdebugx(5, "%s: got expected PONG", __func__); - goto finish; + return 1; } buf = strchr(buf, '\n'); if (buf) { @@ -511,15 +505,41 @@ ssize_t upsdrvquery_prepare(udq_pipe_conn_t *conn, struct timeval tv) { } /* Diminishing timeouts for read() */ - 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 */ + ptv->tv_usec -= (suseconds_t)(difftimeval(now, start)); + while (ptv->tv_usec < 0) { + ptv->tv_sec--; + ptv->tv_usec = 1000000 + ptv->tv_usec; /* Note it is negative */ } - if (tv.tv_sec <= 0 && tv.tv_usec <= 0) { + if (ptv->tv_sec <= 0 && ptv->tv_usec <= 0) { upsdebugx(5, "%s: requested timeout expired", __func__); - break; + return 0; } + + if (read_interval) + usleep(read_interval); + } +} + +ssize_t upsdrvquery_prepare(udq_pipe_conn_t *conn, struct timeval tv) { + if (!conn || INVALID_FD(conn->sockfd)) + return -1; + + /* Avoid noise */ + if (upsdrvquery_write(conn, "NOBROADCAST\n") < 0) + goto socket_error; + + if (tv.tv_sec < 1 && tv.tv_usec < 1) { + upsdebugx(5, "%s: proclaiming readiness for tracked commands without flush of server messages", __func__); + return 1; + } + + /* flush incoming, if any */ + upsdebugx(5, "%s: waiting for a while to flush server messages - posting a PING, waiting for PONG", __func__); + switch (upsdrvquery_ping(conn, &tv, 1000)) { + case -1: goto socket_error; + case 0: goto finish; /* No reply - maybe handle somehow? */ + case 1: break; /* Got PONG */ + default: break; } /* Check that we can have a civilized dialog -- diff --git a/drivers/upsdrvquery.h b/drivers/upsdrvquery.h index 8d84a4314e..348a11c9d7 100644 --- a/drivers/upsdrvquery.h +++ b/drivers/upsdrvquery.h @@ -42,6 +42,9 @@ void upsdrvquery_close(udq_pipe_conn_t *conn); 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); +/* Return 1 if we had a reply within timeout specified by *ptv (5 sec if NULL), + * 0 if not, -1 on socket errors */ +ssize_t upsdrvquery_ping(udq_pipe_conn_t *conn, struct timeval *ptv, useconds_t read_interval); ssize_t upsdrvquery_prepare(udq_pipe_conn_t *conn, struct timeval tv); ssize_t upsdrvquery_request(udq_pipe_conn_t *conn, struct timeval tv, const char *query); ssize_t upsdrvquery_restore_broadcast(udq_pipe_conn_t *conn); From 11f6d9b71a674698e5e531eed172ee16338f5d8e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 23 Jan 2026 15:49:29 +0100 Subject: [PATCH 013/198] drivers/upsdrvctl.c: upsdrvquery_ping() after telling the driver to stop, so upsdrvctl exits when the driver is gone [#3277] Signed-off-by: Jim Klimov --- drivers/upsdrvctl.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index 3c9091f9c9..f129cdc3db 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -457,18 +457,29 @@ static void stop_driver(const ups_t *ups) tv.tv_sec = 15; tv.tv_usec = 0; udq_ret = upsdrvquery_oneshot_conn(udq_pipe, "INSTCMD driver.exit\n", buf, sizeof(buf), &tv); - upsdebugx(1, "%s: upsdrvquery_oneshot_conn() replied to 'exit': '%s'", __func__, buf); + upsdebugx(1, "%s: upsdrvquery_oneshot_conn() replied to 'exit' (%" PRIiSIZE "): '%s'", __func__, udq_ret, buf); + + if (udq_ret >= 0) { + upsdrvquery_write(udq_pipe, "NOBROADCAST"); + while (upsdrvquery_ping(udq_pipe, &tv, 1000) > 0) { + /* 0 = no reply, -1 = socket error; either way driver deemed dead? */ + upsdebugx(1, "%s: keep waiting for driver exit", __func__); + sleep(1); + } + upsdebugx(1, "%s: final PING did not PONG back", __func__); + } } - upsdrvquery_close(udq_pipe); upslogx(LOG_ERR, "%s to %s the 'exit' command to the driver socket", - udq_ret < 0 ? "Failed" : "Succeeded", + (udq_ret < 0) ? "Failed" : "Succeeded", testmode ? "emulate" : "send"); if (udq_ret < 0) { exec_error++; } + upsdrvquery_close(udq_pipe); + return; } } else { From 1529a108a9892447d84c1c316ee3077579348be7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 24 Jan 2026 12:05:37 +0100 Subject: [PATCH 014/198] drivers/upsdrvquery.c: upsdrvquery_write() use MSG_NOSIGNAL where available [#3277] Proper NUT daemons intercept SIGPIPE and survive closed connections, but consumers of upsdrvquery might not, and would crash. If we can, just return the error (and errno=EPIPE) for the specific call. Signed-off-by: Jim Klimov --- drivers/upsdrvquery.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index f922a5acac..79036acd5b 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -192,7 +192,7 @@ void upsdrvquery_close(udq_pipe_conn_t *conn) { * so send() can issue SIGPIPE and by default the * process crashes. Try to work around that here. * https://stackoverflow.com/questions/108183/how-to-prevent-sigpipes-or-handle-them-properly - * TODO: Consider mixing send() and MSG_NOSIGNAL + * NOTE: in upsdrvquery_write() we use MSG_NOSIGNAL * where available. */ #ifndef WIN32 @@ -430,7 +430,12 @@ ssize_t upsdrvquery_write(udq_pipe_conn_t *conn, const char *buf) { } #ifndef WIN32 +# ifdef MSG_NOSIGNAL + ret = send(conn->sockfd, buf, buflen, MSG_NOSIGNAL); +# else + /* Per docs, same as send() with zero flags value */ ret = write(conn->sockfd, buf, buflen); +# endif if (ret < 0 || ret != (int)buflen) { if (nut_debug_level > 0 || nut_upsdrvquery_debug_level >= NUT_UPSDRVQUERY_DEBUG_LEVEL_DIALOG) From b0479fed9860ff5b36e80f1990b6f0f45d132d85 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 24 Jan 2026 12:17:45 +0100 Subject: [PATCH 015/198] drivers/upsdrvquery.c: upsdrvquery_close(): refactor work with setsockopt(), prefer it over the blanket signal change for the process; handle EPIPE specially [#3277] Signed-off-by: Jim Klimov --- drivers/upsdrvquery.c | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index 79036acd5b..2f76aaa079 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -193,9 +193,22 @@ void upsdrvquery_close(udq_pipe_conn_t *conn) { * process crashes. Try to work around that here. * https://stackoverflow.com/questions/108183/how-to-prevent-sigpipes-or-handle-them-properly * NOTE: in upsdrvquery_write() we use MSG_NOSIGNAL - * where available. + * where available instead of plain write(). */ #ifndef WIN32 +# ifndef MSG_NOSIGNAL +# ifdef SO_NOSIGPIPE + /* Just for this one socket (and gonna be gone soon): */ + int set = 1; + setsockopt(conn->sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int)); +# else /* !SO_NOSIGPIPE */ + /* Not thread-safe, but we do not aim for this here, hopefully + * (any nut-scanner users, though?) and this is a last-resort + * variant during build. Probably plain signal(SIGPIPE, SIG_IGN) + * would be as good (used all over NUT code base) -- but we do + * not know whether a random API consumer handles or ignores + * the signal?.. + */ sigset_t old_state, set; /* get the current state */ @@ -207,9 +220,8 @@ void upsdrvquery_close(udq_pipe_conn_t *conn) { /* block that signal also */ sigprocmask(SIG_BLOCK, &set, NULL); -# ifdef SO_NOSIGPIPE - setsockopt(conn->sockfd, SO_NOSIGPIPE); -# endif /* SO_NOSIGPIPE */ +# endif /* !SO_NOSIGPIPE */ +# endif /* !MSG_NOSIGNAL */ #endif /* !WIN32 */ upsdebugx(5, "%s: closing driver socket, try to say goodbye", __func__); @@ -217,7 +229,11 @@ void upsdrvquery_close(udq_pipe_conn_t *conn) { ret = upsdrvquery_write(conn, "LOGOUT\n"); #ifndef WIN32 +# ifndef MSG_NOSIGNAL +# ifndef SO_NOSIGPIPE sigprocmask(SIG_BLOCK, &old_state, NULL); +# endif /* !SO_NOSIGPIPE */ +# endif /* !MSG_NOSIGNAL */ #endif /* !WIN32 */ if (7 <= ret) { @@ -227,7 +243,15 @@ void upsdrvquery_close(udq_pipe_conn_t *conn) { #endif /* WIN32 */ usleep(1000000); } else { - upsdebugx(5, "%s: must have been closed on the other side", __func__); + if (errno == EPIPE) { + upsdebug_with_errno(5, "%s: write failed, socket must have been closed on the other side - okay for goodbye", __func__); +#ifdef WIN32 + loggedOut = 1; +#endif /* WIN32 */ + usleep(1000000); + } else { + upsdebug_with_errno(5, "%s: write failed", __func__); + } } nut_upsdrvquery_debug_level = nudl; } From ef33fc071349cbb9ae57366867d6050370dcdce0 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 24 Jan 2026 12:30:23 +0100 Subject: [PATCH 016/198] drivers/upsdrvquery.{c,h}, UPGRADING.adoc, NEWS.adoc: introduced upsdrvquery_NOSIGPIPE toggle for consumers who might want to handle SIGPIPE themselves [#3277] Signed-off-by: Jim Klimov --- NEWS.adoc | 6 ++++++ UPGRADING.adoc | 6 ++++++ docs/nut.dict | 4 +++- drivers/upsdrvquery.c | 35 +++++++++++++++++++++++++---------- drivers/upsdrvquery.h | 8 ++++++++ 5 files changed, 48 insertions(+), 11 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index d2076b68ea..eb7c571899 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -83,6 +83,12 @@ https://github.com/networkupstools/nut/milestone/12 * Fixed thread-safety of IP address printout in `libupsclient` method `upscli_tryconnect()` (practical bug seen in `nut-scanner` parallel scans). [issue #3234] + * The `upsdrvquery` code base was revised to handle SIGPIPE without crashing + (if the consumers did not neuter the signal themselves), although this + behavior is optional by `upsdrvquery_NOSIGPIPE`. + Separated an `upsdrvquery_ping()` operation from earlier code, so it can + be directly used by consumers (in-tree this is drivers and `upsdrvctl`). + [issue #3276, PR #3277] - NUT for Windows specific updates: * Revised detection of (relative) paths to program and configuration files diff --git a/UPGRADING.adoc b/UPGRADING.adoc index fdfcdabd60..8b3666b656 100644 --- a/UPGRADING.adoc +++ b/UPGRADING.adoc @@ -93,6 +93,12 @@ Changes from 2.8.4 to 2.8.5 of this new facility to keep working under both old and new file names. [#3101] +- The `upsdrvquery*` semi-internal API for talking on the driver socket was + updated with default handling for SIGPIPE. If your consumer wants to catch + it themselves, instead of using `errno=EPIPE` after a failed call, you can + use `upsdrvquery_NOSIGPIPE=0` to disable neutering of the signal inside + the API itself. [PR #3277] + - Fixed man page naming for `nutdrv_siemens-sitop(.8)` (dash vs. underscore) to match the driver program name. Packaging recipes may have to be updated. Follow-up from slightly botched renaming in original contribution. [PR #545] diff --git a/docs/nut.dict b/docs/nut.dict index 1733c0a17f..7f37733d83 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3632 utf-8 +personal_ws-1.1 en 3634 utf-8 AAC AAS ABI @@ -344,6 +344,7 @@ EOLed EPEL EPERM EPFCLCD +EPIPE EPO EPS ESC @@ -810,6 +811,7 @@ NONBLOCK NONUT NOP NOPARENT +NOSIGPIPE NOTALARM NOTBOOST NOTBYPASS diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index 2f76aaa079..a2fa03293f 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -52,6 +52,14 @@ */ int nut_upsdrvquery_debug_level = NUT_UPSDRVQUERY_DEBUG_LEVEL_DEFAULT; +/* Do our best to disable SIGPIPE in failed write()/send() attempts? + * Note errno=EPIPE should still be raised in case of failure, just + * the process using this code would not crash. Feature is enabled + * by default, but consumers which handle their signals specially + * can disable it by setting upsdrvquery_NOSIGPIPE=0 + */ +int upsdrvquery_NOSIGPIPE = 1; + udq_pipe_conn_t *upsdrvquery_connect(const char *sockfn) { udq_pipe_conn_t *conn = (udq_pipe_conn_t*)xcalloc(1, sizeof(udq_pipe_conn_t)); @@ -200,7 +208,8 @@ void upsdrvquery_close(udq_pipe_conn_t *conn) { # ifdef SO_NOSIGPIPE /* Just for this one socket (and gonna be gone soon): */ int set = 1; - setsockopt(conn->sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int)); + if (upsdrvquery_NOSIGPIPE) + setsockopt(conn->sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int)); # else /* !SO_NOSIGPIPE */ /* Not thread-safe, but we do not aim for this here, hopefully * (any nut-scanner users, though?) and this is a last-resort @@ -211,15 +220,17 @@ void upsdrvquery_close(udq_pipe_conn_t *conn) { */ sigset_t old_state, set; - /* get the current state */ - sigprocmask(SIG_BLOCK, NULL, &old_state); + if (upsdrvquery_NOSIGPIPE) { + /* get the current state */ + sigprocmask(SIG_BLOCK, NULL, &old_state); - /* add signal_to_block to that existing state */ - set = old_state; - sigaddset(&set, SIGPIPE); + /* add signal_to_block to that existing state */ + set = old_state; + sigaddset(&set, SIGPIPE); - /* block that signal also */ - sigprocmask(SIG_BLOCK, &set, NULL); + /* block that signal also */ + sigprocmask(SIG_BLOCK, &set, NULL); + } # endif /* !SO_NOSIGPIPE */ # endif /* !MSG_NOSIGNAL */ #endif /* !WIN32 */ @@ -231,7 +242,8 @@ void upsdrvquery_close(udq_pipe_conn_t *conn) { #ifndef WIN32 # ifndef MSG_NOSIGNAL # ifndef SO_NOSIGPIPE - sigprocmask(SIG_BLOCK, &old_state, NULL); + if (upsdrvquery_NOSIGPIPE) + sigprocmask(SIG_BLOCK, &old_state, NULL); # endif /* !SO_NOSIGPIPE */ # endif /* !MSG_NOSIGNAL */ #endif /* !WIN32 */ @@ -455,7 +467,10 @@ ssize_t upsdrvquery_write(udq_pipe_conn_t *conn, const char *buf) { #ifndef WIN32 # ifdef MSG_NOSIGNAL - ret = send(conn->sockfd, buf, buflen, MSG_NOSIGNAL); + if (upsdrvquery_NOSIGPIPE) + ret = send(conn->sockfd, buf, buflen, MSG_NOSIGNAL); + else + ret = write(conn->sockfd, buf, buflen); # else /* Per docs, same as send() with zero flags value */ ret = write(conn->sockfd, buf, buflen); diff --git a/drivers/upsdrvquery.h b/drivers/upsdrvquery.h index 348a11c9d7..cd2aac5077 100644 --- a/drivers/upsdrvquery.h +++ b/drivers/upsdrvquery.h @@ -63,4 +63,12 @@ extern int nut_upsdrvquery_debug_level; #define NUT_UPSDRVQUERY_DEBUG_LEVEL_CONNECT 5 #define NUT_UPSDRVQUERY_DEBUG_LEVEL_DIALOG 4 +/* Do our best to disable SIGPIPE in failed write()/send() attempts? + * Note errno=EPIPE should still be raised in case of failure, just + * the process using this code would not crash. Feature is enabled + * by default, but consumers which handle their signals specially + * can disable it by setting upsdrvquery_NOSIGPIPE=0 + */ +extern int upsdrvquery_NOSIGPIPE; + #endif /* NUT_UPSDRVQUERY_H_SEEN */ From 461151c94a4b1fbce81ad1f895079ad48808ee46 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 24 Jan 2026 12:35:17 +0100 Subject: [PATCH 017/198] drivers/upsdrvctl.c: stop_driver(): handle not-hearing from the last PONG a bit cleaner [#3277] Signed-off-by: Jim Klimov --- drivers/upsdrvctl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index f129cdc3db..59ab283c15 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -466,7 +466,9 @@ static void stop_driver(const ups_t *ups) upsdebugx(1, "%s: keep waiting for driver exit", __func__); sleep(1); } - upsdebugx(1, "%s: final PING did not PONG back", __func__); + upsdebug_with_errno(1, "%s: final PING did not PONG back", __func__); + /* Let the driver's exit() finish */ + usleep(1000000); } } From 18404a7a89ba8648a1edd2d1c362c0796448ac1b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 24 Jan 2026 13:34:34 +0100 Subject: [PATCH 018/198] drivers/upsdrvquery.c: upsdrvquery_ping(): revise intense reading loop and timeout accounting when the read size remains 0 [#3277] Signed-off-by: Jim Klimov --- drivers/upsdrvctl.c | 6 ++++- drivers/upsdrvquery.c | 59 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 55 insertions(+), 10 deletions(-) diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index 59ab283c15..d1d48d636c 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -461,7 +461,11 @@ static void stop_driver(const ups_t *ups) if (udq_ret >= 0) { upsdrvquery_write(udq_pipe, "NOBROADCAST"); - while (upsdrvquery_ping(udq_pipe, &tv, 1000) > 0) { + /* Poke reads inside ping every 0.1s, not too often but responsive enough + * Sometimes we do get into being able to send PING but as the channel + * is closing, the reads return 0 and errno=Success infinitely. + */ + while (upsdrvquery_ping(udq_pipe, &tv, 100000) > 0) { /* 0 = no reply, -1 = socket error; either way driver deemed dead? */ upsdebugx(1, "%s: keep waiting for driver exit", __func__); sleep(1); diff --git a/drivers/upsdrvquery.c b/drivers/upsdrvquery.c index a2fa03293f..a105e53624 100644 --- a/drivers/upsdrvquery.c +++ b/drivers/upsdrvquery.c @@ -501,25 +501,39 @@ ssize_t upsdrvquery_write(udq_pipe_conn_t *conn, const char *buf) { /* Return 1 if we had a reply, 0 if not, -1 on socket errors */ ssize_t upsdrvquery_ping(udq_pipe_conn_t *conn, struct timeval *ptv, useconds_t read_interval) { - struct timeval start, now, tv; + struct timeval start, now, last, tv; + double maxdiff; if (!ptv) { tv.tv_sec = 5; tv.tv_usec = 0; ptv = &tv; } + maxdiff = (double)(ptv->tv_sec) + 0.000001 * (double)(ptv->tv_usec); gettimeofday(&start, NULL); if (upsdrvquery_write(conn, "PING\n") < 0) return -1; + last = start; while (1) { char *buf; + ssize_t read_ret; + double delta; + + errno = 0; + read_ret = upsdrvquery_read_timeout(conn, *ptv); + + if (errno == EPIPE) { + upsdebug_with_errno(5, "%s: upsdrvquery_read_timeout() connection was closed: %" PRIiSIZE, __func__, read_ret); + return -1; + } + + upsdebug_with_errno(5, "%s: upsdrvquery_read_timeout() returned %" PRIiSIZE, __func__, read_ret); - upsdrvquery_read_timeout(conn, *ptv); gettimeofday(&now, NULL); - if (difftimeval(now, start) > ((double)(ptv->tv_sec) + 0.000001 * (double)(ptv->tv_usec))) { + if (difftimeval(now, start) > maxdiff) { upsdebugx(5, "%s: requested timeout expired", __func__); return 0; } @@ -548,19 +562,46 @@ ssize_t upsdrvquery_ping(udq_pipe_conn_t *conn, struct timeval *ptv, useconds_t } } - /* Diminishing timeouts for read() */ - ptv->tv_usec -= (suseconds_t)(difftimeval(now, start)); + if (read_interval) { + upsdebugx(5, "%s: sleep %" PRIuMAX "usec", __func__, (uintmax_t)read_interval); + usleep(read_interval); + } + + /* Diminishing timeouts for read() and later processing */ + last = now; + gettimeofday(&now, NULL); + delta = difftimeval(now, last); + upsdebugx(7, "%s: start tv={sec=%" PRIiMAX ", usec=%06" PRIiMAX "}", + __func__, (intmax_t)start.tv_sec, (intmax_t)start.tv_usec); + upsdebugx(7, "%s: last tv={sec=%" PRIiMAX ", usec=%06" PRIiMAX "}", + __func__, (intmax_t)last.tv_sec, (intmax_t)last.tv_usec); + upsdebugx(7, "%s: now tv={sec=%" PRIiMAX ", usec=%06" PRIiMAX "}", + __func__, (intmax_t)now.tv_sec, (intmax_t)now.tv_usec); + upsdebugx(6, "%s: initial tv={sec=%" PRIiMAX ", usec=%06" PRIiMAX "}; applying delta %g", + __func__, (intmax_t)ptv->tv_sec, (intmax_t)ptv->tv_usec, + delta); + + /* Note: delta is in whole seconds and fractional useconds */ + while (delta > 1) { + delta -= 1; + ptv->tv_sec--; + } + + /* Fractional remainder */ + ptv->tv_usec -= (suseconds_t)(delta * 1000000); + upsdebugx(7, "%s: semiupd tv={sec=%" PRIiMAX ", usec=%06" PRIiMAX "} (1e6*delta = %" PRIiMAX ")", + __func__, (intmax_t)ptv->tv_sec, (intmax_t)ptv->tv_usec, + (intmax_t)(delta * 1000000)); while (ptv->tv_usec < 0) { ptv->tv_sec--; ptv->tv_usec = 1000000 + ptv->tv_usec; /* Note it is negative */ } - if (ptv->tv_sec <= 0 && ptv->tv_usec <= 0) { + upsdebugx(6, "%s: updated tv={sec=%" PRIiMAX ", usec=%06" PRIiMAX "}", + __func__, (intmax_t)ptv->tv_sec, (intmax_t)ptv->tv_usec); + if (ptv->tv_sec < 0) { upsdebugx(5, "%s: requested timeout expired", __func__); return 0; } - - if (read_interval) - usleep(read_interval); } } From 1a069665eea31ba734f9fb6e2cf7b48b918f03ae Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 24 Jan 2026 15:36:27 +0100 Subject: [PATCH 019/198] drivers/upsdrvctl.c: stop_driver(): if upsdrvquery_connect_drvname_upsname() failed, try another in case the driver is still starting and we were called too soon [#3277] Signed-off-by: Jim Klimov --- drivers/upsdrvctl.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index d1d48d636c..65a343cd03 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -438,13 +438,28 @@ static void stop_driver(const ups_t *ups) if (ret != 0) { ssize_t udq_ret; - udq_pipe_conn_t *udq_pipe; + udq_pipe_conn_t *udq_pipe; upslog_with_errno(LOG_ERR, "Can't open %s either", pidfn); udq_pipe = upsdrvquery_connect_drvname_upsname(ups->driver, ups->upsname); - if (udq_pipe) + if (udq_pipe) { upslogx(LOG_ERR, "At least could open the driver socket"); + } else { + /* There IS a chance that the driver is still + * starting and not listening on the socket yet. + * FIXME: Could align with ups->maxstartdelay... + * but if it is just not running -- this may + * mean minutes of fruitless sleep. + */ + upsdebugx(1, "%s: initial driver socket connection failed, retrying shortly", __func__); + sleep(5); + udq_pipe = upsdrvquery_connect_drvname_upsname(ups->driver, ups->upsname); + if (udq_pipe) { + upslogx(LOG_ERR, "At least could open the driver socket"); + } + } + if (testmode) { udq_ret = (udq_pipe == NULL ? -1 : 0); } else { @@ -481,6 +496,8 @@ static void stop_driver(const ups_t *ups) testmode ? "emulate" : "send"); if (udq_ret < 0) { + upslogx(LOG_ERR, "Failed to stop the driver %s for %s, it may be not running or not fully started yet", + ups->driver, ups->upsname); exec_error++; } From 7408a4ec07b0046a16884ef193c3352789945a61 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 24 Jan 2026 15:37:08 +0100 Subject: [PATCH 020/198] drivers/upsdrvctl.c: stop_driver(): try shorter PING first, so a closed socket is detected earlier [#3277] Signed-off-by: Jim Klimov --- drivers/upsdrvctl.c | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index 65a343cd03..083b3a644b 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -469,21 +469,46 @@ static void stop_driver(const ups_t *ups) memset(buf, 0, sizeof(buf)); /* Post the query and wait for reply */ /* FIXME: coordinate with pollfreq? */ - tv.tv_sec = 15; + + /* Below we poke reads inside ping every 0.1s, + * which is not too often but responsive enough. + * Sometimes we do get into being able to send + * "PING" but as the channel is closing, the + * reads return 0 and errno=Success infinitely. + * So we first ping with a 1-second timeout, + * then retry (and maybe fail instantly but + * definitely with EPIPE) with a 3-sec backoff, + * and then again with a longer common countdown + * (tv = 15.0s caried over remaining retries). + */ + tv.tv_sec = 1; tv.tv_usec = 0; udq_ret = upsdrvquery_oneshot_conn(udq_pipe, "INSTCMD driver.exit\n", buf, sizeof(buf), &tv); upsdebugx(1, "%s: upsdrvquery_oneshot_conn() replied to 'exit' (%" PRIiSIZE "): '%s'", __func__, udq_ret, buf); if (udq_ret >= 0) { + int n = 0; + upsdrvquery_write(udq_pipe, "NOBROADCAST"); - /* Poke reads inside ping every 0.1s, not too often but responsive enough - * Sometimes we do get into being able to send PING but as the channel - * is closing, the reads return 0 and errno=Success infinitely. - */ - while (upsdrvquery_ping(udq_pipe, &tv, 100000) > 0) { + while (upsdrvquery_ping(udq_pipe, &tv, 100000) > (n == 0 ? -1 : 0)) { /* 0 = no reply, -1 = socket error; either way driver deemed dead? */ upsdebugx(1, "%s: keep waiting for driver exit", __func__); sleep(1); + n++; + switch (n) { + case 1: + /* New TO for longer backoff, once */ + tv.tv_sec = 3; + tv.tv_usec = 0; + break; + case 2: + /* New TO overall, set once */ + tv.tv_sec = 15; + tv.tv_usec = 0; + break; + default: + break; + } } upsdebug_with_errno(1, "%s: final PING did not PONG back", __func__); /* Let the driver's exit() finish */ From c34b4fa25896c06cd8c3c166d556dae0cc29fb08 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 24 Jan 2026 20:07:16 +0100 Subject: [PATCH 021/198] docs/nut.dict: add gio [#3279] Signed-off-by: Jim Klimov --- docs/nut.dict | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/nut.dict b/docs/nut.dict index 3343fd1e38..14a80931c8 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3638 utf-8 +personal_ws-1.1 en 3639 utf-8 AAC AAS ABI @@ -2196,6 +2196,7 @@ gitignore gitk gitlab gitlog +gio gmail gmake gmtime From b1a0a8539cb87d4e9361fd36d21e80a008c9880f Mon Sep 17 00:00:00 2001 From: Tim Niemueller Date: Sat, 24 Jan 2026 20:37:48 +0100 Subject: [PATCH 022/198] Update doc/nut.dict from make spellcheck-interactive Add missing terms. Signed-off-by: Tim Niemueller --- docs/nut.dict | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/nut.dict b/docs/nut.dict index 14a80931c8..b6eecbd4cc 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3639 utf-8 +personal_ws-1.1 en 3641 utf-8 AAC AAS ABI @@ -1315,6 +1315,7 @@ SyntaxWarning Sysgration SyslogIdentifier SystemIO +SystemRoot Systeme Syu Szady @@ -2190,13 +2191,13 @@ getval getvar gh gif +gio gitcache github gitignore gitk gitlab gitlog -gio gmail gmake gmtime @@ -2440,6 +2441,7 @@ libexecdir libexpat libfreeipmi libgd +libglib libgpgme libgpiod libhid From ba4f907b91d02434a8446136ef294edf81360f71 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 26 Jan 2026 12:09:51 +0100 Subject: [PATCH 023/198] drivers/arduino-hid.c, NEWS.adoc, docs/nut.dict: add `ups.load`, `input.voltage`, `output.voltage` for e.g. Ugreen US3000 [#3281] Signed-off-by: Jim Klimov --- NEWS.adoc | 2 ++ docs/nut.dict | 3 ++- drivers/arduino-hid.c | 6 +++++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index eb7c571899..e4bf18272c 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -233,6 +233,8 @@ https://github.com/networkupstools/nut/milestone/12 continues polling rather than triggering expensive reconnection attempts. True disconnections are still detected via other error codes or when all polls fail. [issue #3116] + * `arduino-hid` subdriver enhanced with `ups.load`, `input.voltage` and + `output.voltage` readings where supported (e.g. Ugreen US3000). [#3281] - `nut-scanner` tool updates: * Fixed `nut-scanner` search for "simulation devices" to not use only the diff --git a/docs/nut.dict b/docs/nut.dict index 7f37733d83..f0e22b1272 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3634 utf-8 +personal_ws-1.1 en 3635 utf-8 AAC AAS ABI @@ -1427,6 +1427,7 @@ UUU UUUU UX Ubuntu +Ugreen Ulf Ulfat Uncomment diff --git a/drivers/arduino-hid.c b/drivers/arduino-hid.c index 4aa47c685d..1bf448cf5b 100644 --- a/drivers/arduino-hid.c +++ b/drivers/arduino-hid.c @@ -36,7 +36,7 @@ #include "main.h" /* for getval() */ #include "usb-common.h" -#define ARDUINO_HID_VERSION "Arduino HID 0.21" +#define ARDUINO_HID_VERSION "Arduino HID 0.22" /* FIXME: experimental flag to be put in upsdrv_info */ /* Arduino */ @@ -110,6 +110,10 @@ static hid_info_t arduino_hid2nut[] = { { "battery.charge.low", 0, 0, "UPS.PowerSummary.RemainingCapacityLimit", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL}, { "battery.charge.warning", 0, 0, "UPS.PowerSummary.WarningCapacityLimit", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL}, + { "ups.load", 0, 0, "UPS.PowerSummary.PercentLoad", NULL, "%.0f", 0, NULL }, + { "input.voltage", 0, 0, "UPS.PowerConverter.Input.[1].Voltage", NULL, "%.1f", 0, NULL }, + { "output.voltage", 0, 0, "UPS.PowerConverter.Output.Voltage", NULL, "%.1f", 0, NULL }, + /* USB HID PresentStatus Flags TODO: Parse these into battery.charger.status */ From 9ddac6a9be25218b6670e78226ae3f53adbef597 Mon Sep 17 00:00:00 2001 From: air5551 Date: Mon, 26 Jan 2026 20:49:56 -0500 Subject: [PATCH 024/198] Added Liebert PSI5-800RT120 Signed-off-by: air5551 --- data/driver.list.in | 1 + 1 file changed, 1 insertion(+) diff --git a/data/driver.list.in b/data/driver.list.in index 95a09b2324..34e0a94615 100644 --- a/data/driver.list.in +++ b/data/driver.list.in @@ -741,6 +741,7 @@ "Liebert" "ups" "3" "PowerSure PSA 500" "USB" "usbhid-ups" "Liebert" "ups" "3" "PowerSure PSA500MT3-230U" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/601 "Liebert" "ups" "3" "PowerSure PSI 1440" "USB" "usbhid-ups" # http://www.emersonnetworkpower.com/en-US/Products/ACPower/Pages/LiebertPowerSurePSILineInteractiveUPS10003000VA.aspx +"Liebert" "ups" "3" "PSI5-800RT120" "USB" "usbhid-ups" #https://www.vertiv.com/en-us/products-catalog/critical-power/uninterruptible-power-supplies-ups/psi5-800rt120/ "LNXI" "pdu" "1" "Icebox" "10 outlets" "powerman-pdu (experimental)" From e2b4d2bbeb0842d960e888fa539a8ebb9878fce6 Mon Sep 17 00:00:00 2001 From: air5551 Date: Mon, 26 Jan 2026 21:34:05 -0500 Subject: [PATCH 025/198] Trying to make CI happy :3 Signed-off-by: air5551 --- data/driver.list.in | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/data/driver.list.in b/data/driver.list.in index 34e0a94615..bbda2927eb 100644 --- a/data/driver.list.in +++ b/data/driver.list.in @@ -741,8 +741,7 @@ "Liebert" "ups" "3" "PowerSure PSA 500" "USB" "usbhid-ups" "Liebert" "ups" "3" "PowerSure PSA500MT3-230U" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/601 "Liebert" "ups" "3" "PowerSure PSI 1440" "USB" "usbhid-ups" # http://www.emersonnetworkpower.com/en-US/Products/ACPower/Pages/LiebertPowerSurePSILineInteractiveUPS10003000VA.aspx -"Liebert" "ups" "3" "PSI5-800RT120" "USB" "usbhid-ups" #https://www.vertiv.com/en-us/products-catalog/critical-power/uninterruptible-power-supplies-ups/psi5-800rt120/ - +"Liebert" "ups" "3" "PSI5-800RT120" "USB" "usbhid-ups" #https://www.vertiv.com/en-us/products-catalog/critical-power/uninterruptible-power-supplies-ups/psi5-800rt120/ "LNXI" "pdu" "1" "Icebox" "10 outlets" "powerman-pdu (experimental)" "Lyonn" "ups" "2" "CTB-800V" "" "nutdrv_qx" From e3a33d5d07d83a96c8a82c169bc2d0edea071880 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 27 Jan 2026 11:23:44 +0100 Subject: [PATCH 026/198] data/driver.list.in: clean up the markup a bit [#3285] Signed-off-by: Jim Klimov --- data/driver.list.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data/driver.list.in b/data/driver.list.in index bbda2927eb..d44c1ddf84 100644 --- a/data/driver.list.in +++ b/data/driver.list.in @@ -741,7 +741,8 @@ "Liebert" "ups" "3" "PowerSure PSA 500" "USB" "usbhid-ups" "Liebert" "ups" "3" "PowerSure PSA500MT3-230U" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/601 "Liebert" "ups" "3" "PowerSure PSI 1440" "USB" "usbhid-ups" # http://www.emersonnetworkpower.com/en-US/Products/ACPower/Pages/LiebertPowerSurePSILineInteractiveUPS10003000VA.aspx -"Liebert" "ups" "3" "PSI5-800RT120" "USB" "usbhid-ups" #https://www.vertiv.com/en-us/products-catalog/critical-power/uninterruptible-power-supplies-ups/psi5-800rt120/ +"Liebert" "ups" "3" "PSI5-800RT120" "USB" "usbhid-ups" # https://www.vertiv.com/en-us/products-catalog/critical-power/uninterruptible-power-supplies-ups/psi5-800rt120/ + "LNXI" "pdu" "1" "Icebox" "10 outlets" "powerman-pdu (experimental)" "Lyonn" "ups" "2" "CTB-800V" "" "nutdrv_qx" From 976a639a9bd97c2c6c5681522bbe7de932f35d7a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 26 Jan 2026 10:57:35 +0100 Subject: [PATCH 027/198] drivers/nutdrv_qx.c: improve debug tracing for main loop skeleton [#3282] Signed-off-by: Jim Klimov --- drivers/nutdrv_qx.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index 2dba7df7eb..817d1cd4c7 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -3445,6 +3445,8 @@ void upsdrv_updateinfo(void) retry = 0; dstate_dataok(); + + upsdebugx(1, "%s finished", __func__); } /* Initialise data from UPS */ @@ -3516,8 +3518,14 @@ void upsdrv_initinfo(void) upsh.instcmd = instcmd; /* Subdriver initinfo */ - if (subdriver->initinfo != NULL) + if (subdriver->initinfo != NULL) { + upsdebugx(2, "%s calling subdriver-specific initinfo()...", __func__); subdriver->initinfo(); + } else { + upsdebugx(2, "%s there is no subdriver-specific initinfo() to call", __func__); + } + + upsdebugx(1, "%s finished", __func__); } /* Open the port and the like and choose the subdriver */ @@ -3797,8 +3805,14 @@ void upsdrv_initups(void) fatalx(EXIT_FAILURE, "Device not supported!"); /* Subdriver initups */ - if (subdriver->initups != NULL) + if (subdriver->initups != NULL) { + upsdebugx(2, "%s calling subdriver-specific initups()...", __func__); subdriver->initups(); + } else { + upsdebugx(2, "%s there is no subdriver-specific initups() to call", __func__); + } + + upsdebugx(1, "%s finished", __func__); } /* Close the ports and the like */ @@ -3844,6 +3858,7 @@ void upsdrv_cleanup(void) #endif /* TESTING */ + upsdebugx(1, "%s finished", __func__); } From 6c212087986b2710ae798410de4da5112654f358 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 27 Jan 2026 12:02:44 +0100 Subject: [PATCH 028/198] drivers/nutdrv_qx.c: subdriver_matcher(): more debug-tracing [#3282] Signed-off-by: Jim Klimov --- drivers/nutdrv_qx.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index 817d1cd4c7..6b831bc415 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -4111,6 +4111,8 @@ static int subdriver_matcher(void) const char *protocol = getval("protocol"); int i; + upsdebugx(2, "%s...", __func__); + /* Select the subdriver for this device */ for (i = 0; subdriver_list[i] != NULL; i++) { @@ -4139,10 +4141,13 @@ static int subdriver_matcher(void) subdriver = subdriver_list[i]; + upsdebugx(2, "%s: Trying protocol %s...", __func__, subdriver->name); if (subdriver->claim()) { + upsdebugx(1, "%s: Trying protocol %s: claim succeeded", __func__, subdriver->name); break; } + upsdebugx(2, "%s: Trying protocol %s: claim failed", __func__, subdriver->name); subdriver = NULL; } @@ -4154,11 +4159,14 @@ static int subdriver_matcher(void) if (!subdriver) { upslogx(LOG_ERR, "Device not supported!"); + upsdebugx(2, "%s finished", __func__); return 0; } upslogx(LOG_INFO, "Using protocol: %s", subdriver->name); + upsdebugx(2, "%s finished", __func__); + return 1; } From 127f949db64a5cf92ff9b81dcbe1e6b980872409 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 27 Jan 2026 12:11:06 +0100 Subject: [PATCH 029/198] drivers/nutdrv_qx.c: upsdrv_initups(): log that we got as far as matching the device claimer (and which media type while at it) [#3282] Signed-off-by: Jim Klimov --- drivers/nutdrv_qx.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index 6b831bc415..b17fcf5c75 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -3801,6 +3801,20 @@ void upsdrv_initups(void) #endif /* QX_USB */ /* Choose subdriver */ +#if defined(QX_SERIAL) && defined(QX_USB) + upsdebugx(1, "%s: trying to match the handler for %s device", __func__, is_usb ? "USB" : "Serial"); +#else +# ifdef QX_SERIAL + upsdebugx(1, "%s: trying to match the handler for Serial device", __func__); +# endif +# ifdef QX_USB + upsdebugx(1, "%s: trying to match the handler for USB device", __func__); +# endif +# if !(defined(QX_SERIAL)) && !(defined(QX_USB)) + /* Should not get here... so it is even more interesting to see this */ + upsdebugx(1, "%s: trying to match the handler for a device (weird build of the driver does not discern Serial/USB)", __func__); +# endif +#endif if (!subdriver_matcher()) fatalx(EXIT_FAILURE, "Device not supported!"); From fdeeb4e79fbf1d43d42270361af7074a017e5743 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 26 Jan 2026 10:58:15 +0100 Subject: [PATCH 030/198] drivers/nutdrv_qx.c: try a longer sleep after serial dtr/rts setting [#3282] Some devices are slow to respond to a first query and fail detection. Maybe delaying by a bit over 1 second would help? Signed-off-by: Jim Klimov --- drivers/nutdrv_qx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index b17fcf5c75..b33c782f62 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -58,7 +58,7 @@ # define DRIVER_NAME "Generic Q* Serial driver" #endif /* QX_USB */ -#define DRIVER_VERSION "0.48" +#define DRIVER_VERSION "0.49" #ifdef QX_SERIAL # include "serial.h" @@ -3643,7 +3643,7 @@ void upsdrv_initups(void) ser_set_rts(upsfd, cablepower[i].rts); /* Allow some time to settle for the cablepower */ - usleep(100000); + usleep(1100000); # endif /* TESTING */ From 5c7dbd2ecc62e5f678a9359efe03d02f66fb461d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 27 Jan 2026 13:22:51 +0100 Subject: [PATCH 031/198] drivers/nutdrv_qx_voltronic.c: voltronic_claim(): retry if the first query was OK and second was invalid [#3282] Signed-off-by: Jim Klimov --- drivers/nutdrv_qx_voltronic.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/nutdrv_qx_voltronic.c b/drivers/nutdrv_qx_voltronic.c index 1e6efa9495..7f072a392b 100644 --- a/drivers/nutdrv_qx_voltronic.c +++ b/drivers/nutdrv_qx_voltronic.c @@ -25,7 +25,7 @@ #include "nutdrv_qx.h" #include "nutdrv_qx_voltronic.h" -#define VOLTRONIC_VERSION "Voltronic 0.13" +#define VOLTRONIC_VERSION "Voltronic 0.14" /* Support functions */ static int voltronic_claim(void); @@ -1690,7 +1690,7 @@ static int voltronic_claim(void) item_t *item = find_nut_info("input.voltage", 0, 0); - /* Don't know what happened */ + /* Don't know what happened - should have looked up in the mapping table here! */ if (!item) return 0; @@ -1713,8 +1713,19 @@ static int voltronic_claim(void) /* No reply/Unable to get value */ if (qx_process(item, NULL)) { - dstate_delinfo("input.voltage"); - return 0; + int query_failed = -1; + + if (errno == EINVAL) { + upsdebugx(2, "%s: Sometimes the device is laggy, and we could have posted many queries and the buffer is full of replies to them; try to flush it and ask again", __func__); + usleep(5000000); /* arbitrary 5s delay for the device to maybe produce answers to earlier voltage requests */ + upsdebugx(2, "%s: Buffers flushed, retry the query", __func__); + query_failed = qx_process(item, NULL); + } + + if (query_failed) { + dstate_delinfo("input.voltage"); + return 0; + } } /* Unable to process value/Protocol out of range */ From 869d658ac65fb2faa954df2f7e598be055db48a9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 27 Jan 2026 13:09:51 +0000 Subject: [PATCH 032/198] drivers/Makefile.am: cosmetic fixes [#3279] Signed-off-by: Jim Klimov --- drivers/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/Makefile.am b/drivers/Makefile.am index babcc9f1a9..db6b148702 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -368,9 +368,9 @@ mge_shut_LDADD = $(LDADD_DRIVERS_SERIAL) -lm # UPower if HAVE_GLIB - # Only build upower if GLib was found +# Only build nut-upower if the set of libGLib/libGIO was found driverexec_PROGRAMS += $(UPOWER_DRIVERLIST) - + nut_upower_SOURCES = nut-upower.c nut_upower_LDADD = $(LDADD_DRIVERS) $(GLIB_LIBS) nut_upower_CFLAGS = $(AM_CFLAGS) $(GLIB_CFLAGS) From ea4bff5fb7bcb163bb22f388d43b4ce8f7f9905a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 27 Jan 2026 13:11:47 +0000 Subject: [PATCH 033/198] configure.ac: move nut-upower up to be near macosx equivalent, and hotfix GLIB_CFLAGS with -isystem options to reduce CLANG (mostly) compiler warnings [#3279] Signed-off-by: Jim Klimov --- configure.ac | 94 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 66 insertions(+), 28 deletions(-) diff --git a/configure.ac b/configure.ac index da830e1522..4cbc4f2425 100644 --- a/configure.ac +++ b/configure.ac @@ -3146,6 +3146,72 @@ NUT_REPORT_DRIVER([build Mac OS X meta-driver], [${nut_with_macosx_ups}], [${nut_macosx_ups_lib}], [WITH_MACOSX], [Define to enable Mac OS X meta-driver]) +dnl ---------------------------------------------------------------------- +dnl Check for libGLib / libGIO (Required for UPower driver) +dnl NOTE: Do not confuse libglib{2} (GNOME) with glibc (part of compiler) +dnl ---------------------------------------------------------------------- + +have_glib=no + +AS_IF([test "${with_upower}" != "no"], [ + AS_IF([test x"$have_PKG_CONFIG" = xyes], + [ifdef([PKG_CHECK_MODULES], + [PKG_CHECK_MODULES(GLIB, [glib-2.0 gio-2.0], [have_glib=yes], [have_glib=no])], + [have_glib=no]) + ], + [AC_MSG_WARN([pkg-config not found, cannot look properly for glib-2.0/gio-2.0])] + ) +]) + +AS_IF([test "${have_glib}" = "yes"], [ + AC_DEFINE(HAVE_GLIB, 1, [Define to 1 if GLib and GIO are available]) + + dnl GLib headers seem incorrect and offensive to many compilers + dnl (starting names with underscores and capital characters, + dnl varying support for attributes, method pointer mismatches). + dnl There is nothing NUT can do about it, except telling the + dnl compiler that we take these headers from the system as they + dnl are, so strict checks should not apply to them. + dnl On newer releases (2025+) the headers and CLANG seem to work + dnl together out of the box, but during the decade before this is + dnl troublesome. + AS_IF([test "${CLANGCC}" = "yes" || test "${GCC}" = "yes"], [ + myGLIB_CFLAGS="" + for TOKEN in ${GLIB_CFLAGS} ; do + AS_CASE(["${TOKEN}"], + [-I/*], [ + _IDIR="`echo \"${TOKEN}\" | sed 's/^-I//'`" + AS_IF([echo " ${GLIB_CFLAGS}" | ${EGREP} " -isystem *${_IDIR}" >/dev/null], + [myGLIB_CFLAGS="${myGLIB_CFLAGS} ${TOKEN}"], + [myGLIB_CFLAGS="${myGLIB_CFLAGS} -isystem ${_IDIR} ${TOKEN}"] + )], + [myGLIB_CFLAGS="${myGLIB_CFLAGS} ${TOKEN}"] + ) + done + unset TOKEN + unset _IDIR + myGLIB_CFLAGS="`echo \"${myGLIB_CFLAGS}\" | sed 's/^ *//'`" + + AS_IF([test x"${GLIB_CFLAGS}" != x -a x"${GLIB_CFLAGS}" != x"${myGLIB_CFLAGS}"], [ + AC_MSG_NOTICE([Patched libglib/libgio CFLAGS to declare -isystem]) + AS_IF([test x"${nut_enable_configure_debug}" = xyes], [ + AC_MSG_NOTICE([(CONFIGURE-DEVEL-DEBUG) old: ${GLIB_CFLAGS}]) + AC_MSG_NOTICE([(CONFIGURE-DEVEL-DEBUG) new: ${myGLIB_CFLAGS}]) + ]) + GLIB_CFLAGS="${myGLIB_CFLAGS}" + ]) + unset myGLIB_CFLAGS + ]) +], [ + AS_CASE(["${with_upower}"], + [yes], [AC_MSG_ERROR([GLib/GIO not found but requested via --with-upower])], + [auto],[AC_MSG_WARN([GLib/GIO not found. The 'upower' driver will not be built.])] + ) +]) + +AM_CONDITIONAL(HAVE_GLIB, test "${have_glib}" = "yes") +AC_MSG_RESULT(${have_glib}) + dnl ---------------------------------------------------------------------- dnl checks related to --with_linux_i2c dnl Check for i2c header on Linux, used for ASEM UPS driver @@ -5442,34 +5508,6 @@ AS_IF([test x"$have_PKG_CONFIG" = xyes], ) AC_MSG_RESULT(${have_cppunit}) -dnl ---------------------------------------------------------------------- -dnl Check for GLib / GIO (Required for UPower driver) -dnl ---------------------------------------------------------------------- - -have_glib=no - -if test "${with_upower}" != "no"; then -AS_IF([test x"$have_PKG_CONFIG" = xyes], - [ifdef([PKG_CHECK_MODULES], - [PKG_CHECK_MODULES(GLIB, [glib-2.0 gio-2.0], [have_glib=yes], [have_glib=no])], - [have_glib=no]) - ], - [AC_MSG_WARN([pkg-config not found, cannot look properly for glib-2.0/gio-2.0])] -) -fi - -if test "${have_glib}" = "yes"; then - AC_DEFINE(HAVE_GLIB, 1, [Define to 1 if GLib and GIO are available]) -else - if test "${with_upower}" = "yes"; then - AC_MSG_ERROR([GLib/GIO not found but requested via --with-upower]) - fi - AC_MSG_WARN([GLib/GIO not found. The 'upower' driver will not be built.]) -fi - -AM_CONDITIONAL(HAVE_GLIB, test "${have_glib}" = "yes") -AC_MSG_RESULT(${have_glib}) - dnl On some systems, CppUnit inexplicably fails with trivial assertions dnl so it should not be enabled with those environments, corrupting the dnl test results with misleading errors. From 0a6da0dedb3026f7504f257769ce04d8f44e36e6 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 27 Jan 2026 13:32:50 +0000 Subject: [PATCH 034/198] NEWS.adoc, UPGRADING.adoc: update nut-upower entry with link to the PR [#3279] Signed-off-by: Jim Klimov --- NEWS.adoc | 2 +- UPGRADING.adoc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index 9410816a40..491bfd6208 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -202,7 +202,7 @@ https://github.com/networkupstools/nut/milestone/12 - Introduced a new NUT driver named `nut-upower` which provides support for monitoring UPS and battery devices managed by the UPower daemon via D-Bus. This also introduces a new category of drivers that talk to - operating system services to obtain power state information. + operating system services to obtain power state information. [PR #3279] - `usbhid-ups` driver updates: * Declared support for APC with USB ID `051d:0005` (details may evolve diff --git a/UPGRADING.adoc b/UPGRADING.adoc index e1091218c7..1c11f27ca8 100644 --- a/UPGRADING.adoc +++ b/UPGRADING.adoc @@ -129,7 +129,7 @@ Changes from 2.8.4 to 2.8.5 devices via D-Bus, with the `nut-upower` driver as the first implementation. This driver requires `glib-2.0` and `gio-2.0` development libraries to be available at build time. For packagers, this adds new dependencies if the - build should include this driver. + build should include this driver. [PR #3279] Changes from 2.8.3 to 2.8.4 --------------------------- From c789781282453196f02b509fbd3e5383e579ae2f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 27 Jan 2026 17:47:50 +0100 Subject: [PATCH 035/198] drivers/usb-common.c: add debug tracing [#2270] Signed-off-by: Jim Klimov --- drivers/usb-common.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/usb-common.c b/drivers/usb-common.c index 4834714cc8..7a7051c02e 100644 --- a/drivers/usb-common.c +++ b/drivers/usb-common.c @@ -26,26 +26,39 @@ int is_usb_device_supported(usb_device_id_t *usb_device_id_list, USBDevice_t *de int retval = NOT_SUPPORTED; usb_device_id_t *usbdev; + upsdebugx(3, "%s: checking if this driver can support USB device VID:PID 0x%04X:0x%04X", + __func__, (unsigned int)device->VendorID, (unsigned int)device->ProductID); + for (usbdev = usb_device_id_list; (usbdev->vendorID != 0 || usbdev->productID != 0 || usbdev->fun != NULL); usbdev++ ) { + upsdebugx(4, "%s: checking table entry for VID:PID 0x%04X:0x%04X " + "(custom init handler is%s available)", + __func__, (unsigned int)usbdev->vendorID, + (unsigned int)usbdev->productID, + (usbdev->fun == NULL ? " NOT" : "")); + if (usbdev->vendorID != device->VendorID) { + upsdebugx(4, "%s: NOT_SUPPORTED: vendor ID mismatch", __func__); continue; } /* flag as possibly supported if we see a known vendor */ retval = POSSIBLY_SUPPORTED; + upsdebugx(4, "%s: POSSIBLY_SUPPORTED: known vendor ID at least", __func__); if (usbdev->productID != device->ProductID) { continue; } /* call the specific handler, if it exists */ if (usbdev->fun != NULL) { + upsdebugx(4, "%s: call the custom init handler", __func__); (*usbdev->fun)(device); } + upsdebugx(4, "%s: SUPPORTED: known vendor and product IDs", __func__); return SUPPORTED; } From 6d1b2e1d0496b97a79e36ed0a55964e8594d5160 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 27 Jan 2026 22:22:15 +0100 Subject: [PATCH 036/198] drivers/nutdrv_qx_voltronic.c: voltronic_claim(): log failed query codes and their errnos [#3276] Signed-off-by: Jim Klimov --- drivers/nutdrv_qx_voltronic.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/nutdrv_qx_voltronic.c b/drivers/nutdrv_qx_voltronic.c index 7f072a392b..114c9655cb 100644 --- a/drivers/nutdrv_qx_voltronic.c +++ b/drivers/nutdrv_qx_voltronic.c @@ -1685,6 +1685,7 @@ static testing_t voltronic_testing[] = { /* This function allows the subdriver to "claim" a device: return 1 if the device is supported by this subdriver, else 0. */ static int voltronic_claim(void) { + int query_result; /* We need at least QGS and QPI to run this subdriver */ @@ -1695,12 +1696,16 @@ static int voltronic_claim(void) return 0; /* No reply/Unable to get value */ - if (qx_process(item, NULL)) + if ((query_result = qx_process(item, NULL))) { + upsdebug_with_errno(4, "%s: failed (%d) to get 'input.voltage'", __func__, query_result); return 0; + } /* Unable to process value */ - if (ups_infoval_set(item) != 1) + if ((query_result = ups_infoval_set(item)) != 1) { + upsdebug_with_errno(4, "%s: failed (%d) to set infoval for 'input.voltage'", __func__, query_result); return 0; + } /* UPS Protocol */ item = find_nut_info("ups.firmware.aux", 0, 0); @@ -1712,24 +1717,25 @@ static int voltronic_claim(void) } /* No reply/Unable to get value */ - if (qx_process(item, NULL)) { - int query_failed = -1; + if ((query_result = qx_process(item, NULL))) { + upsdebug_with_errno(4, "%s: failed (%d) to get 'ups.firmware.aux'", __func__, query_result); if (errno == EINVAL) { upsdebugx(2, "%s: Sometimes the device is laggy, and we could have posted many queries and the buffer is full of replies to them; try to flush it and ask again", __func__); usleep(5000000); /* arbitrary 5s delay for the device to maybe produce answers to earlier voltage requests */ upsdebugx(2, "%s: Buffers flushed, retry the query", __func__); - query_failed = qx_process(item, NULL); + query_result = qx_process(item, NULL); } - if (query_failed) { + if (query_result) { dstate_delinfo("input.voltage"); return 0; } } /* Unable to process value/Protocol out of range */ - if (ups_infoval_set(item) != 1) { + if ((query_result = ups_infoval_set(item)) != 1) { + upsdebug_with_errno(4, "%s: failed (%d) to set infoval for 'ups.firmware.aux'", __func__, query_result); dstate_delinfo("input.voltage"); return 0; } From e4470c2d01cb6c0ef0b123bfc744496b698d47fc Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 27 Jan 2026 22:23:08 +0100 Subject: [PATCH 037/198] drivers/nutdrv_qx_voltronic.c: voltronic_claim(): do not limit second query retry to errno==EINVAL for now [#3276] Signed-off-by: Jim Klimov --- drivers/nutdrv_qx_voltronic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/nutdrv_qx_voltronic.c b/drivers/nutdrv_qx_voltronic.c index 114c9655cb..9436d48eab 100644 --- a/drivers/nutdrv_qx_voltronic.c +++ b/drivers/nutdrv_qx_voltronic.c @@ -1720,12 +1720,12 @@ static int voltronic_claim(void) if ((query_result = qx_process(item, NULL))) { upsdebug_with_errno(4, "%s: failed (%d) to get 'ups.firmware.aux'", __func__, query_result); - if (errno == EINVAL) { + /*if (errno == EINVAL) {*/ upsdebugx(2, "%s: Sometimes the device is laggy, and we could have posted many queries and the buffer is full of replies to them; try to flush it and ask again", __func__); usleep(5000000); /* arbitrary 5s delay for the device to maybe produce answers to earlier voltage requests */ upsdebugx(2, "%s: Buffers flushed, retry the query", __func__); query_result = qx_process(item, NULL); - } + /*}*/ if (query_result) { dstate_delinfo("input.voltage"); From 1cac6e2fbcb138df35598abc29a99efdce3f3faa Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 28 Jan 2026 10:11:47 +0100 Subject: [PATCH 038/198] tests/Makefile.am: revise dependency for libdummy_mockdrv.la to honour ENABLE_SHARED_PRIVATE_LIBS setting [#2800] Signed-off-by: Jim Klimov --- clients/Makefile.am | 2 ++ common/Makefile.am | 1 + tests/Makefile.am | 12 ++++++++++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/clients/Makefile.am b/clients/Makefile.am index f9e4450fb8..e68fb784ba 100644 --- a/clients/Makefile.am +++ b/clients/Makefile.am @@ -238,6 +238,7 @@ libnutclient_la_SOURCES = nutclient.h nutclient.cpp libnutclient_la_LDFLAGS = -version-info 2:2:0 # Needed in not-standalone builds with -DHAVE_NUTCOMMON=1 # which is defined for in-tree CXX builds above: +# NOTE: C++ code currently links private common libs only statically [ENABLE_SHARED_PRIVATE_LIBS support TBD per #2584] libnutclient_la_LIBADD = \ $(top_builddir)/common/libcommonclient.la if HAVE_WINDOWS @@ -252,6 +253,7 @@ if HAVE_CXX11 # libnutclientstub version information and build libnutclientstub_la_SOURCES = nutclientmem.h nutclientmem.cpp libnutclientstub_la_LDFLAGS = -version-info 1:1:0 +# NOTE: C++ code currently links private common libs only statically [ENABLE_SHARED_PRIVATE_LIBS support TBD per #2584] libnutclientstub_la_LIBADD = libnutclient.la if HAVE_WINDOWS # Many versions of MingW seem to fail to build non-static DLL without this diff --git a/common/Makefile.am b/common/Makefile.am index 92551a2fa9..5d1bfcc9d9 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -220,6 +220,7 @@ endif HAVE_WINDOWS endif WITH_DEV_LIBNUTCONF libnutconf_la_CXXFLAGS = $(AM_CXXFLAGS) # NOTE: No @LTLIBOBJS@ here, because libcommonclient.la includes them (if any) + # NOTE: C++ code currently links private common libs only statically [ENABLE_SHARED_PRIVATE_LIBS support TBD per #2584] libnutconf_la_LIBADD = @NETLIBS@ libcommonclient.la libnutconf_la_SOURCES = nutconf.cpp nutstream.cpp nutwriter.cpp nutipc.cpp \ ../include/nutconf.hpp ../include/nutipc.hpp \ diff --git a/tests/Makefile.am b/tests/Makefile.am index 3042e6ea99..5158349631 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -52,13 +52,14 @@ $(top_builddir)/clients/libnutclientstub.la: dummy # started from scratch right in this dir get dependencies in proper order # (sub-makes are independent as far as trying to write into same files): $(top_builddir)/common/libcommon.la $(top_builddir)/common/libcommonclient.la: $(top_builddir)/common/libparseconf.la +$(top_builddir)/common/libcommonversion.la: $(top_builddir)/include/nut_version.h +# NOTE: C++ code currently links private common libs only statically [ENABLE_SHARED_PRIVATE_LIBS support TBD per #2584] $(top_builddir)/common/libnutconf.la: $(top_builddir)/common/libcommonclient.la -$(top_builddir)/drivers/libdummy_mockdrv.la: $(top_builddir)/common/libcommon.la $(top_builddir)/common/libcommonversion.la $(top_builddir)/common/libparseconf.la $(top_builddir)/clients/libnutclient.la: $(top_builddir)/common/libcommonclient.la $(top_builddir)/clients/libnutclientstub.la: $(top_builddir)/clients/libnutclient.la -$(top_builddir)/common/libcommonversion.la: $(top_builddir)/include/nut_version.h if ENABLE_SHARED_PRIVATE_LIBS + $(top_builddir)/common/libcommonversion-private.la \ $(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-all.la \ $(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-client.la: dummy @@ -68,9 +69,16 @@ $(top_builddir)/common/libcommonversion-private.la: $(top_builddir)/include/nut_ $(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-all.la: $(top_builddir)/common/libcommon.la $(top_builddir)/common/libcommonversion-private.la $(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-client.la: $(top_builddir)/common/libcommonclient.la $(top_builddir)/common/libcommonversion-private.la +$(top_builddir)/drivers/libdummy_mockdrv.la: $(top_builddir)/common/libcommonversion.la $(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-all.la + NUT_LIBCOMMON = $(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-all.la + else !ENABLE_SHARED_PRIVATE_LIBS + +$(top_builddir)/drivers/libdummy_mockdrv.la: $(top_builddir)/common/libcommon.la $(top_builddir)/common/libcommonversion.la $(top_builddir)/common/libparseconf.la + NUT_LIBCOMMON = $(top_builddir)/common/libcommon.la + endif !ENABLE_SHARED_PRIVATE_LIBS nutlogtest_SOURCES = nutlogtest.c From d5bf20c5eb915fb7fbbce98ef66cddf14878eaa0 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 28 Jan 2026 10:20:48 +0100 Subject: [PATCH 039/198] common/Makefile.am, tests/Makefile.am: revise libnutconf dependency to honour ENABLE_SHARED_PRIVATE_LIBS and match tools/nutconf/Makefile.am [#2800] Signed-off-by: Jim Klimov --- common/Makefile.am | 8 ++++++-- tests/Makefile.am | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/common/Makefile.am b/common/Makefile.am index 5d1bfcc9d9..153e852972 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -220,8 +220,12 @@ endif HAVE_WINDOWS endif WITH_DEV_LIBNUTCONF libnutconf_la_CXXFLAGS = $(AM_CXXFLAGS) # NOTE: No @LTLIBOBJS@ here, because libcommonclient.la includes them (if any) - # NOTE: C++ code currently links private common libs only statically [ENABLE_SHARED_PRIVATE_LIBS support TBD per #2584] - libnutconf_la_LIBADD = @NETLIBS@ libcommonclient.la + libnutconf_la_LIBADD = @NETLIBS@ +if ENABLE_SHARED_PRIVATE_LIBS + libnutconf_la_LIBADD += libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-client.la +else !ENABLE_SHARED_PRIVATE_LIBS + libnutconf_la_LIBADD += libcommonclient.la +endif !ENABLE_SHARED_PRIVATE_LIBS libnutconf_la_SOURCES = nutconf.cpp nutstream.cpp nutwriter.cpp nutipc.cpp \ ../include/nutconf.hpp ../include/nutipc.hpp \ ../include/nutstream.hpp ../include/nutwriter.hpp diff --git a/tests/Makefile.am b/tests/Makefile.am index 5158349631..7bc18670c5 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -54,7 +54,6 @@ $(top_builddir)/clients/libnutclientstub.la: dummy $(top_builddir)/common/libcommon.la $(top_builddir)/common/libcommonclient.la: $(top_builddir)/common/libparseconf.la $(top_builddir)/common/libcommonversion.la: $(top_builddir)/include/nut_version.h # NOTE: C++ code currently links private common libs only statically [ENABLE_SHARED_PRIVATE_LIBS support TBD per #2584] -$(top_builddir)/common/libnutconf.la: $(top_builddir)/common/libcommonclient.la $(top_builddir)/clients/libnutclient.la: $(top_builddir)/common/libcommonclient.la $(top_builddir)/clients/libnutclientstub.la: $(top_builddir)/clients/libnutclient.la @@ -70,12 +69,14 @@ $(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-comm $(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-client.la: $(top_builddir)/common/libcommonclient.la $(top_builddir)/common/libcommonversion-private.la $(top_builddir)/drivers/libdummy_mockdrv.la: $(top_builddir)/common/libcommonversion.la $(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-all.la +$(top_builddir)/common/libnutconf.la: $(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-client.la NUT_LIBCOMMON = $(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-all.la else !ENABLE_SHARED_PRIVATE_LIBS $(top_builddir)/drivers/libdummy_mockdrv.la: $(top_builddir)/common/libcommon.la $(top_builddir)/common/libcommonversion.la $(top_builddir)/common/libparseconf.la +$(top_builddir)/common/libnutconf.la: $(top_builddir)/common/libcommonclient.la NUT_LIBCOMMON = $(top_builddir)/common/libcommon.la From 828f69455f0a2ad27c3effccae0b1bfa8dec9d3a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 28 Jan 2026 11:28:29 +0100 Subject: [PATCH 040/198] drivers/nutdrv_qx.c, nutdrv_qx_voltronic.c, NEWS.adoc, docs/nut.dict: qx_process_answer(): set errno=ETIMEDOUT (not EINVAL) if raised by caller or we had a zero-length read; use this in voltronic_claim() [#3276, #3283] Signed-off-by: Jim Klimov --- NEWS.adoc | 6 ++++++ docs/nut.dict | 4 +++- drivers/nutdrv_qx.c | 21 +++++++++++++++++---- drivers/nutdrv_qx_voltronic.c | 32 ++++++++++++++++++-------------- 4 files changed, 44 insertions(+), 19 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index eb7c571899..fa1bfd0c95 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -143,6 +143,12 @@ https://github.com/networkupstools/nut/milestone/12 well -- namely, that we successfully use reasonably many of the existing mappings. Suggest how user can help improve the driver if too few data points were seen. [PR #3095] + * The `qx_process_answer()` method was extended to raise `errno=ETIMEDOUT` + (rather than `EINVAL`) for short reads that are zero length (and/or that + `errno` value was set in caller's context already). This was used to make + `Voltronic` protocol initial connections more reliable when the device + controller lags upon first contact (is booting itself?) [issue #3276, + PR #3283] * New `nutdrv_qx_innovatae` adds support for Ippon INNOVA TAE series which are similar to Q1 except in reporting of nominal `voltage`, `current`, `frequency` data (that along with `battery_voltage_reports_one_pack` and diff --git a/docs/nut.dict b/docs/nut.dict index 7f37733d83..34091fa4e9 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3634 utf-8 +personal_ws-1.1 en 3636 utf-8 AAC AAS ABI @@ -330,6 +330,7 @@ EE EEPROM EFI EG +EINVAL EL ELCD EMI @@ -352,6 +353,7 @@ ESS ESV ESXi ETIME +ETIMEDOUT EUROCASE EVeRr EXtreme diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index b33c782f62..ea2a695a82 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -4432,6 +4432,7 @@ static bool_t qx_ups_walk(walkmode_t mode) previous_item.answer); /* Process the answer */ + errno = 0; retcode = qx_process_answer(item, strlen(item->answer)); /* ..otherwise: execute command to get answer from the UPS */ @@ -4663,11 +4664,15 @@ item_t *find_nut_info(const char *varname, const unsigned long flag, const unsig /* Process the answer we got back from the UPS * Return -1 on errors, 0 on success * Can set errno, note that EINVAL means unsupported - * parameter value here! + * parameter value here, and ETIMEDOUT can be passed + * from previous context for short reads, or set + * unilaterally for zero-length reads! */ static int qx_process_answer(item_t *item, const size_t len) { - errno = 0; + /* Initial errno inherited from caller, e.g. may be qx_command() + * in qx_process(), but may be from other memset() etc. after it + */ /* Query rejected by the UPS */ if (subdriver->rejected && !strcasecmp(item->answer, subdriver->rejected)) { @@ -4679,12 +4684,19 @@ static int qx_process_answer(item_t *item, const size_t len) /* Short reply */ if (item->answer_len && len < item->answer_len) { - upsdebugx(2, "%s: short reply (%s) %" PRIuSIZE "<%" PRIuSIZE, + upsdebug_with_errno(2, "%s: short reply (%s) %" PRIuSIZE "<%" PRIuSIZE, __func__, item->info_type, len, item->answer_len); - errno = EINVAL; + if (len == 0 || errno == ETIMEDOUT) { + errno = ETIMEDOUT; + } else { + errno = EINVAL; + } return -1; } + /* Not a systemic error by default */ + errno = 0; + /* Wrong leading character */ if (item->leading && item->answer[0] != item->leading) { upsdebugx(2, @@ -4711,6 +4723,7 @@ static int qx_process_answer(item_t *item, const size_t len) snprintf(item->value, sizeof(item->value), "%s", ""); } + /* Reset the common error level, if some method above raised it */ errno = 0; return 0; } diff --git a/drivers/nutdrv_qx_voltronic.c b/drivers/nutdrv_qx_voltronic.c index 9436d48eab..408864a396 100644 --- a/drivers/nutdrv_qx_voltronic.c +++ b/drivers/nutdrv_qx_voltronic.c @@ -1692,13 +1692,26 @@ static int voltronic_claim(void) item_t *item = find_nut_info("input.voltage", 0, 0); /* Don't know what happened - should have looked up in the mapping table here! */ - if (!item) + if (!item) { + upsdebug_with_errno(4, "%s: did not find 'input.voltage' in mapping table", __func__); return 0; + } /* No reply/Unable to get value */ if ((query_result = qx_process(item, NULL))) { upsdebug_with_errno(4, "%s: failed (%d) to get 'input.voltage'", __func__, query_result); - return 0; + + if (errno == ETIMEDOUT) { + upsdebugx(2, "%s: Sometimes the device is laggy, and we could have posted many queries and the buffer is full of replies to them (or it is still producing the answers); try to sleep, flush it and ask again", __func__); + usleep(5000000); /* arbitrary 5s delay for the device to maybe produce answers to earlier voltage requests */ + upsdebugx(2, "%s: Retry the query now, buffers will be flushed then", __func__); + query_result = qx_process(item, NULL); + } + + if (query_result) { + /* Not a known timeout/zero-read initially, or still a bad response */ + return 0; + } } /* Unable to process value */ @@ -1712,6 +1725,7 @@ static int voltronic_claim(void) /* Don't know what happened */ if (!item) { + upsdebug_with_errno(4, "%s: did not find 'ups.firmware.aux' in mapping table", __func__); dstate_delinfo("input.voltage"); return 0; } @@ -1719,18 +1733,8 @@ static int voltronic_claim(void) /* No reply/Unable to get value */ if ((query_result = qx_process(item, NULL))) { upsdebug_with_errno(4, "%s: failed (%d) to get 'ups.firmware.aux'", __func__, query_result); - - /*if (errno == EINVAL) {*/ - upsdebugx(2, "%s: Sometimes the device is laggy, and we could have posted many queries and the buffer is full of replies to them; try to flush it and ask again", __func__); - usleep(5000000); /* arbitrary 5s delay for the device to maybe produce answers to earlier voltage requests */ - upsdebugx(2, "%s: Buffers flushed, retry the query", __func__); - query_result = qx_process(item, NULL); - /*}*/ - - if (query_result) { - dstate_delinfo("input.voltage"); - return 0; - } + dstate_delinfo("input.voltage"); + return 0; } /* Unable to process value/Protocol out of range */ From 0248dc0cc3af2451b803e27a7e36118de8ddb151 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 28 Jan 2026 14:17:40 +0100 Subject: [PATCH 041/198] docs/developers.txt: update recommendation about hiding IDE dirs from a careless `git clean -fdX` Signed-off-by: Jim Klimov --- docs/developers.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/developers.txt b/docs/developers.txt index ed43d00a4a..d617ae18d7 100644 --- a/docs/developers.txt +++ b/docs/developers.txt @@ -337,7 +337,8 @@ locations can be wiped by a careless `git clean -fdX`. You are advised to explore configuring your IDE to store project configurations outside the source codebase location, or to track such subdirectories as `nbproject` or `nb-cache` or `.idea` as a separate Git repository (not necessarily a -submodule of NUT nor really diligently tracked) to avoid such surprises. +submodule of NUT nor really diligently tracked) to avoid such surprises, +e.g. `(cd nbproject && git init .)` can help. IDE notes on Windows ~~~~~~~~~~~~~~~~~~~~ From 12a0d2bf175a533d408e2878565ede6879a14f69 Mon Sep 17 00:00:00 2001 From: Vladdrako Date: Wed, 28 Jan 2026 14:59:46 +0200 Subject: [PATCH 042/198] drivers: powercom-hid: use offdelay/ondelay config options for shutdown commands The powercom_shutdown_nuf(), powercom_stayoff_nuf(), and powercom_startup_nuf() functions were reading delay values from dstate_getinfo("ups.delay.shutdown") and dstate_getinfo("ups.delay.start"), which return the UPS's CURRENT delay values read via HID. However, users configure their desired delays via the "offdelay" and "ondelay" driver options in ups.conf. These were being ignored. This patch changes the functions to: 1. First try the value passed directly to the instant command 2. Then try getval("offdelay")/getval("ondelay") from driver config 3. Then try dstate_getinfo() for current UPS values 4. Finally fall back to sensible defaults (60s shutdown, 120s startup) This ensures that user configuration is respected. Tested on Powercom RPT-800AP (VendorID: 0x0d9f, ProductID: 0x0004). Signed-off-by: Vladyslav Andreichykov --- drivers/powercom-hid.c | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/drivers/powercom-hid.c b/drivers/powercom-hid.c index 6047bb8fcb..6f5d15e3b6 100644 --- a/drivers/powercom-hid.c +++ b/drivers/powercom-hid.c @@ -97,11 +97,21 @@ static const char *powercom_startup_fun(double value) static double powercom_startup_nuf(const char *value) { const char *s = dstate_getinfo("ups.delay.start"); + const char *cfg = getval("ondelay"); uint32_t val, command; int iv; - /* Start with seconds "as is" - convert into whole minutes */ - iv = atoi(value ? value : s) / 60; /* minutes */ + /* Priority: 1) command value, 2) config ondelay, 3) UPS current, 4) default */ + if (value && *value) { + iv = atoi(value) / 60; + } else if (cfg && *cfg) { + iv = atoi(cfg) / 60; + } else if (s && *s) { + iv = atoi(s) / 60; + } else { + iv = 2; /* Default: 2 minutes (120 seconds) */ + } + #if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) ) # pragma GCC diagnostic push #endif @@ -165,10 +175,21 @@ static const char *powercom_shutdown_fun(double value) static double powercom_shutdown_nuf(const char *value) { const char *s = dstate_getinfo("ups.delay.shutdown"); + const char *cfg = getval("offdelay"); uint16_t val, command; int iv; - iv = atoi(value ? value : s); /* seconds */ + /* Priority: 1) command value, 2) config offdelay, 3) UPS current, 4) default */ + if (value && *value) { + iv = atoi(value); + } else if (cfg && *cfg) { + iv = atoi(cfg); + } else if (s && *s) { + iv = atoi(s); + } else { + iv = 60; /* Default: 60 seconds */ + } + if (iv < 0 || (intmax_t)iv > (intmax_t)UINT16_MAX) { upsdebugx(0, "%s: value = %d is not in uint16_t range", __func__, iv); return 0; @@ -219,11 +240,21 @@ static info_lkp_t powercom_shutdown_info[] = { static double powercom_stayoff_nuf(const char *value) { const char *s = dstate_getinfo("ups.delay.shutdown"); + const char *cfg = getval("offdelay"); uint16_t val, command; int iv; - /* FIXME: Anything for powercom_sdcmd_discrete_delay? */ - iv = atoi(value ? value : s); + /* Priority: 1) command value, 2) config offdelay, 3) UPS current, 4) default */ + if (value && *value) { + iv = atoi(value); + } else if (cfg && *cfg) { + iv = atoi(cfg); + } else if (s && *s) { + iv = atoi(s); + } else { + iv = 60; /* Default: 60 seconds */ + } + if (iv < 0 || (intmax_t)iv > (intmax_t)UINT16_MAX) { upsdebugx(0, "%s: value = %d is not in uint16_t range", __func__, iv); return 0; From cced83a58d8d980cbeaad019522ab0f0c25d77e7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 28 Jan 2026 14:40:11 +0100 Subject: [PATCH 043/198] .obs/workflows.yml: separate project builds with what looks like RC tags to use a separate OBS template (tweaked to change the dash into tilde for packaging versions) [#1209] Signed-off-by: Jim Klimov --- .obs/workflows.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.obs/workflows.yml b/.obs/workflows.yml index 013722d0f3..34b217483f 100644 --- a/.obs/workflows.yml +++ b/.obs/workflows.yml @@ -28,3 +28,22 @@ release_tag: target_project: home:networkupstools:nut-releases filters: event: tag_push + tags: + only: + - "v[0-9]+.[0-9]+.[0-9]+" + ignore: + # v1.2.3-rc1, these need a different regex in _service of template project + - "*-*" + +release_candidate_tag: + steps: + - branch_package: + source_project: home:networkupstools:nut-stable-rc + source_package: "%{SCM_REPOSITORY_NAME}" + target_project: home:networkupstools:nut-releases + filters: + event: tag_push + tags: + only: + # v1.2.3-rc1, these need a different regex in _service of template project + - "v[0-9]+.[0-9]+.[0-9]+-.*" From 5dc37572ba2e44c757a9a97013b787a9a1015b1c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 28 Jan 2026 15:04:51 +0100 Subject: [PATCH 044/198] scripts/obs/_service: stash recent template project changes from OBS setup [#1209] Signed-off-by: Jim Klimov --- scripts/obs/_service | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/scripts/obs/_service b/scripts/obs/_service index 2f1fd332ae..7c5c2b88bb 100644 --- a/scripts/obs/_service +++ b/scripts/obs/_service @@ -10,6 +10,18 @@ v([^-]*)-*(.*) \1\2 + + v?.?.? + .git nut From 744b7b87a439725197fbe1ea9d2990de898642b7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 28 Jan 2026 10:26:54 +0100 Subject: [PATCH 045/198] clients/Makefile.am, tests/Makefile.am: revise libnutclient* dependencies to honour ENABLE_SHARED_PRIVATE_LIBS [#2800] Signed-off-by: Jim Klimov --- clients/Makefile.am | 10 ++++++++-- tests/Makefile.am | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/clients/Makefile.am b/clients/Makefile.am index e68fb784ba..7d14c5e8ce 100644 --- a/clients/Makefile.am +++ b/clients/Makefile.am @@ -238,9 +238,16 @@ libnutclient_la_SOURCES = nutclient.h nutclient.cpp libnutclient_la_LDFLAGS = -version-info 2:2:0 # Needed in not-standalone builds with -DHAVE_NUTCOMMON=1 # which is defined for in-tree CXX builds above: -# NOTE: C++ code currently links private common libs only statically [ENABLE_SHARED_PRIVATE_LIBS support TBD per #2584] +if ENABLE_SHARED_PRIVATE_LIBS +libnutclient_la_LIBADD = \ + $(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-client.la +if HAVE_WINDOWS + libnutclient_la_LIBADD += $(NETLIBS) +endif HAVE_WINDOWS +else !ENABLE_SHARED_PRIVATE_LIBS libnutclient_la_LIBADD = \ $(top_builddir)/common/libcommonclient.la +endif !ENABLE_SHARED_PRIVATE_LIBS if HAVE_WINDOWS # Many versions of MingW seem to fail to build non-static DLL without this libnutclient_la_LDFLAGS += -no-undefined @@ -253,7 +260,6 @@ if HAVE_CXX11 # libnutclientstub version information and build libnutclientstub_la_SOURCES = nutclientmem.h nutclientmem.cpp libnutclientstub_la_LDFLAGS = -version-info 1:1:0 -# NOTE: C++ code currently links private common libs only statically [ENABLE_SHARED_PRIVATE_LIBS support TBD per #2584] libnutclientstub_la_LIBADD = libnutclient.la if HAVE_WINDOWS # Many versions of MingW seem to fail to build non-static DLL without this diff --git a/tests/Makefile.am b/tests/Makefile.am index 7bc18670c5..11692209df 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -53,8 +53,6 @@ $(top_builddir)/clients/libnutclientstub.la: dummy # (sub-makes are independent as far as trying to write into same files): $(top_builddir)/common/libcommon.la $(top_builddir)/common/libcommonclient.la: $(top_builddir)/common/libparseconf.la $(top_builddir)/common/libcommonversion.la: $(top_builddir)/include/nut_version.h -# NOTE: C++ code currently links private common libs only statically [ENABLE_SHARED_PRIVATE_LIBS support TBD per #2584] -$(top_builddir)/clients/libnutclient.la: $(top_builddir)/common/libcommonclient.la $(top_builddir)/clients/libnutclientstub.la: $(top_builddir)/clients/libnutclient.la if ENABLE_SHARED_PRIVATE_LIBS @@ -70,6 +68,7 @@ $(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-comm $(top_builddir)/drivers/libdummy_mockdrv.la: $(top_builddir)/common/libcommonversion.la $(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-all.la $(top_builddir)/common/libnutconf.la: $(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-client.la +$(top_builddir)/clients/libnutclient.la: $(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-client.la NUT_LIBCOMMON = $(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-all.la @@ -77,6 +76,7 @@ else !ENABLE_SHARED_PRIVATE_LIBS $(top_builddir)/drivers/libdummy_mockdrv.la: $(top_builddir)/common/libcommon.la $(top_builddir)/common/libcommonversion.la $(top_builddir)/common/libparseconf.la $(top_builddir)/common/libnutconf.la: $(top_builddir)/common/libcommonclient.la +$(top_builddir)/clients/libnutclient.la: $(top_builddir)/common/libcommonclient.la NUT_LIBCOMMON = $(top_builddir)/common/libcommon.la From 8309662eec2c73e37271d71b5e60cc8f2c2667d3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 28 Jan 2026 15:35:39 +0100 Subject: [PATCH 046/198] NEWS.adoc: update about powercom-hid fix for shutdown/stayoff/startup INSTCMDs [#3288] Signed-off-by: Jim Klimov --- NEWS.adoc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NEWS.adoc b/NEWS.adoc index eb7c571899..91af10c8a6 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -227,6 +227,11 @@ https://github.com/networkupstools/nut/milestone/12 fixed to use the same mapping helper as other subdrivers. [issue #3246] * `powercom-hid` subdriver improved with a `powercom_hack_voltage_lkp` to query `battery.voltage`. [issue #2766] + * `powercom-hid` subdriver now honours configured `offdelay` and `ondelay` + driver options in `ups.conf`, and prefers them (if present) over the + values received from the UPS itself (like `ups.delay.shutdown` and + `ups.delay.start`), to fix implementations of shutdown/stayoff/startup + instant commands. [PR #3288] * Improved handling of transient `LIBUSB_ERROR_IO` failures during polling. Some devices (CyberPower, etc.) have firmware bugs causing random I/O errors on certain HID reports. The driver now skips failing reports and From 4da001b6c1af78ee6dee70d5f069d499685de830 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 28 Jan 2026 15:39:32 +0100 Subject: [PATCH 047/198] drivers/powercom-hid.c: bump POWERCOM_HID_VERSION and revise comments [#3288] Signed-off-by: Jim Klimov --- drivers/powercom-hid.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/powercom-hid.c b/drivers/powercom-hid.c index 6f5d15e3b6..eecbec2b4b 100644 --- a/drivers/powercom-hid.c +++ b/drivers/powercom-hid.c @@ -28,7 +28,7 @@ #include /* isdigit() */ -#define POWERCOM_HID_VERSION "PowerCOM HID 0.73" +#define POWERCOM_HID_VERSION "PowerCOM HID 0.74" /* FIXME: experimental flag to be put in upsdrv_info */ /* PowerCOM */ @@ -101,7 +101,9 @@ static double powercom_startup_nuf(const char *value) uint32_t val, command; int iv; - /* Priority: 1) command value, 2) config ondelay, 3) UPS current, 4) default */ + /* Priority: 1) command value, 2) config ondelay, 3) UPS current, 4) default + * Note we start with seconds "as is" - convert into whole minutes for the device protocol + */ if (value && *value) { iv = atoi(value) / 60; } else if (cfg && *cfg) { @@ -179,7 +181,9 @@ static double powercom_shutdown_nuf(const char *value) uint16_t val, command; int iv; - /* Priority: 1) command value, 2) config offdelay, 3) UPS current, 4) default */ + /* Priority: 1) command value, 2) config offdelay, 3) UPS current, 4) default + * Note we start with seconds "as is" - convert into magic numbers for the device protocol below + */ if (value && *value) { iv = atoi(value); } else if (cfg && *cfg) { @@ -244,7 +248,10 @@ static double powercom_stayoff_nuf(const char *value) uint16_t val, command; int iv; - /* Priority: 1) command value, 2) config offdelay, 3) UPS current, 4) default */ + /* FIXME: Anything for powercom_sdcmd_discrete_delay? */ + /* Priority: 1) command value, 2) config offdelay, 3) UPS current, 4) default + * Note we start with seconds "as is" - convert into magic numbers for the device protocol below + */ if (value && *value) { iv = atoi(value); } else if (cfg && *cfg) { From 9e0352c7695e7f727e6eba184716a4c64a37c65c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 28 Jan 2026 16:18:16 +0100 Subject: [PATCH 048/198] tools/semver-compare.sh, docs/nut-versioning.adoc: revise help for "Shellish syntax to compare two semvers" [#3055] Signed-off-by: Jim Klimov --- docs/nut-versioning.adoc | 7 +++++-- tools/semver-compare.sh | 7 ++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/nut-versioning.adoc b/docs/nut-versioning.adoc index 28c85fc544..e632ecd6f6 100644 --- a/docs/nut-versioning.adoc +++ b/docs/nut-versioning.adoc @@ -463,8 +463,11 @@ Return sorted (via expansion) list of original semver strings (till end of args), in their original spelling (with leading zeroes, if present, not stripped away). -`semver-compare.sh [OPTS] {test|[} "SEMVER1" {-gt|-ge|-lt|-le|-eq|=|==|-ne|!=|<>|<|<=|>|>=} "SEMVER2"`:: -Shell-style syntax to compare two semver strings (via expanded variants). +`semver-compare.sh [OPTS] {test|[|[[} "SEMVER1" {-gt|>|-ge|>=|-lt|<|-le|<=|-eq|=|==|-ne|!=|<>} "SEMVER2" {]|]]}`:: +Relaxed shell-style syntax to compare two semver strings (via their expanded +variants). Introduced so this script can be just prefixed into existing +(alphanumeric-based) shell comparisons, or newly added with a human-readable +command-line interface. + Note that `--min-components` can play a role here (e.g. is `1.2.3` equal to `1.2.3.0.0`? You can specify whether and how many zeroes can be added diff --git a/tools/semver-compare.sh b/tools/semver-compare.sh index 688aa22575..bbbe81eb39 100755 --- a/tools/semver-compare.sh +++ b/tools/semver-compare.sh @@ -1,6 +1,6 @@ #!/bin/sh -# Copyright (C) 2025 by Jim Klimov +# Copyright (C) 2025-2026 by 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 @@ -190,8 +190,9 @@ Actions: Return sorted (via expansion) list of original semvers (till end of args) in their original spelling (with unstripped leading zeroes, if present) - $0 [OPTS] {test|[} "SEMVER1" {-gt|-ge|-lt|-le|-eq|=|==|-ne|!=|<>|<|<=|>|>=} "SEMVER2" - Shellish syntax to compare two semvers + $0 [OPTS] {test|[|[[} "SEMVER1" {-gt|>|-ge|>=|-lt|<|-le|<=|-eq|=|==|-ne|!=|<>} "SEMVER2" {]|]]} + Relaxed shellish syntax to compare two semvers, so this script can be + just prefixed into existing (alphanumeric-based) shell comparisons EOF exit 0 ;; From c999ad592607ffb4e1dfc33580ffca799f49ba18 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 28 Jan 2026 17:46:41 +0100 Subject: [PATCH 049/198] tests/nut-driver-enumerator-test.sh: quiesce shell-check concerns about "==" comparator [#3055] Co-authored-by: Greg Troxel Signed-off-by: Jim Klimov --- tests/nut-driver-enumerator-test.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/nut-driver-enumerator-test.sh b/tests/nut-driver-enumerator-test.sh index 93007d7144..10f477c22e 100755 --- a/tests/nut-driver-enumerator-test.sh +++ b/tests/nut-driver-enumerator-test.sh @@ -612,9 +612,11 @@ testcase_semver_compare() { "SEMVER comparison helper: shell-style maths: equality with added trailing zeroed components (and different leading zero pads)" 0 "" \ test 01.02.03 = 1.002.0003.0 + # Note: escaping the double-equals token to keep shell checkers quiet + # about what they can think of as unportable bashism run_testcase_generic callSEMVERCMP \ "SEMVER comparison helper: shell-style maths: (non-)equality with added trailing zero value e.g. 3 vs 30" 1 "" \ - test 01.02.03 == 1.002.00030 + test 01.02.03 \=\= 1.002.00030 run_testcase_generic callSEMVERCMP \ "SEMVER comparison helper: shell-style maths: non-equality with added trailing zeroed components (and different leading zero pads)" 1 "" \ From 5258b8f7a867ac66b567f379d11928b724af8c3c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 29 Jan 2026 10:26:50 +0100 Subject: [PATCH 050/198] docs/maintainer-guide.txt: update a comment Signed-off-by: Jim Klimov --- docs/maintainer-guide.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/maintainer-guide.txt b/docs/maintainer-guide.txt index e059fbfe95..c1d684b795 100644 --- a/docs/maintainer-guide.txt +++ b/docs/maintainer-guide.txt @@ -178,6 +178,8 @@ symbol names and API versions, similar to what `GNUC` or `SUNW` libraries do. :; git tag v2.8.3-rc7 :; NUT_VERSION_QUERY="UPDATE_FILE_GIT_RELEASE" ./tools/gitlog2version.sh + +# Output sample wrapped for readability: SEMVER=2.8.3; TRUNK='upstream/master'; BASE='735451f1f21556f2a7b8443053e8962c2184239f'; DESC='v2.8.2-2881+gbdade6241' => TAG='v2.8.2' + SUFFIX='-2881+gbdade6241+v2.8.3+rc7' => VER5='2.8.2.2878.3' => DESC5='2.8.2.2878.3-2881+gbdade6241+v2.8.3+rc7' From 466a4997d39060b21838855c2b247f9883b7ef0f Mon Sep 17 00:00:00 2001 From: TomZanna Date: Thu, 29 Jan 2026 17:28:26 +0100 Subject: [PATCH 051/198] drivers/tripplitesu.c: add 1s delay in command_send Intermittent communication timeouts were observed when multiple commands were sent in rapid succession. Adding a 1-second delay at the beginning of command_send() ensures the hardware buffer is ready and prevents the "read timeout" errors. Signed-off-by: TomZanna --- data/driver.list.in | 1 + drivers/tripplitesu.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/data/driver.list.in b/data/driver.list.in index d44c1ddf84..39104e0897 100644 --- a/data/driver.list.in +++ b/data/driver.list.in @@ -1569,6 +1569,7 @@ "Tripp Lite" "ups" "3" "SU3000XLCD" "USB (protocol 4004)" "usbhid-ups" # http://www.tripplite.com/en/products/model.cfm?txtSeriesID=744&txtModelID=5342 "Tripp Lite" "ups" "3" "SUINT1000RTXL2UA" "USB (protocol 4001)" "usbhid-ups" # http://www.tripplite.com/en/products/model.cfm?txtModelID=3983 "Tripp Lite" "ups" "3" "SUINT1500RTXL2UA" "USB (protocol 4001)" "usbhid-ups" # http://www.tripplite.com/en/products/model.cfm?txtSeriesID=934&txtModelID=2720 +"Tripp Lite" "ups" "3" "SUINT1500RTXL2UA" "Serial" "tripplitesu" # http://www.tripplite.com/en/products/model.cfm?txtSeriesID=934&txtModelID=2720 "Tripp Lite" "ups" "3" "SUINT2200RTXL2UA" "USB (protocol 4001)" "usbhid-ups" # http://www.tripplite.com/en/products/model.cfm?txtSeriesID=934&txtModelID=3970 "Tripp Lite" "ups" "3" "SUINT3000RTXL2U" "USB (protocol 4005)" "usbhid-ups" # http://www.tripplite.com/en/products/model.cfm?txtModelID=4523 diff --git a/drivers/tripplitesu.c b/drivers/tripplitesu.c index f00fae5153..dd069dbd42 100644 --- a/drivers/tripplitesu.c +++ b/drivers/tripplitesu.c @@ -126,7 +126,7 @@ #include "nut_stdint.h" #define DRIVER_NAME "Tripp Lite SmartOnline driver" -#define DRIVER_VERSION "0.11" +#define DRIVER_VERSION "0.12" /* driver description structure */ upsdrv_info_t upsdrv_info = { @@ -222,6 +222,7 @@ static ssize_t do_command(char type, const char *command, const char *parameters size_t count; ssize_t ret; + usleep(1E6); ser_flush_io(upsfd); if (response) { From 3ed243f6b966f2deb4727b684bfb5db39a599bf4 Mon Sep 17 00:00:00 2001 From: TomZanna Date: Thu, 29 Jan 2026 18:43:46 +0100 Subject: [PATCH 052/198] drivers/tripplitesu.c: add configurable command delay to prevent read timeouts --- NEWS.adoc | 4 ++++ docs/man/tripplitesu.txt | 9 +++++++++ drivers/tripplitesu.c | 32 +++++++++++++++++++++++++++++++- 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/NEWS.adoc b/NEWS.adoc index a9059723ac..c8894c0fd2 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -204,6 +204,10 @@ https://github.com/networkupstools/nut/milestone/12 PR #3093] * Fixed default `unit_id`, apparently broken by changes in NUT v2.8.1. [issue #3191, PR #3192] + + - `tripplitesu` driver updates: + * Added configurable command delay to prevent read timeouts + [PR #3273] - Introduced a new NUT driver named `nut-upower` which provides support for monitoring UPS and battery devices managed by the UPower daemon diff --git a/docs/man/tripplitesu.txt b/docs/man/tripplitesu.txt index a279a25827..ae2ec8f4d5 100644 --- a/docs/man/tripplitesu.txt +++ b/docs/man/tripplitesu.txt @@ -33,6 +33,15 @@ Set the low battery warning threshold in percent at which shutdown is initiated by linkman:upsmon[8]. By default, the UPS may not report low battery until there are only a few seconds left. Common values are around 25--30. +*command_delay*='milliseconds':: +Set a delay in milliseconds to be applied before each command sent to the UPS. +The default value is 0 (disabled). If experiencing intermittent communication +timeouts when multiple commands are sent in rapid succession, set this to +1000 (1 second) or adjust as needed. + +This delay helps prevent "read timeout" errors when the hardware buffer is +not ready to accept new commands immediately after completing the previous one. + AUTHOR ------ diff --git a/drivers/tripplitesu.c b/drivers/tripplitesu.c index dd069dbd42..56e22f28c6 100644 --- a/drivers/tripplitesu.c +++ b/drivers/tripplitesu.c @@ -66,6 +66,7 @@ The following parameters (ups.conf) are supported: lowbatt + command_delay The following variables are supported (RW = read/write): ambient.humidity (1) @@ -163,6 +164,8 @@ static struct { unsigned long commands_available; } ups; +static long command_delay = 0; /* delay in milliseconds before each command, 0 = no delay by default */ + /* bits in commands_available */ #define WDG_AVAILABLE (1UL << 1) @@ -222,9 +225,13 @@ static ssize_t do_command(char type, const char *command, const char *parameters size_t count; ssize_t ret; - usleep(1E6); ser_flush_io(upsfd); + /* Apply configurable delay if enabled (> 0) to prevent communication timeouts */ + if (command_delay > 0) { + usleep((useconds_t)command_delay*1000); + } + if (response) { *response = '\0'; } @@ -891,12 +898,35 @@ void upsdrv_tweak_prognames(void) void upsdrv_makevartable(void) { addvar(VAR_VALUE, "lowbatt", "Set low battery level, in percent"); + addvar(VAR_VALUE, "command_delay", + "Delay in milliseconds before each command (default: 0 = no delay; " + "set to 1000ms if experiencing communication timeouts)"); } void upsdrv_initups(void) { + const char *val; + upsfd = ser_open(device_path); ser_set_speed(upsfd, device_path, B2400); + + /* Initialize command_delay from configuration */ + val = getval("command_delay"); + if (val) { + long temp = atol(val); + /* 0 (no delay) or positive values */ + if (temp < 0) { + fatalx(EXIT_FAILURE, "Invalid command_delay parameter: %s (must be >= 0)", val); + } + command_delay = temp; + if (command_delay == 0) { + upsdebugx(2, "command_delay is explicitly set to 0 (no delay)"); + } else { + upsdebugx(2, "Setting command_delay to %ld milliseconds", command_delay); + } + } else { + upsdebugx(2, "Using default command_delay of %ld (no delay)", command_delay); + } } void upsdrv_cleanup(void) From 1643b4753e7fb99d6e5b7b7fd1b8cb29bd46b227 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 30 Jan 2026 15:12:54 +0100 Subject: [PATCH 053/198] scripts/obs/*, docs/packager-guide.txt: introduce new sub-packages for GPIO and UPower drivers [#1209] Signed-off-by: Jim Klimov --- docs/packager-guide.txt | 8 ++++++++ scripts/obs/Makefile.am | 4 ++++ scripts/obs/debian.control | 2 ++ scripts/obs/debian.nut-gpio.install | 1 + scripts/obs/debian.nut-gpio.manpages | 1 + scripts/obs/debian.nut-upower.install | 1 + scripts/obs/debian.nut-upower.manpages | 1 + scripts/obs/nut.dsc | 6 ++++-- 8 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 scripts/obs/debian.nut-gpio.install create mode 100644 scripts/obs/debian.nut-gpio.manpages create mode 100644 scripts/obs/debian.nut-upower.install create mode 100644 scripts/obs/debian.nut-upower.manpages diff --git a/docs/packager-guide.txt b/docs/packager-guide.txt index 7af43e60d5..f3fbf70e8b 100644 --- a/docs/packager-guide.txt +++ b/docs/packager-guide.txt @@ -316,6 +316,14 @@ nut-gpio - Size: - Deps: +[[pkg-nut-upower]] +nut-upower +^^^^^^^^^^ +- Desc: (may be platform-dependent); maybe better `nut-dbus`? +- Files: +- Size: +- Deps: + [[pkg-nut-linux-i2c]] nut-linux-i2c ^^^^^^^^^^^^^ diff --git a/scripts/obs/Makefile.am b/scripts/obs/Makefile.am index 3394091eb4..208d723f4f 100644 --- a/scripts/obs/Makefile.am +++ b/scripts/obs/Makefile.am @@ -52,6 +52,8 @@ EXTRA_DIST += \ debian.nut-doc.doc-base.nut-packager-guide \ debian.nut-doc.doc-base.nut-user-manual \ debian.nut-doc.install \ + debian.nut-gpio.install \ + debian.nut-gpio.manpages \ debian.nut-ipmi.install \ debian.nut-ipmi.manpages \ debian.nut-linux-i2c.install \ @@ -74,6 +76,8 @@ EXTRA_DIST += \ debian.nut-snmp.docs \ debian.nut-snmp.install \ debian.nut-snmp.manpages \ + debian.nut-upower.install \ + debian.nut-upower.manpages \ debian.nut-xml.install \ debian.nut-xml.manpages \ debian.nut.README.Debian \ diff --git a/scripts/obs/debian.control b/scripts/obs/debian.control index e14a9b93a3..d3dcd6e775 100644 --- a/scripts/obs/debian.control +++ b/scripts/obs/debian.control @@ -10,6 +10,8 @@ Build-Depends: debhelper (>= 8.1.3), libsystemd-dev, libgd-dev | libgd2-xpm-dev | libgd2-noxpm-dev, libjpeg-dev, + libglib2.0-dev, + libgpiod-dev, libsnmp-dev | libsnmp9-dev, libssl1.0-dev | libssl-dev, libusb-1.0-dev | libusb-0.1-dev | libusb-dev (>= 0.1.8), diff --git a/scripts/obs/debian.nut-gpio.install b/scripts/obs/debian.nut-gpio.install new file mode 100644 index 0000000000..664b078cc5 --- /dev/null +++ b/scripts/obs/debian.nut-gpio.install @@ -0,0 +1 @@ +debian/tmp/lib/nut/generic_gpio_libgpiod diff --git a/scripts/obs/debian.nut-gpio.manpages b/scripts/obs/debian.nut-gpio.manpages new file mode 100644 index 0000000000..b8878c4fb7 --- /dev/null +++ b/scripts/obs/debian.nut-gpio.manpages @@ -0,0 +1 @@ +debian/tmp/usr/share/man/man8/generic_gpio.8 diff --git a/scripts/obs/debian.nut-upower.install b/scripts/obs/debian.nut-upower.install new file mode 100644 index 0000000000..2dc08ba546 --- /dev/null +++ b/scripts/obs/debian.nut-upower.install @@ -0,0 +1 @@ +debian/tmp/lib/nut/nut-upower diff --git a/scripts/obs/debian.nut-upower.manpages b/scripts/obs/debian.nut-upower.manpages new file mode 100644 index 0000000000..b84266209f --- /dev/null +++ b/scripts/obs/debian.nut-upower.manpages @@ -0,0 +1 @@ +debian/tmp/usr/share/man/man8/nut-upower.8 diff --git a/scripts/obs/nut.dsc b/scripts/obs/nut.dsc index 8c910131a3..c6ed1a52d5 100644 --- a/scripts/obs/nut.dsc +++ b/scripts/obs/nut.dsc @@ -1,6 +1,6 @@ Format: 1.0 Source: nut -Binary: nut, nut-server, nut-client, nut-cgi, nut-snmp, nut-ipmi, nut-modbus, nut-linux-i2c, nut-xml, nut-powerman-pdu, nut-doc, libupsclient4, libupsclient-dev, libnutclient1, libnutclient-dev, python-nut, nut-monitor, libups-nut-perl +Binary: nut, nut-server, nut-client, nut-cgi, nut-snmp, nut-ipmi, nut-modbus, nut-linux-i2c, nut-xml, nut-powerman-pdu, nut-gpio, nut-upower, nut-doc, libupsclient4, libupsclient-dev, libnutclient1, libnutclient-dev, python-nut, nut-monitor, libups-nut-perl Architecture: any all Version: 2.8.4-1 Maintainer: Arnaud Quette @@ -10,7 +10,7 @@ Standards-Version: 3.9.6 Vcs-Browser: http://anonscm.debian.org/gitweb/?p=collab-maint/nut.git;a=summary Vcs-Git: git://anonscm.debian.org/collab-maint/nut.git Testsuite: autopkgtest -Build-Depends: debhelper (>= 8.1.3), cdbs (>= 0.4.122~), autotools-dev, dh-autoreconf, libsystemd-dev, libjpeg-dev, libgd-dev | libgd2-xpm-dev | libgd2-noxpm-dev, libssl1.0-dev | libssl-dev, libsnmp-dev | libsnmp9-dev, libusb-dev (>= 0.1.8), libneon27-gnutls-dev | libneon27-dev, libpowerman0-dev (>= 2.3.3), libwrap0-dev (>= 7.6), python2 | python3, libfreeipmi-dev (>= 0.8.5) [!hurd-i386], libipmimonitoring-dev (>= 1.1.5-2) [!hurd-i386], libnss3-dev, libtool, libltdl-dev, liblua5.1-0-dev, lua5.1, pkg-config, dh-python | dh-python2 | dh-python3 | dh-pypy, libmodbus-dev, libi2c-dev +Build-Depends: debhelper (>= 8.1.3), cdbs (>= 0.4.122~), autotools-dev, dh-autoreconf, libsystemd-dev, libjpeg-dev, libgd-dev | libgd2-xpm-dev | libgd2-noxpm-dev, libssl1.0-dev | libssl-dev, libsnmp-dev | libsnmp9-dev, libusb-dev (>= 0.1.8), libneon27-gnutls-dev | libneon27-dev, libglib2.0-dev, libgpiod-dev, libpowerman0-dev (>= 2.3.3), libwrap0-dev (>= 7.6), python2 | python3, libfreeipmi-dev (>= 0.8.5) [!hurd-i386], libipmimonitoring-dev (>= 1.1.5-2) [!hurd-i386], libnss3-dev, libtool, libltdl-dev, liblua5.1-0-dev, lua5.1, pkg-config, dh-python | dh-python2 | dh-python3 | dh-pypy, libmodbus-dev, libi2c-dev # , python (>= 2.6.6-3~) | python-is-python2 | python-is-python3 #+++ python-pycparser # The pycparser is required to rebuild DMF files, but those pre-built @@ -30,6 +30,7 @@ Package-List: nut-cgi deb admin optional arch=any nut-client deb admin optional arch=any nut-doc deb doc optional arch=all + nut-gpio deb admin optional arch=any nut-ipmi deb admin optional arch=linux-any,kfreebsd-any nut-linux-i2c deb admin optional arch=linux-any nut-modbus deb admin optional arch=any @@ -37,6 +38,7 @@ Package-List: nut-powerman-pdu deb admin extra arch=any nut-server deb admin optional arch=any nut-snmp deb admin optional arch=any + nut-upower deb admin optional arch=any nut-xml deb admin optional arch=any python-nut deb python optional arch=all # DEBTRANSFORM-TAR: nut-2.7.4-DMF+daisychain-cb7c7ea8b0d.tar.gz From 7b37361c67e266e07deca99c0547fbce327996ac Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 31 Jan 2026 10:07:30 +0100 Subject: [PATCH 054/198] drivers/upsdrvctl.c: register callback_upsconf_args if we ENABLE_SHARED_PRIVATE_LIBS [#2800] Signed-off-by: Jim Klimov --- drivers/upsdrvctl.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index 083b3a644b..f534051741 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -1622,6 +1622,10 @@ int main(int argc, char **argv) prog = argv[0]; +#if (defined ENABLE_SHARED_PRIVATE_LIBS) && ENABLE_SHARED_PRIVATE_LIBS + callback_upsconf_args = do_upsconf_args; +#endif + /* Historically special banner*/ snprintf(progdesc, sizeof(progdesc), "%s - UPS driver controller", xbasename(prog)); print_banner_once(progdesc, 0); From 85ec5af19255dbc6ba7890f7fbf9f3bfb0355c2e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 31 Jan 2026 10:09:23 +0100 Subject: [PATCH 055/198] tools/nut-scanner/nutscan-init.c: comment on do_upsconf_args() placeholder vs. ENABLE_SHARED_PRIVATE_LIBS [#2800] Signed-off-by: Jim Klimov --- tools/nut-scanner/nutscan-init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/nut-scanner/nutscan-init.c b/tools/nut-scanner/nutscan-init.c index a577bb7496..cb49ebb844 100644 --- a/tools/nut-scanner/nutscan-init.c +++ b/tools/nut-scanner/nutscan-init.c @@ -138,7 +138,7 @@ size_t max_threads_ipmi = 0; /* limits not yet known */ #endif /* HAVE_PTHREAD */ #ifdef WIN32 -/* Stub for libupsclient */ +/* Stub for libupsclient, no need to register a callback for ENABLE_SHARED_PRIVATE_LIBS builds */ void do_upsconf_args(char *confupsname, char *var, char *val) { NUT_UNUSED_VARIABLE(confupsname); NUT_UNUSED_VARIABLE(var); From 7c3c8542cdc1fafca3a258a8432b77ca24239c85 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 1 Feb 2026 07:37:07 +0100 Subject: [PATCH 056/198] configure.ac: when testing PYTHON* capabilities, check not only for a known PYTHON*_VERSION_INFO_REPORT but also for non-trivial PYTHON* itself - we could forget that due to auto-prio [#1792] Signed-off-by: Jim Klimov --- configure.ac | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 4cbc4f2425..3109b7b084 100644 --- a/configure.ac +++ b/configure.ac @@ -3445,7 +3445,7 @@ if test x"${nut_with_nut_monitor}" != xno ; then PYTHON2_TEST_MODULES="re,glob,codecs,gtk,gtk.glade,gobject,ConfigParser" PYTHON3_TEST_MODULES_QT5="re,glob,codecs,PyQt5.uic,configparser" PYTHON3_TEST_MODULES_QT6="re,glob,codecs,PyQt6.uic,configparser" - if test -n "${PYTHON2_VERSION_INFO_REPORT}" ; then + if test -n "${PYTHON2_VERSION_INFO_REPORT}" -a -n "${PYTHON2}" ; then AC_MSG_CHECKING([if we have Python2 prerequisites for NUT-Monitor desktop application]) if ${PYTHON2} -c "import ${PYTHON2_TEST_MODULES}" 1>&5 2>&5 \ ; then @@ -3499,7 +3499,7 @@ if test x"${nut_with_nut_monitor}" != xno ; then fi fi - if test -n "${PYTHON3_VERSION_INFO_REPORT}" ; then + if test -n "${PYTHON3_VERSION_INFO_REPORT}" -a -n "${PYTHON3}" ; then AC_MSG_CHECKING([if we have Python3 Qt5 prerequisites for NUT-Monitor desktop application]) if ${PYTHON3} -c "import ${PYTHON3_TEST_MODULES_QT5}" 1>&5 2>&5 \ ; then @@ -3515,7 +3515,7 @@ if test x"${nut_with_nut_monitor}" != xno ; then fi fi - if test -n "${PYTHON3_VERSION_INFO_REPORT}" ; then + if test -n "${PYTHON3_VERSION_INFO_REPORT}" -a -n "${PYTHON3}" ; then AC_MSG_CHECKING([if we have Python3 Qt6 prerequisites for NUT-Monitor desktop application]) if ${PYTHON3} -c "import ${PYTHON3_TEST_MODULES_QT6}" 1>&5 2>&5 \ ; then @@ -3533,7 +3533,7 @@ if test x"${nut_with_nut_monitor}" != xno ; then dnl Fall back to default interpreter if test -z "${nut_with_nut_monitor_py2gtk2}${nut_with_nut_monitor_py3qt5}${nut_with_nut_monitor_py3qt6}" \ - && test -n "${PYTHON_VERSION_INFO_REPORT}" \ + && test -n "${PYTHON_VERSION_INFO_REPORT}" -a -n "${PYTHON}" \ && test x"${PYTHON_VERSION_INFO_REPORT}" != x"${PYTHON3_VERSION_INFO_REPORT}" \ && test x"${PYTHON_VERSION_INFO_REPORT}" != x"${PYTHON2_VERSION_INFO_REPORT}" \ ; then From e51b9f0dfb4de44b90667ca664d72d601fb416b2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 13:40:12 +0100 Subject: [PATCH 057/198] *.{c,h}: rectify indentations and line-wrapping in block comments Signed-off-by: Jim Klimov --- clients/upscmd.c | 4 +- clients/upsimage.c | 17 ++--- clients/upsmon.c | 5 +- clients/upssched.c | 10 +-- clients/upsset.c | 5 +- common/common-nut_version.c | 2 +- common/common.c | 4 +- common/wincompat.c | 122 ++++++++++++++++---------------- drivers/al175.c | 6 +- drivers/apc-hid.c | 2 +- drivers/apcsmart-old.c | 32 ++++----- drivers/apcsmart_tabs.c | 14 ++-- drivers/arduino-hid.c | 10 +-- drivers/asem.c | 4 +- drivers/bcmxcp.c | 10 +-- drivers/belkinunv.c | 79 +++++++++++---------- drivers/bestfcom.c | 4 +- drivers/bestfortress.c | 54 +++++++------- drivers/bestuferrups.c | 8 +-- drivers/clone-outlet.c | 40 +++++------ drivers/etapro.c | 10 +-- drivers/genericups.c | 10 +-- drivers/hidparser.c | 12 ++-- drivers/libusb0.c | 22 +++--- drivers/libusb1.c | 22 +++--- drivers/macosx-ups.c | 8 +-- drivers/metasys.c | 33 +++++---- drivers/mge-xml.c | 2 +- drivers/microdowell.c | 12 ++-- drivers/netxml-ups.c | 6 +- drivers/nutdrv_atcl_usb.c | 8 +-- drivers/optiups.c | 8 ++- drivers/richcomm_usb.c | 8 +-- drivers/riello_usb.c | 4 +- drivers/skel.c | 4 +- drivers/snmp-ups-helpers.c | 2 +- drivers/tripplite-hid.c | 6 +- drivers/tripplitesu.c | 8 +-- drivers/upscode2.c | 4 +- drivers/usbhid-ups.c | 2 +- tools/nut-scanner/nut-scanner.c | 4 +- tools/nut-scanner/nutscan-ip.c | 2 +- tools/nut-scanner/scan_avahi.c | 6 +- 43 files changed, 324 insertions(+), 311 deletions(-) diff --git a/clients/upscmd.c b/clients/upscmd.c index 47efe29161..53761a99dc 100644 --- a/clients/upscmd.c +++ b/clients/upscmd.c @@ -133,7 +133,7 @@ static void listcmds(void) } /* we must first read the entire list of commands, - before we can start reading the descriptions */ + * before we can start reading the descriptions */ ltmp = xcalloc(1, sizeof(*ltmp)); ltmp->name = xstrdup(answer[2]); @@ -429,7 +429,7 @@ int main(int argc, char **argv) /* getpass leaks slightly - use -p when testing in valgrind */ if (!have_pw) { /* using getpass or getpass_r might not be a - good idea here (marked obsolete in POSIX) */ + * good idea here (marked obsolete in POSIX) */ char *pwtmp = GETPASS("Password: "); if (!pwtmp) { diff --git a/clients/upsimage.c b/clients/upsimage.c index 909841704f..1d99fdac15 100644 --- a/clients/upsimage.c +++ b/clients/upsimage.c @@ -359,9 +359,9 @@ static void noimage(const char *fmt, ...) } /* draws bar indicator when minimum, nominal or maximum values for the given - UPS variable can be determined. - deviation < 0 means that values below nom should be grey instead of - green */ + * UPS variable can be determined. + * deviation < 0 means that values below nom should be grey instead of green + */ static void drawgeneralbar(double var, int min, int nom, int max, int deviation, const char *format) __attribute__((noreturn)); @@ -388,7 +388,7 @@ static void drawgeneralbar(double var, int min, int nom, int max, max = nom + 3*deviation; } else { /* if nominal value isn't available, assume, it's the - average between min and max */ + * average between min and max */ nom = (min + max) / 2; } @@ -678,7 +678,7 @@ int main(int argc, char **argv) if (!strcmp(cmd, imgvar[i].name)) { /* sanity check whether we have draw function - registered with this variable */ + * registered with this variable */ if (!imgvar[i].drawfunc) { noimage("Draw function N/A"); #ifndef HAVE___ATTRIBUTE__NORETURN @@ -700,9 +700,10 @@ int main(int argc, char **argv) } /* when getting minimum, nominal and maximum values, - we first look if the marginal value is supported - by the UPS driver, if not, we look it up in the - imgarg table under the SAME name */ + * we first look if the marginal value is supported + * by the UPS driver, if not, we look it up in the + * imgarg table under the SAME name + */ /* get the minimum value */ if (imgvar[i].minimum) { diff --git a/clients/upsmon.c b/clients/upsmon.c index c349b193b5..89386bf29f 100644 --- a/clients/upsmon.c +++ b/clients/upsmon.c @@ -236,8 +236,9 @@ static void wall(const char *text) char *command; /* first +1 is for the space between message and text - second +1 is for trailing 0 - +2 is for "" */ + * second +1 is for trailing 0 + * +2 is for "" + */ size_t commandsz = strlen(MESSAGE_CMD) + 1 + 2 + strlen(text) + 1; command = malloc (commandsz); diff --git a/clients/upssched.c b/clients/upssched.c index fe8f914a12..1cb7177aff 100644 --- a/clients/upssched.c +++ b/clients/upssched.c @@ -945,7 +945,7 @@ static TYPE_FD conn_add(TYPE_FD sockfd) conn_t *conn, *tmp, *last; /* We have detected a connection on the opened pipe. So we start - by saving its handle and create a new pipe for future connection */ + * by saving its handle and creating a new pipe for future connection */ conn = xcalloc(1, sizeof(*conn)); conn->fd = sockfd; @@ -983,9 +983,11 @@ static TYPE_FD conn_add(TYPE_FD sockfd) ConnectNamedPipe(acc,&connect_overlapped); /* A new pipe waiting for new client connection has been created. - We could manage the current connection now */ - /* Start a read operation on the newly connected pipe so we could wait - on the event associated to this IO */ + * We could manage the current connection now. + */ + + /* Start a read operation on the newly connected pipe so we could + * wait on the event associated to this IO */ memset(&conn->read_overlapped,0,sizeof(conn->read_overlapped)); memset(conn->buf,0,sizeof(conn->buf)); conn->read_overlapped.hEvent = CreateEvent(NULL, /*Security*/ diff --git a/clients/upsset.c b/clients/upsset.c index 03e10b504f..4b6c302822 100644 --- a/clients/upsset.c +++ b/clients/upsset.c @@ -789,8 +789,9 @@ static void do_type(const char *varname) } /* RANGE is usually paired with NUMBER. - We can ignore 'RANGE' and let the 'NUMBER' - case (which should come next) handle it. */ + * We can ignore 'RANGE' and let the 'NUMBER' + * case (which should come next) handle it. + */ if (!strcasecmp(answer[i], "RANGE")) { continue; } diff --git a/common/common-nut_version.c b/common/common-nut_version.c index 8cb4796c35..cbaf506955 100644 --- a/common/common-nut_version.c +++ b/common/common-nut_version.c @@ -351,7 +351,7 @@ const char *suggest_doc_links(const char *progname, const char *progconf) { * man page section for "System Management Programs". * If this ever changes (e.g. clients like `upsc` can be * a "User Program" just as well), we may need an extra - method argument here. + * method argument here. */ snprintfcat(buf, sizeof(buf), "Read The Fine Manual ('man %s %s') and/or ", diff --git a/common/common.c b/common/common.c index 5e6697a052..10fca114e3 100644 --- a/common/common.c +++ b/common/common.c @@ -763,8 +763,8 @@ struct passwd *get_user_pwent(const char *name) return r; /* POSIX does not specify that "user not found" is an error, so - some implementations of getpwnam() do not set errno when this - happens. */ + * some implementations of getpwnam() do not set errno when this + * happens. */ if (errno == 0) fatalx(EXIT_FAILURE, "OS user %s not found", name); else diff --git a/common/wincompat.c b/common/wincompat.c index 8a6f2e1b3a..59a5a5aa2a 100644 --- a/common/wincompat.c +++ b/common/wincompat.c @@ -483,8 +483,8 @@ void syslog(int priority, const char *fmt, ...) WriteFile (pipe,buf1,strlen(buf2)+sizeof(DWORD),&bytesWritten,NULL); /* testing result is useless. If we have an error and try to report it, - this will probably lead to a call to this function and an infinite - loop */ + * this will probably lead to a call to this function and an infinite + * loop */ CloseHandle(pipe); } @@ -758,9 +758,9 @@ int w32_serial_read (serial_handler_t * sh, void *ptr, size_t ulen, DWORD timeou } else if (sh->vtime_) { /* non-interruptible -- have to use kernel timeouts - also note that this is not strictly correct. - if vmin > ulen then things won't work right. - sh->overlapped_armed = -1; + * also note that this is not strictly correct. + * if vmin > ulen then things won't work right. + * // sh->overlapped_armed = -1; */ inq = ulen; } @@ -909,7 +909,7 @@ int w32_serial_write (serial_handler_t * sh, const void *ptr, size_t len) serial_handler_t * w32_serial_open (const char *name, int flags) { /* flags are currently ignored, it's here just to have the same - interface as POSIX open */ + * interface as POSIX open */ NUT_UNUSED_VARIABLE(flags); COMMTIMEOUTS to; @@ -942,7 +942,7 @@ serial_handler_t * w32_serial_open (const char *name, int flags) SetCommTimeouts (sh->handle, &to); /* Reset serial port to known state of 9600-8-1-no flow control - on open for better behavior under Win 95. + * on open for better behavior under Win 95. */ DCB state; GetCommState (sh->handle, &state); @@ -962,8 +962,7 @@ serial_handler_t * w32_serial_open (const char *name, int flags) state.XonChar = 0x11; state.XoffChar = 0x13; state.fOutxDsrFlow = FALSE; /* disable DSR flow control */ - state.fRtsControl = RTS_CONTROL_ENABLE; /* ignore lead control except - DTR */ + state.fRtsControl = RTS_CONTROL_ENABLE; /* ignore lead control except DTR */ state.fOutxCtsFlow = FALSE; /* disable output flow control */ state.fDtrControl = DTR_CONTROL_ENABLE; /* assert DTR */ state.fDsrSensitivity = FALSE; /* don't assert DSR */ @@ -1097,7 +1096,7 @@ int tcflush (serial_handler_t * sh, int queue) if ((queue == TCIFLUSH) | (queue == TCIOFLUSH)) /* Input flushing by polling until nothing turns up - (we stop after 1000 chars anyway) */ + * (we stop after 1000 chars anyway) */ for (max = 1000; max > 0; max--) { DWORD ev; @@ -1147,7 +1146,7 @@ TCSAFLUSH: flush output and discard input, then change attributes. /* -------------- Set baud rate ------------------ */ /* FIXME: WIN32 also has 14400, 56000, 128000, and 256000. - Unix also has 230400. */ + * Unix also has 230400. */ switch (t->c_ospeed) { @@ -1253,10 +1252,11 @@ TCSAFLUSH: flush output and discard input, then change attributes. state.ErrorChar = 0; /* -------------- Set software flow control ------------------ */ - /* Set fTXContinueOnXoff to FALSE. This prevents the triggering of a - premature XON when the remote device interprets a received character - as XON (same as IXANY on the remote side). Otherwise, a TRUE - value separates the TX and RX functions. */ + /* Set fTXContinueOnXoff to FALSE. This prevents the triggering + * of a premature XON when the remote device interprets a received + * character as XON (same as IXANY on the remote side). + * Otherwise, a TRUE value separates the TX and RX functions. + */ state.fTXContinueOnXoff = TRUE; /* separate TX and RX flow control */ @@ -1283,9 +1283,10 @@ TCSAFLUSH: flush output and discard input, then change attributes. state.fOutxDsrFlow = FALSE; /* Some old flavors of Unix automatically enabled hardware flow - control when software flow control was not enabled. Since newer - Unices tend to require explicit setting of hardware flow-control, - this is what we do. */ + * control when software flow control was not enabled. Since newer + * Unices tend to require explicit setting of hardware flow-control, + * this is what we do. + */ /* RTS/CTS flow control */ if (t->c_cflag & CRTSCTS) @@ -1318,8 +1319,8 @@ TCSAFLUSH: flush output and discard input, then change attributes. state.fDsrSensitivity = TRUE; /* yes */ /* -------------- Error handling ------------------ */ - /* Since read/write operations terminate upon error, we - will use ClearCommError() to resume. */ + /* Since read/write operations terminate upon error, + * we will use ClearCommError() to resume. */ state.fAbortOnError = TRUE; @@ -1335,42 +1336,43 @@ TCSAFLUSH: flush output and discard input, then change attributes. else { /* FIXME: Sometimes when CLRDTR is set, setting - state.fDtrControl = DTR_CONTROL_ENABLE will fail. This - is a problem since a program might want to change some - parameters while DTR is still down. */ + * state.fDtrControl = DTR_CONTROL_ENABLE will fail. + * This is a problem since a program might want to + * change some parameters while DTR is still down. + */ EscapeCommFunction (sh->handle, SETDTR); } /* - The following documentation on was taken from "Linux Serial Programming - HOWTO". It explains how MIN (t->c_cc[VMIN] || vmin_) and TIME - (t->c_cc[VTIME] || vtime_) is to be used. - - In non-canonical input processing mode, input is not assembled into - lines and input processing (erase, kill, delete, etc.) does not - occur. Two parameters control the behavior of this mode: c_cc[VTIME] - sets the character timer, and c_cc[VMIN] sets the minimum number of - characters to receive before satisfying the read. - - If MIN > 0 and TIME = 0, MIN sets the number of characters to receive - before the read is satisfied. As TIME is zero, the timer is not used. - - If MIN = 0 and TIME > 0, TIME serves as a timeout value. The read will - be satisfied if a single character is read, or TIME is exceeded (t = - TIME *0.1 s). If TIME is exceeded, no character will be returned. - - If MIN > 0 and TIME > 0, TIME serves as an inter-character timer. The - read will be satisfied if MIN characters are received, or the time - between two characters exceeds TIME. The timer is restarted every time - a character is received and only becomes active after the first - character has been received. - - If MIN = 0 and TIME = 0, read will be satisfied immediately. The - number of characters currently available, or the number of characters - requested will be returned. According to Antonino (see contributions), - you could issue a fcntl(fd, F_SETFL, FNDELAY); before reading to get - the same result. + * The following documentation on was taken from "Linux Serial + * Programming HOWTO". It explains how MIN (t->c_cc[VMIN] || vmin_) + * and TIME (t->c_cc[VTIME] || vtime_) is to be used. + * + * In non-canonical input processing mode, input is not assembled into + * lines and input processing (erase, kill, delete, etc.) does not + * occur. Two parameters control the behavior of this mode: c_cc[VTIME] + * sets the character timer, and c_cc[VMIN] sets the minimum number of + * characters to receive before satisfying the read. + * + * If MIN > 0 and TIME = 0, MIN sets the number of characters to receive + * before the read is satisfied. As TIME is zero, the timer is not used. + * + * If MIN = 0 and TIME > 0, TIME serves as a timeout value. The read will + * be satisfied if a single character is read, or TIME is exceeded (t = + * TIME *0.1 s). If TIME is exceeded, no character will be returned. + * + * If MIN > 0 and TIME > 0, TIME serves as an inter-character timer. The + * read will be satisfied if MIN characters are received, or the time + * between two characters exceeds TIME. The timer is restarted every time + * a character is received and only becomes active after the first + * character has been received. + * + * If MIN = 0 and TIME = 0, read will be satisfied immediately. The + * number of characters currently available, or the number of characters + * requested will be returned. According to Antonino (see contributions), + * you could issue a fcntl(fd, F_SETFL, FNDELAY); before reading to get + * the same result. */ if (t->c_lflag & ICANON) @@ -1398,15 +1400,15 @@ TCSAFLUSH: flush output and discard input, then change attributes. if ((sh->vmin_ > 0) && (sh->vtime_ == 0)) { /* Returns immediately with whatever is in buffer on a ReadFile(); - or blocks if nothing found. We will keep calling ReadFile(); until - vmin_ characters are read */ + * or blocks if nothing found. We will keep calling ReadFile(); + * until vmin_ characters are read */ to.ReadIntervalTimeout = to.ReadTotalTimeoutMultiplier = MAXDWORD; to.ReadTotalTimeoutConstant = MAXDWORD - 1; } else if ((sh->vmin_ == 0) && (sh->vtime_ > 0)) { /* set timeoout constant appropriately and we will only try to - read one character in ReadFile() */ + * read one character in ReadFile() */ to.ReadTotalTimeoutConstant = sh->vtime_; to.ReadIntervalTimeout = to.ReadTotalTimeoutMultiplier = MAXDWORD; } @@ -1418,7 +1420,7 @@ TCSAFLUSH: flush output and discard input, then change attributes. else if ((sh->vmin_ == 0) && (sh->vtime_ == 0)) { /* returns immediately with whatever is in buffer as per - Time-Outs docs in Win32 SDK API docs */ + * Time-Outs docs in Win32 SDK API docs */ to.ReadIntervalTimeout = MAXDWORD; } @@ -1567,9 +1569,9 @@ int tcgetattr (serial_handler_t * sh, struct termios *t) /* -------------- Hardware flow control ------------------ */ /* Some old flavors of Unix automatically enabled hardware flow - control when software flow control was not enabled. Since newer - Unices tend to require explicit setting of hardware flow-control, - this is what we do. */ + * control when software flow control was not enabled. Since newer + * Unices tend to require explicit setting of hardware flow-control, + * this is what we do. */ /* Input flow-control */ if ((state.fRtsControl == RTS_CONTROL_HANDSHAKE) && @@ -1582,9 +1584,9 @@ int tcgetattr (serial_handler_t * sh, struct termios *t) /* -------------- CLOCAL --------------- */ /* DSR is only lead toggled only by CLOCAL. Check it to see if - CLOCAL was called. */ + * CLOCAL was called. */ /* FIXME: If tcsetattr() hasn't been called previously, this may - give a false CLOCAL. */ + * give a false CLOCAL. */ if (state.fDsrSensitivity == FALSE) t->c_cflag |= CLOCAL; diff --git a/drivers/al175.c b/drivers/al175.c index 5ea80e5689..fff1bf2d53 100644 --- a/drivers/al175.c +++ b/drivers/al175.c @@ -327,7 +327,7 @@ static void comli_prepare(raw_data_t *dest, const comli_head_t *h, const void *b /* it's caller responsibility to allocate enough space. - else it is a bug in the program */ + * else it is a bug in the program */ if ( (out+11+count+2) > (dest->buf + dest->buf_size) ) fatalx(EXIT_FAILURE, "too small dest in comli_prepare\n"); @@ -1276,7 +1276,7 @@ void upsdrv_shutdown(void) /* tell the UPS to shut down, then return - DO NOT SLEEP HERE */ /* maybe try to detect the UPS here, but try a shutdown even if - it doesn't respond at first if possible */ + * it doesn't respond at first if possible */ /* replace with a proper shutdown function */ upslogx(LOG_ERR, "shutdown not supported"); @@ -1284,7 +1284,7 @@ void upsdrv_shutdown(void) set_exit_flag(EF_EXIT_FAILURE); /* you may have to check the line status since the commands - for toggling power are frequently different for OL vs. OB */ + * for toggling power are frequently different for OL vs. OB */ /* OL: this must power cycle the load if possible */ diff --git a/drivers/apc-hid.c b/drivers/apc-hid.c index 6f1826d725..de0ae5a924 100644 --- a/drivers/apc-hid.c +++ b/drivers/apc-hid.c @@ -42,7 +42,7 @@ static char * tweak_max_report[] = { /* Back-UPS ES 700 does NOT overflow. */ /* Back-UPS ES 725 does NOT overflow. */ /* Back-UPS ES 525 overflows on ReportID 0x0c - (UPS.PowerSummary.RemainingCapacity). */ + * (UPS.PowerSummary.RemainingCapacity). */ "Back-UPS ES 525", /* Back-UPS CS 650 overflows on ReportID 0x46 */ "Back-UPS CS", diff --git a/drivers/apcsmart-old.c b/drivers/apcsmart-old.c index 740a41e90c..f28812abeb 100644 --- a/drivers/apcsmart-old.c +++ b/drivers/apcsmart-old.c @@ -316,8 +316,8 @@ static void do_capabilities(void) upsdebugx(1, "APC - About to get capabilities string"); /* If we can do caps, then we need the Firmware revision which has - the locale descriptor as the last character (ugh) - */ + * the locale descriptor as the last character (ugh) + */ ptr = dstate_getinfo("ups.firmware"); if (ptr) upsloc = ptr[strlen(ptr) - 1]; @@ -340,8 +340,8 @@ static void do_capabilities(void) /* Early Smart-UPS, not as smart as later ones */ /* This should never happen since we only call - this if the REQ_CAPABILITIES command is supported - */ + * this if the REQ_CAPABILITIES command is supported + */ upslogx(LOG_ERR, "ERROR: APC cannot do capabilities but said it could!"); return; } @@ -494,8 +494,8 @@ static void oldapcsetup(void) update_status(); /* If we have come down this path then we dont do capabilities and - other shiny features - */ + * other shiny features + */ } static void protocol_verify(unsigned char cmd) @@ -645,9 +645,9 @@ static void getbaseinfo(void) upsdebugx(1, "APC - Attempting to find command set"); /* Initially we ask the UPS what commands it takes - If this fails we are going to need an alternate - strategy - we can deal with that if it happens - */ + * If this fails we are going to need an alternate + * strategy - we can deal with that if it happens + */ ret = ser_send_char(upsfd, APC_CMDSET); @@ -665,14 +665,12 @@ static void getbaseinfo(void) return; } - upsdebugx(1, "APC - Parsing out command set"); - /* We have the version.alert.cmdchars string - NB the alert chars are normally in IGNCHARS - so will have been pretty much edited out. - You will need to change the ser_get_line above if - you want to check those out too.... - */ - alrts = strchr(temp, '.'); + * NB the alert chars are normally in IGNCHARS + * so will have been pretty much edited out. + * You will need to change the ser_get_line above if + * you want to check those out too.... + */ + alrts = strchr(temp, '.'); if (alrts == NULL) { fatalx(EXIT_FAILURE, "Unable to split APC version string"); } diff --git a/drivers/apcsmart_tabs.c b/drivers/apcsmart_tabs.c index 0955e01dd5..06dd1d774f 100644 --- a/drivers/apcsmart_tabs.c +++ b/drivers/apcsmart_tabs.c @@ -73,13 +73,13 @@ apc_vartab_t apc_vartab[] = { { NULL, 0, 0, NULL, 0, 0 } /* todo: - - I = alarm enable (hex field) - split into alarm.n.enable - J = alarm status (hex field) - split into alarm.n.status - - 0x15 = output voltage selection (APC_F_VOLT) - 0x5C = load power (APC_POLL|APC_F_PERCENT) - + * + * I = alarm enable (hex field) - split into alarm.n.enable + * J = alarm status (hex field) - split into alarm.n.status + * + * 0x15 = output voltage selection (APC_F_VOLT) + * 0x5C = load power (APC_POLL|APC_F_PERCENT) + * */ }; diff --git a/drivers/arduino-hid.c b/drivers/arduino-hid.c index 1bf448cf5b..8b556ebe63 100644 --- a/drivers/arduino-hid.c +++ b/drivers/arduino-hid.c @@ -103,9 +103,9 @@ static hid_info_t arduino_hid2nut[] = { { "battery.runtime", 0, 0, "UPS.PowerSummary.RunTimeToEmpty", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL}, { "battery.runtime.low", 0, 0, "UPS.PowerSummary.RemainingTimeLimit", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL }, /* Parse `*Capacity` values assuming `UPS.PowerSummary.CapacityMode` is set to 2, which means the `*Capacity` - units are percent. The Arduino HID Powerdevice library is capable of doing other modes, if the Sketch wants - to use them, but it appears most drivers just assume percent. - */ + * units are percent. The Arduino HID Powerdevice library is capable of doing other modes, if the Sketch wants + * to use them, but it appears most drivers just assume percent. + */ { "battery.charge", 0, 0, "UPS.PowerSummary.RemainingCapacity", NULL, "%.0f", 0, NULL }, { "battery.charge.low", 0, 0, "UPS.PowerSummary.RemainingCapacityLimit", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL}, { "battery.charge.warning", 0, 0, "UPS.PowerSummary.WarningCapacityLimit", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL}, @@ -115,8 +115,8 @@ static hid_info_t arduino_hid2nut[] = { { "output.voltage", 0, 0, "UPS.PowerConverter.Output.Voltage", NULL, "%.1f", 0, NULL }, /* USB HID PresentStatus Flags - TODO: Parse these into battery.charger.status - */ + * TODO: Parse these into battery.charger.status + */ { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.ACPresent", NULL, NULL, HU_FLAG_QUICK_POLL, online_info}, { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Discharging", NULL, NULL, HU_FLAG_QUICK_POLL, discharging_info}, { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Charging", NULL, NULL, HU_FLAG_QUICK_POLL, charging_info}, diff --git a/drivers/asem.c b/drivers/asem.c index 6b530db70f..ac0170cb9b 100644 --- a/drivers/asem.c +++ b/drivers/asem.c @@ -381,7 +381,7 @@ void upsdrv_shutdown(void) /* tell the UPS to shut down, then return - DO NOT SLEEP HERE */ /* maybe try to detect the UPS here, but try a shutdown even if - it doesn't respond at first if possible */ + * it doesn't respond at first if possible */ /* replace with a proper shutdown function */ upslogx(LOG_ERR, "shutdown not supported"); @@ -389,7 +389,7 @@ void upsdrv_shutdown(void) set_exit_flag(EF_EXIT_FAILURE); /* you may have to check the line status since the commands - for toggling power are frequently different for OL vs. OB */ + * for toggling power are frequently different for OL vs. OB */ /* OL: this must power cycle the load if possible */ diff --git a/drivers/bcmxcp.c b/drivers/bcmxcp.c index efb108f3dd..d66d38f6c2 100644 --- a/drivers/bcmxcp.c +++ b/drivers/bcmxcp.c @@ -1077,7 +1077,7 @@ void init_ext_vars(void) send_write_command(AUTHOR, 4); - sleep(PW_SLEEP); /* Need to. Have to wait at least 0,25 sec max 16 sec */ + sleep(PW_SLEEP); /* Need to. Have to wait at least 0,25 sec max 16 sec */ cbuf[0] = PW_SET_CONF_COMMAND; cbuf[1] = PW_CONF_REQ; @@ -2040,10 +2040,10 @@ static int instcmd(const char *cmdname, const char *extra) return decode_instcmd_exec(res, (unsigned char)answer[0], cmdname, "Testing battery now"); /* Get test info from UPS ? - Should we wait for 50 sec and get the - answer from the test. - Or return, as we may lose line power - and need to do a shutdown.*/ + * Should we wait for 50 sec and get the + * answer from the test. + * Or return, as we may lose line power + * and need to do a shutdown.*/ } if (!strcasecmp(cmdname, "test.system.start")) { diff --git a/drivers/belkinunv.c b/drivers/belkinunv.c index a8a0519304..f0bbed41cf 100644 --- a/drivers/belkinunv.c +++ b/drivers/belkinunv.c @@ -235,7 +235,7 @@ static void belkin_nut_open_tty(void) ser_set_speed(upsfd, device_path, B2400); /* must clear DTR and set RTS for 1 second for UPS to go to - "smart" mode */ + * "smart" mode */ ser_set_dtr(upsfd, 0); ser_set_rts(upsfd, 1); sleep(1); @@ -463,8 +463,8 @@ static TYPE_FD_SER belkin_std_open_tty(const char *device) { } /* set communications parameters: 2400 baud, 8 bits, 1 stop bit, no - parity, enable reading, hang up when done, ignore modem control - lines. */ + * parity, enable reading, hang up when done, ignore modem control + * lines. */ memset(&tios, 0, sizeof(tios)); tios.c_cflag = B2400 | CS8 | CREAD | HUPCL | CLOCAL; tios.c_cc[VMIN] = 1; @@ -476,16 +476,16 @@ static TYPE_FD_SER belkin_std_open_tty(const char *device) { } /* signal the UPS to enter "smart" mode. This is done by setting RTS - and dropping DTR for at least 0.25 seconds. RTS and DTR refer to - two specific pins in the 9-pin serial connector. Note: this must - be done for at least 0.25 seconds for the UPS to react. Ignore - any errors, as this probably means we are not on a "real" serial - port. */ + * and dropping DTR for at least 0.25 seconds. RTS and DTR refer to + * two specific pins in the 9-pin serial connector. Note: this must + * be done for at least 0.25 seconds for the UPS to react. Ignore + * any errors, as this probably means we are not on a "real" serial + * port. */ ser_set_dtr(upsfd, 0); ser_set_rts(upsfd, 1); /* flush both directions of serial port: throw away all data in - transit */ + * transit */ r = ser_flush_io(fd); if (r == -1) { close(fd); @@ -507,11 +507,11 @@ static TYPE_FD_SER belkin_std_open_tty(const char *device) { #endif /* WIN32 */ /* sleep at least 0.25 seconds for the UPS to wake up. Belkin's own - software sleeps 1 second, so that's what we do, too. */ + * software sleeps 1 second, so that's what we do, too. */ usleep(1000000); /* flush incoming data again, and read any remaining garbage - bytes. There should not be any. */ + * bytes. There should not be any. */ r = tcflush(fd, TCIFLUSH); if (r == -1) { close(fd); @@ -836,7 +836,7 @@ static int belkin_wait(void) } /* wait until the UPS is online and the battery level - is >= level */ + * is >= level */ bs = belkin_std_read_int(fd, REG_BATSTATUS); /* battery status */ if (bs==-1) { failcount++; @@ -1050,9 +1050,9 @@ void upsdrv_updateinfo(void) if (us & US_ACFAILURE) { status_set("ACFAIL"); /* AC failure, self-invented */ /* Note: this is not the same as "on battery", because this - flag makes sense even during a test, or when the load is - off. It simply reflects the status of utility power. A - "critical" situation should be OB && BL && ACFAIL. */ + * flag makes sense even during a test, or when the load is + * off. It simply reflects the status of utility power. A + * "critical" situation should be OB && BL && ACFAIL. */ } if (us & US_OVERLOAD) { status_set("OVER"); /* overload */ @@ -1175,20 +1175,20 @@ void upsdrv_shutdown(void) * general handling of other `sdcommands` here */ /* Note: this UPS cannot (apparently) be put into "soft - shutdown" mode; thus the -k option should not normally be - used; instead, a workaround using the "-x wait" option - should be used; see belkinunv(8) for details. - - In case somebody uses the -k option, the best we can do - here is a timed shutdown; this will wake up the attached - load after 10 minutes, come rain come shine. If AC power - does not return, this will probably lead to a few - shutdown/reboot cycles, until the batteries finally die and - possibly cause a system crash. - - Don't use this! Use the solution involving the "-x wait" - option instead, as suggested on the belkinunv(8) man - page. + * shutdown" mode; thus the -k option should not normally be + * used; instead, a workaround using the "-x wait" option + * should be used; see belkinunv(8) for details. + * + * In case somebody uses the -k option, the best we can do + * here is a timed shutdown; this will wake up the attached + * load after 10 minutes, come rain come shine. If AC power + * does not return, this will probably lead to a few + * shutdown/reboot cycles, until the batteries finally die and + * possibly cause a system crash. + * + * Don't use this! Use the solution involving the "-x wait" + * option instead, as suggested on the belkinunv(8) man + * page. */ upslogx(LOG_WARNING, @@ -1209,10 +1209,11 @@ int instcmd(const char *cmdname, const char *extra) upsdebug_INSTCMD_STARTING(cmdname, extra); /* We use test.failure.start to initiate a "deep battery test". - This does not really simulate a 'power failure', because we - won't start shutdown procedures during a test. - - We use test.battery.start to initiate a "10-second battery test". */ + * This does not really simulate a 'power failure', because we + * won't start shutdown procedures during a test. + * + * We use test.battery.start to initiate a "10-second battery test". + */ if (!strcasecmp(cmdname, "beeper.off")) { /* compatibility mode for old command */ @@ -1277,11 +1278,11 @@ int instcmd(const char *cmdname, const char *extra) if (!strcasecmp(cmdname, "shutdown.reboot")) { upslog_INSTCMD_POWERSTATE_CHANGE(cmdname, extra); /* restarttimer is in minutes, shutdowntimer is in - seconds. Still, restarttimer=1 is not safe, - because it might be decremented before - shutdowntimer is set, which would cause the UPS to - stay off. So we need restarttimer=2, which means, - the UPS will stay off between 60 and 120 seconds */ + * seconds. Still, restarttimer=1 is not safe, + * because it might be decremented before + * shutdowntimer is set, which would cause the UPS to + * stay off. So we need restarttimer=2, which means, + * the UPS will stay off between 60 and 120 seconds */ r = belkin_nut_write_int(REG_RESTARTTIMER, 2); /* 2 minutes */ r |= belkin_nut_write_int(REG_SHUTDOWNTIMER, 1); /* 1 second */ if (r == -1) upslogx(LOG_WARNING, "Command '%s' failed", cmdname); @@ -1387,7 +1388,7 @@ void upsdrv_makevartable(void) void upsdrv_initups(void) { /* If '-x wait' or '-x wait=' option given, branch into - standalone behavior. */ + * standalone behavior. */ if (getval("wait") || dstate_getinfo("driver.flag.wait")) { exit(belkin_wait()); } diff --git a/drivers/bestfcom.c b/drivers/bestfcom.c index 5608cca0b1..231b427c47 100644 --- a/drivers/bestfcom.c +++ b/drivers/bestfcom.c @@ -456,7 +456,7 @@ static void ups_sync(void) char buf[256]; /* A bit better sanity might be good here. As is, we expect the - human to observe the time being totally not a time. */ + * human to observe the time being totally not a time. */ if (execute("time\r", buf, sizeof(buf)) > 0) { upsdebugx(1, "UPS Time: %s", buf); @@ -606,7 +606,7 @@ static void upsdrv_init_nofc(void) upsdebugx(2, "id response: %s", rstring); /* Better way to identify this unit is using "d 15\r", which results in - "15 M# MD1KVA", "id\r" yields "Unit ID "C1K03588"" */ + * "15 M# MD1KVA", "id\r" yields "Unit ID "C1K03588"" */ if (strstr(rstring, "Unit ID \"C1K")){ fc.model = MDxxxx; snprintf(fc.name, sizeof(fc.name), "%s", "Micro Ferrups"); diff --git a/drivers/bestfortress.c b/drivers/bestfortress.c index 174009a9f6..9795487287 100644 --- a/drivers/bestfortress.c +++ b/drivers/bestfortress.c @@ -93,21 +93,21 @@ void upsdrv_initinfo(void) dstate_setinfo("output.voltamps", "0"); /* tunable via front panel: (european voltage level) - parameter factory default range - INFO_LOWXFER 196 V p7=nnn 160-210 - INFO_HIGHXFER 254 V p8=nnn 215-274 - INFO_LOBATTIME 2 min p2=n 1-5 - - comm mode p6=0 dumb DONT USE (will lose access to parameter setting!) - p6=1 B1200 - p6=2 B2400 - P6=3 B4800 - p6=4 B9600 - maybe cycle through speeds to autodetect? - - echo off e0 - echo on e1 - */ + * parameter factory default range + * INFO_LOWXFER 196 V p7=nnn 160-210 + * INFO_HIGHXFER 254 V p8=nnn 215-274 + * INFO_LOBATTIME 2 min p2=n 1-5 + * + * comm mode p6=0 dumb DONT USE (will lose access to parameter setting!) + * p6=1 B1200 + * p6=2 B2400 + * P6=3 B4800 + * p6=4 B9600 + * maybe cycle through speeds to autodetect? + * + * echo off e0 + * echo on e1 + */ dstate_setinfo("input.transfer.low", "%s", ""); dstate_setflags("input.transfer.low", ST_FLAG_STRING | ST_FLAG_RW); dstate_setaux("input.transfer.low", 3); @@ -314,16 +314,16 @@ void upsdrv_updateinfo(void) /* syslog (LOG_DAEMON | LOG_NOTICE,"ups: got %d chars '%s'\n", recv, temp + 2); */ /* status example: - 000000000001000000000000012201210000001200014500000280600000990025000000000301BE - 000000000001000000000000012401230000001200014800000280600000990025000000000301B7 - |Vi||Vo| |Io||Psou| |Vb||f| |tr||Ti| CS - 000000000001000000000000023802370000000200004700000267500000990030000000000301BD - 1 1 2 2 3 3 4 4 5 5 6 6 7 7 78 - 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 90 + * 000000000001000000000000012201210000001200014500000280600000990025000000000301BE + * 000000000001000000000000012401230000001200014800000280600000990025000000000301B7 + * |Vi||Vo| |Io||Psou| |Vb||f| |tr||Ti| CS + * 000000000001000000000000023802370000000200004700000267500000990030000000000301BD + * 1 1 2 2 3 3 4 4 5 5 6 6 7 7 78 + * 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 90 */ /* last bytes are a checksum: - interpret response as hex string, sum of all bytes must be zero + * interpret response as hex string, sum of all bytes must be zero */ checksum_ok = ( (checksum (temp+2) & 0xff) == 0 ); /* setinfo (INFO_, ""); */ @@ -339,8 +339,8 @@ void upsdrv_updateinfo(void) /* I can't figure out why this is missing the first two chars. - But the first two chars are not used, so just set them to zero - when missing. */ + * But the first two chars are not used, so just set them to zero + * when missing. */ len = strlen(temp+2); temp[0] = '0'; temp[1] = '0'; @@ -389,9 +389,9 @@ void upsdrv_updateinfo(void) low_batt = fromhex(p[21]) & 8 || fromhex(p[20]) & 1; is_off = p[11] == '0'; trimming = p[33] == '1'; - boosting = 0; /* FIXME, don't know which bit gets set - (brownouts are very rare here and I can't - simulate one) */ + boosting = 0; /* FIXME, don't know which bit gets set + * (brownouts are very rare here and + * I can't simulate one) */ status_init(); if (low_batt) diff --git a/drivers/bestuferrups.c b/drivers/bestuferrups.c index 6ae94ac6cc..a9bcc6339c 100644 --- a/drivers/bestuferrups.c +++ b/drivers/bestuferrups.c @@ -119,7 +119,7 @@ void upsdrv_initinfo (void) fc.model = RE1800; } else if (memcmp(temp, "C1", 2) == 0) { /* Better way to identify unit is using "d 15\r", which results in - "15 M# MD1KVA", "id\r" yields "Unit ID "C1K03588"" */ + * "15 M# MD1KVA", "id\r" yields "Unit ID "C1K03588"" */ fc.model = MD1KVA; } @@ -428,8 +428,8 @@ void upsdrv_updateinfo(void) dstate_setinfo("ambient.temperature", "%05.1f", (double)ambtemp); dstate_dataok(); - /* Tim: With out this return, it always falls over to the - datastate() at the end of the function */ + /* Tim: Without this return, it always falls over to the + * datastate() at the end of the function */ return; } else { @@ -450,7 +450,7 @@ static void ups_sync(void) fflush (stdout); /* A bit better sanity might be good here. As is, we expect the - human to observe the time being totally not a time. */ + * human to observe the time being totally not a time. */ if (execute("time\r", buf, sizeof(buf)) > 0) { fprintf(stderr, "UPS Time: %s\n", buf); diff --git a/drivers/clone-outlet.c b/drivers/clone-outlet.c index 98178ca7cc..d57aa9efdd 100644 --- a/drivers/clone-outlet.c +++ b/drivers/clone-outlet.c @@ -1,24 +1,24 @@ /* -* clone-outlet.c: clone an UPS, treating its outlet as if it were an UPS -* (monitoring only) -* -* Copyright (C) 2009 - Arjen de Korte -* Copyright (C) 2024 - 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 -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ + * clone-outlet.c: clone an UPS, treating its outlet as if it were an UPS + * (monitoring only) + * + * Copyright (C) 2009 - Arjen de Korte + * Copyright (C) 2024 - 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ #include "main.h" #include "parseconf.h" diff --git a/drivers/etapro.c b/drivers/etapro.c index d2e72010de..1e077ed836 100644 --- a/drivers/etapro.c +++ b/drivers/etapro.c @@ -82,8 +82,8 @@ etapro_get_response(const char *resp_type) unsigned int n, val; /* Read until a newline is found or there is no room in the buffer. - Unlike ser_get_line(), don't discard the following characters - because we have to handle multi-line responses. */ + * Unlike ser_get_line(), don't discard the following characters + * because we have to handle multi-line responses. */ n = 0; while (ser_get_char(upsfd, (unsigned char *)&tmp[n], 1, 0) == 1) { if (n >= sizeof(tmp) - 1 || tmp[n] == '\n') @@ -292,7 +292,7 @@ upsdrv_updateinfo(void) } /* TODO: >= 1000VA models have a 24V battery (max 28V) - check - the model string returned by the RI command. */ + * the model string returned by the RI command. */ battvolt = (14.0 / 255) * x; x = etapro_get_response("SL"); /* load (on battery), 0xFF = 150% */ @@ -308,8 +308,8 @@ upsdrv_updateinfo(void) return; } /* This is the time how long the UPS has been running on battery - (in seconds, reset to zero after power returns), but there - seems to be no variable defined for this yet... */ + * (in seconds, reset to zero after power returns), but there + * seems to be no variable defined for this yet... */ status_init(); diff --git a/drivers/genericups.c b/drivers/genericups.c index fec4c119ad..ea08728b0e 100644 --- a/drivers/genericups.c +++ b/drivers/genericups.c @@ -194,7 +194,7 @@ void upsdrv_initinfo(void) } /* - User wants to override the input signal definitions. See also upsdrv_initups(). + * User wants to override the input signal definitions. See also upsdrv_initups(). */ if ((v = getval("OL")) != NULL) { parse_input_signals(v, &upstab[upstype].line_ol, &upstab[upstype].val_ol); @@ -449,10 +449,10 @@ void upsdrv_initups(void) } /* - See if the user wants to override the output signal definitions? - This must be done here, since we might go to upsdrv_shutdown() - immediately. Input signal definition override is handled in - upsdrv_initinfo() + * See if the user wants to override the output signal definitions? + * This must be done here, since we might go to upsdrv_shutdown() + * immediately. Input signal definition override is handled in + * upsdrv_initinfo() */ if ((v = getval("CP")) != NULL) { parse_output_signals(v, &upstab[upstype].line_norm); diff --git a/drivers/hidparser.c b/drivers/hidparser.c index 2132dba053..bce04a32e7 100644 --- a/drivers/hidparser.c +++ b/drivers/hidparser.c @@ -571,12 +571,12 @@ HIDData_t *FindObject_with_ID_Node(HIDDesc_t *pDesc_arg, uint8_t ReportID, HIDNo void GetValue(const unsigned char *Buf, HIDData_t *pData, long *pValue) { /* Note: https://github.com/networkupstools/nut/issues/1023 - This conversion code can easily be sensitive to 32- vs. 64- bit - compilation environments. Consider the possibility of overflow - in 32-bit representations when computing with extreme values, - for example LogMax-LogMin+1. - Test carefully in both environments if changing any declarations. - */ + * This conversion code can easily be sensitive to 32- vs. 64- bit + * compilation environments. Consider the possibility of overflow + * in 32-bit representations when computing with extreme values, + * for example LogMax-LogMin+1. + * Test carefully in both environments if changing any declarations. + */ int Weight, Bit; unsigned long mask, signbit, magMax, magMin; diff --git a/drivers/libusb0.c b/drivers/libusb0.c index 1780168577..ab002f36f3 100644 --- a/drivers/libusb0.c +++ b/drivers/libusb0.c @@ -354,7 +354,7 @@ static int nut_libusb_open(usb_dev_handle **udevp, bus->dirname, dev->filename); /* supported vendors are now checked by the - supplied matcher */ + * supplied matcher */ /* open the device */ *udevp = udev = usb_open(dev); @@ -387,10 +387,10 @@ static int nut_libusb_open(usb_dev_handle **udevp, } /* collect the identifying information of this - device. Note that this is safe, because - there's no need to claim an interface for - this (and therefore we do not yet need to - detach any kernel drivers). */ + * device. Note that this is safe, because + * there's no need to claim an interface for + * this (and therefore we do not yet need to + * detach any kernel drivers). */ free(curDevice->Vendor); free(curDevice->Product); @@ -601,11 +601,11 @@ static int nut_libusb_open(usb_dev_handle **udevp, rdlen1); /* SECOND METHOD: find HID descriptor among "extra" bytes of - interface descriptor, i.e., bytes tucked onto the end of - descriptor 2. */ + * interface descriptor, i.e., bytes tucked onto the end of + * descriptor 2. */ /* Note: on some broken UPS's (e.g. Tripp Lite Smart1000LCD), - only this second method gives the correct result */ + * only this second method gives the correct result */ iface = &dev->config[usb_subdriver.usb_config_index].interface[usb_subdriver.hid_rep_index].altsetting[0]; for (i=0; iextralen; i+=iface->extra[i]) { upsdebugx(4, "i=%d, extra[i]=%02x, extra[i+1]=%02x", i, @@ -630,9 +630,9 @@ static int nut_libusb_open(usb_dev_handle **udevp, rdlen2); /* when available, always choose the second value, as it - seems to be more reliable (it is the one reported e.g. by - lsusb). Note: if the need arises, can change this to use - the maximum of the two values instead. */ + * seems to be more reliable (it is the one reported e.g. by + * lsusb). Note: if the need arises, can change this to use + * the maximum of the two values instead. */ if ((curDevice->VendorID == 0x463) && (curDevice->bcdDevice == 0x0202)) { upsdebugx(1, "Eaton device v2.02. Using full report descriptor"); rdlens[0] = rdlen1; diff --git a/drivers/libusb1.c b/drivers/libusb1.c index c56746278a..955ada91bd 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -344,10 +344,10 @@ static int nut_libusb_open(libusb_device_handle **udevp, udev = *udevp; /* collect the identifying information of this - device. Note that this is safe, because - there's no need to claim an interface for - this (and therefore we do not yet need to - detach any kernel drivers). */ + * device. Note that this is safe, because + * there's no need to claim an interface for + * this (and therefore we do not yet need to + * detach any kernel drivers). */ free(curDevice->Vendor); free(curDevice->Product); @@ -666,14 +666,14 @@ static int nut_libusb_open(libusb_device_handle **udevp, upsdebugx(3, "HID descriptor length (method 1) %" PRIi32, rdlen1); /* SECOND METHOD: find HID descriptor among "extra" bytes of - interface descriptor, i.e., bytes tucked onto the end of - descriptor 2. */ + * interface descriptor, i.e., bytes tucked onto the end of + * descriptor 2. */ /* Note: on some broken UPS's (e.g. Tripp Lite Smart1000LCD), - only this second method gives the correct result */ + * only this second method gives the correct result */ /* for now, we always assume configuration 0, interface 0, - altsetting 0, as above. */ + * altsetting 0, as above. */ if_desc = &(conf_desc->interface[usb_subdriver.hid_rep_index].altsetting[0]); for (i = 0; i < if_desc->extra_length; i += if_desc->extra[i]) { @@ -696,9 +696,9 @@ static int nut_libusb_open(libusb_device_handle **udevp, upsdebugx(3, "HID descriptor length (method 2) %" PRIi32, rdlen2); /* when available, always choose the second value, as it - seems to be more reliable (it is the one reported e.g. by - lsusb). Note: if the need arises, can change this to use - the maximum of the two values instead. */ + * seems to be more reliable (it is the one reported e.g. by + * lsusb). Note: if the need arises, can change this to use + * the maximum of the two values instead. */ if ((curDevice->VendorID == 0x463) && (curDevice->bcdDevice == 0x0202)) { upsdebugx(1, "Eaton device v2.02. Using full report descriptor"); rdlens[0] = rdlen1; diff --git a/drivers/macosx-ups.c b/drivers/macosx-ups.c index 92c31bfef2..0f03fd0b82 100644 --- a/drivers/macosx-ups.c +++ b/drivers/macosx-ups.c @@ -270,11 +270,11 @@ void upsdrv_shutdown(void) /* tell the UPS to shut down, then return - DO NOT SLEEP HERE */ /* maybe try to detect the UPS here, but try a shutdown even if - it doesn't respond at first if possible */ + * it doesn't respond at first if possible */ /* NOTE: Mac OS X already has shutdown routines - this driver is more - for monitoring and notification purposes. Still, there is a key that - might be useful to set in SystemConfiguration land. */ + * for monitoring and notification purposes. Still, there is a key that + * might be useful to set in SystemConfiguration land. */ /* replace with a proper shutdown function */ upslogx(LOG_ERR, "shutdown not supported"); @@ -282,7 +282,7 @@ void upsdrv_shutdown(void) set_exit_flag(EF_EXIT_FAILURE); /* you may have to check the line status since the commands - for toggling power are frequently different for OL vs. OB */ + * for toggling power are frequently different for OL vs. OB */ /* OL: this must power cycle the load if possible */ diff --git a/drivers/metasys.c b/drivers/metasys.c index 4dab002167..bfe9a65851 100644 --- a/drivers/metasys.c +++ b/drivers/metasys.c @@ -877,9 +877,9 @@ void upsdrv_shutdown(void) unsigned char command[10], answer[10]; /* Ensure that the ups is configured for automatically - restart after a complete battery discharge - and when the power comes back after a shutdown. - Similar code to "shutdown.restart" but different timeouts. + * restart after a complete battery discharge + * and when the power comes back after a shutdown. + * Similar code to "shutdown.restart" but different timeouts. */ if (! autorestart) { command[0]=UPS_SET_TIMES_ON_BATTERY; @@ -909,7 +909,7 @@ void upsdrv_shutdown(void) command_write_sequence(command, 9, answer); /* you may have to check the line status since the commands - for toggling power are frequently different for OL vs. OB */ + * for toggling power are frequently different for OL vs. OB */ /* OL: this must power cycle the load if possible */ @@ -1011,8 +1011,9 @@ static int instcmd(const char *cmdname, const char *extra) command[0]=UPS_SET_BATTERY_TEST; command[1]=0x01; /* 0 = perform battery test - 1 = force UPS on battery power - 2 = restore standard mode (mains power) */ + * 1 = force UPS on battery power + * 2 = restore standard mode (mains power) + */ command_write_sequence(command, 2, answer); return STAT_INSTCMD_HANDLED; } @@ -1024,8 +1025,9 @@ static int instcmd(const char *cmdname, const char *extra) command[0]=UPS_SET_BATTERY_TEST; command[1]=0x02; /* 0 = perform battery test - 1 = force UPS on battery power - 2 = restore standard mode (mains power) */ + * 1 = force UPS on battery power + * 2 = restore standard mode (mains power) + */ command_write_sequence(command, 2, answer); return STAT_INSTCMD_HANDLED; } @@ -1037,8 +1039,9 @@ static int instcmd(const char *cmdname, const char *extra) command[0]=UPS_SET_BATTERY_TEST; command[1]=0x00; /* 0 = perform battery test - 1 = force UPS on battery power - 2 = restore standard mode (mains power) */ + * 1 = force UPS on battery power + * 2 = restore standard mode (mains power) + */ send_write_command(command, 2); sleep(15); res = get_answer(answer); @@ -1079,8 +1082,9 @@ static int instcmd(const char *cmdname, const char *extra) command[0]=UPS_SET_BUZZER_MUTE; command[1]=0x00; /* 0 = not muted - 1 = muted - 2 = read current status */ + * 1 = muted + * 2 = read current status + */ command_write_sequence(command, 2, answer); return STAT_INSTCMD_HANDLED; } @@ -1090,8 +1094,9 @@ static int instcmd(const char *cmdname, const char *extra) command[0]=UPS_SET_BUZZER_MUTE; command[1]=0x01; /* 0 = not muted - 1 = muted - 2 = read current status */ + * 1 = muted + * 2 = read current status + */ command_write_sequence(command, 2, answer); return STAT_INSTCMD_HANDLED; } diff --git a/drivers/mge-xml.c b/drivers/mge-xml.c index ab6fb073ea..f4c74e05ab 100644 --- a/drivers/mge-xml.c +++ b/drivers/mge-xml.c @@ -132,7 +132,7 @@ typedef struct { uint32_t xmlflags; /* XML flags (to be used to determine what kind of variable this is */ size_t xmllen; /* length of the XML string */ const char *(*convert)(const char *value); /* conversion function from XML<->NUT value (returns - NULL if no further processing is required) */ + * NULL if no further processing is required) */ } xml_info_t; static const char *online_info(const char *arg_val) diff --git a/drivers/microdowell.c b/drivers/microdowell.c index f4f588cae7..fd522a118a 100644 --- a/drivers/microdowell.c +++ b/drivers/microdowell.c @@ -246,8 +246,8 @@ static unsigned char * CmdSerial(unsigned char *OutBuffer, size_t Len, unsigned { /* FramePointer to valid data! */ p = InpBuff + ups.FramePointer ; - /* p now point to valid data. - check if it is a error code. */ + /* p now points to valid data. + * check if it is a error code. */ ErrCode = CheckErrCode(p) ; if (!ErrCode) { @@ -911,9 +911,9 @@ void upsdrv_initinfo(void) "Unable to detect a Microdowell's Enterprise UPS on port %s\nCheck the cable, port name and try again", device_path); } - /* I set the correspondig UPS variables - They were read in 'detect_hardware()' - some other variables were set in 'detect_hardware()' */ + /* I set the corresponding UPS variables + * They were read in 'detect_hardware()' + * some other variables were set in 'detect_hardware()' */ dstate_setinfo("ups.model", "Enterprise N%s", ups.UpsModel+3) ; dstate_setinfo("ups.power.nominal", "%d", atoi(ups.UpsModel+3) * 100) ; dstate_setinfo("ups.realpower.nominal", "%d", atoi(ups.UpsModel+3) * 60) ; @@ -1056,7 +1056,7 @@ void upsdrv_initups(void) ser_set_speed(upsfd, device_path, B19200) ; /* need to clear RTS and DTR: otherwise with default cable, communication will be problematic - It is the same as removing pin7 from cable (pin 7 is needed for Plug&Play compatibility) */ + * It is the same as removing pin7 from cable (pin 7 is needed for Plug&Play compatibility) */ ser_set_dtr(upsfd, 0); ser_set_rts(upsfd, 0); diff --git a/drivers/netxml-ups.c b/drivers/netxml-ups.c index 20faa09229..f6dd42392b 100644 --- a/drivers/netxml-ups.c +++ b/drivers/netxml-ups.c @@ -423,13 +423,13 @@ void upsdrv_shutdown(void) { /* tell the UPS to shut down, then return - DO NOT SLEEP HERE */ /* maybe try to detect the UPS here, but try a shutdown even if - it doesn't respond at first if possible */ + * it doesn't respond at first if possible */ /* replace with a proper shutdown function */ /* fatalx(EXIT_FAILURE, "shutdown not supported"); */ /* you may have to check the line status since the commands - for toggling power are frequently different for OL vs. OB */ + * for toggling power are frequently different for OL vs. OB */ /* OL: this must power cycle the load if possible */ @@ -840,7 +840,7 @@ static int netxml_alarm_subscribe(const char *page) ne_request_destroy(request); /* due to different formats used by the various NMCs, we need to\ - break up the reply in lines and parse each one separately */ + * break up the reply in lines and parse each one separately */ for (s = strtok(resp_buf, "\r\n"); s != NULL; s = strtok(NULL, "\r\n")) { long long int tmp_port = -1, tmp_secret = -1; upsdebugx(2, "%s: parsing %s", __func__, s); diff --git a/drivers/nutdrv_atcl_usb.c b/drivers/nutdrv_atcl_usb.c index b7745d142a..b51b7fa534 100644 --- a/drivers/nutdrv_atcl_usb.c +++ b/drivers/nutdrv_atcl_usb.c @@ -339,10 +339,10 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev } /* collect the identifying information of this - device. Note that this is safe, because - there's no need to claim an interface for - this (and therefore we do not yet need to - detach any kernel drivers). */ + * device. Note that this is safe, because + * there's no need to claim an interface for + * this (and therefore we do not yet need to + * detach any kernel drivers). */ free(device->Vendor); free(device->Product); diff --git a/drivers/optiups.c b/drivers/optiups.c index 4a81ad1fb5..6a57ad04c8 100644 --- a/drivers/optiups.c +++ b/drivers/optiups.c @@ -101,9 +101,11 @@ enum { typedef struct ezfill_s { const char *cmd; const char *var; - const float scale; /* if 0, no conversion is done and the string - is passed to dstate as is, otherwise a float - conversion with single decimal is applied */ + + /* if scale is 0, no conversion is done and the + * string is passed to dstate as is; otherwise a + * float conversion with single decimal is applied */ + const float scale; } ezfill_t; /* These can be polled right into a string usable by NUT. diff --git a/drivers/richcomm_usb.c b/drivers/richcomm_usb.c index 766e56d8ea..42578d82d2 100644 --- a/drivers/richcomm_usb.c +++ b/drivers/richcomm_usb.c @@ -389,10 +389,10 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev } /* collect the identifying information of this - device. Note that this is safe, because - there's no need to claim an interface for - this (and therefore we do not yet need to - detach any kernel drivers). */ + * device. Note that this is safe, because + * there's no need to claim an interface for + * this (and therefore we do not yet need to + * detach any kernel drivers). */ free(device->Vendor); free(device->Product); diff --git a/drivers/riello_usb.c b/drivers/riello_usb.c index 4e47b6ae4d..c04d411ffa 100644 --- a/drivers/riello_usb.c +++ b/drivers/riello_usb.c @@ -1244,13 +1244,13 @@ void upsdrv_shutdown(void) int retry; /* maybe try to detect the UPS here, but try a shutdown even if - it doesn't respond at first if possible */ + * it doesn't respond at first if possible */ /* replace with a proper shutdown function */ /* you may have to check the line status since the commands - for toggling power are frequently different for OL vs. OB */ + * for toggling power are frequently different for OL vs. OB */ /* OL: this must power cycle the load if possible */ diff --git a/drivers/skel.c b/drivers/skel.c index 4a5cbc6104..2f1e0c2199 100644 --- a/drivers/skel.c +++ b/drivers/skel.c @@ -108,7 +108,7 @@ void upsdrv_shutdown(void) /* tell the UPS to shut down, then return - DO NOT SLEEP HERE */ /* maybe try to detect the UPS here, but try a shutdown even if - it doesn't respond at first if possible */ + * it doesn't respond at first if possible */ /* replace with a proper shutdown function */ @@ -117,7 +117,7 @@ void upsdrv_shutdown(void) set_exit_flag(EF_EXIT_FAILURE); /* you may have to check the line status since the commands - for toggling power are frequently different for OL vs. OB */ + * for toggling power are frequently different for OL vs. OB */ /* OL: this must power cycle the load if possible */ diff --git a/drivers/snmp-ups-helpers.c b/drivers/snmp-ups-helpers.c index 7d46d23366..c0d5fdf921 100644 --- a/drivers/snmp-ups-helpers.c +++ b/drivers/snmp-ups-helpers.c @@ -60,7 +60,7 @@ const char *su_usdate_to_isodate_info_fun(void *raw_date) /* Try to convert from US date string to time */ /* Note strptime returns NULL upon failure, and a ptr to the last - null char of the string upon success. Just try blindly the conversion! */ + * null char of the string upon success. Just try blindly the conversion! */ strptime(usdate, "%m/%d/%Y", &tm); if (strftime(su_scratch_buf, 254, "%F", &tm) != 0) { upsdebugx(3, "%s: successfully reformated: %s", __func__, su_scratch_buf); diff --git a/drivers/tripplite-hid.c b/drivers/tripplite-hid.c index ed93b3dd4d..4a463846f3 100644 --- a/drivers/tripplite-hid.c +++ b/drivers/tripplite-hid.c @@ -248,8 +248,8 @@ static info_lkp_t tripplite_ioamp[] = { /* TRIPPLITE usage table */ static usage_lkp_t tripplite_usage_lkp[] = { /* currently unknown: - 00ff0001, ffff007d, ffff00c0, ffff00c1, ffff00c2, - ffff00c3, ffff00c4, ffff00c5, ffff00d2, ffff0091, ffff00c7 */ + * 00ff0001, ffff007d, ffff00c0, ffff00c1, ffff00c2, + * ffff00c3, ffff00c4, ffff00c5, ffff00d2, ffff0091, ffff00c7 */ { "TLCustom", 0xffff0010 }, { "TLDelayBeforeStartup", 0xffff0056 }, /* in minutes */ @@ -278,7 +278,7 @@ static usage_lkp_t tripplite_usage_lkp[] = { { "TLOutletsStatusMask", 0xffff0096 }, /* it looks like Tripp Lite confused pages 0x84 and 0x85 for the - following 4 items, on some OMNI1000LCD devices. */ + * following 4 items, on some OMNI1000LCD devices. */ { "TLCharging", 0x00840044 }, /* conflicts with HID spec! */ /* conflicts with HID spec (and HP implementation) for TrippLite! * Refer to tripplite_discharging_info */ diff --git a/drivers/tripplitesu.c b/drivers/tripplitesu.c index 56e22f28c6..6f2f8e1050 100644 --- a/drivers/tripplitesu.c +++ b/drivers/tripplitesu.c @@ -310,9 +310,9 @@ static ssize_t do_command(char type, const char *command, const char *parameters upsdebugx(3, "do_command: %" PRIiSIZE " bytes read [%s]", ret, response); /* Tripp Lite pads their string responses with spaces. - I don't like that, so I remove them. This is safe to - do with all responses for this protocol, so I just - do that here. */ + * I don't like that, so I remove them. This is safe to + * do with all responses for this protocol, so I just + * do that here. */ str_rtrim(response, ' '); return ret; @@ -878,7 +878,7 @@ void upsdrv_shutdown(void) printf("Status failed. Assuming it's on battery and trying a shutdown anyway.\n"); auto_reboot(1); /* in case the power is on, tell it to automatically reboot. if - it is off, this has no effect. */ + * it is off, this has no effect. */ snprintf(parm, sizeof(parm), "%d", 1); /* delay before reboot, in minutes */ do_command(SET, TSU_SHUTDOWN_RESTART, parm, NULL); snprintf(parm, sizeof(parm), "%d", 5); /* delay before shutdown, in seconds */ diff --git a/drivers/upscode2.c b/drivers/upscode2.c index 58134b841a..bbbaeb8720 100644 --- a/drivers/upscode2.c +++ b/drivers/upscode2.c @@ -1043,8 +1043,8 @@ static ssize_t upscrecv(char *buf) ssize_t res; /* NOTE: the serial port is set to use Canonical Mode Input Processing, - which means ser_get_buf() either returns one line terminated with - ENDCHAR, an error or times out. */ + * which means ser_get_buf() either returns one line terminated with + * ENDCHAR, an error or times out. */ while (1) { res = ser_get_buf(upsfd, buf, UPSC_BUFLEN, input_timeout_sec, 0); diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index da3672be1d..d469a59a66 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -1779,7 +1779,7 @@ void upsdrv_initups(void) } /* Search for the first supported UPS matching the - regular expression (USB) or device_path (SHUT) */ + * regular expression (USB) or device_path (SHUT) */ ret = comm_driver->open_dev(&udev, &curDevice, subdriver_matcher, &callback); if (ret < 1) fatalx(EXIT_FAILURE, "No matching HID UPS found"); diff --git a/tools/nut-scanner/nut-scanner.c b/tools/nut-scanner/nut-scanner.c index faa696bc5c..4d95e0cc12 100644 --- a/tools/nut-scanner/nut-scanner.c +++ b/tools/nut-scanner/nut-scanner.c @@ -1610,8 +1610,8 @@ int main(int argc, char *argv[]) # if (defined HAVE_SEMAPHORE_UNNAMED) || (defined HAVE_SEMAPHORE_NAMED) /* FIXME: Currently sem_init already done on nutscan-init for lib need. - We need to destroy it before re-init. We currently can't change "sem value" - on lib (need to be thread safe). */ + * We need to destroy it before re-init. We currently can't change "sem value" + * on lib (need to be thread safe). */ current_sem = nutscan_semaphore(); # ifdef HAVE_SEMAPHORE_UNNAMED sem_destroy(current_sem); diff --git a/tools/nut-scanner/nutscan-ip.c b/tools/nut-scanner/nutscan-ip.c index 60ee7b5c8b..6d9eff1e55 100644 --- a/tools/nut-scanner/nutscan-ip.c +++ b/tools/nut-scanner/nutscan-ip.c @@ -465,7 +465,7 @@ char * nutscan_ip_iter_inc(nutscan_ip_iter_t * ip) return NULL; } /* increment the address (need to pass address in host - byte order, then pass back in network byte order */ + * byte order, then pass back in network byte order */ ip->start.s_addr = htonl((ntohl(ip->start.s_addr) + 1)); if (ntop(&ip->start, host, sizeof(host)) != 0) { diff --git a/tools/nut-scanner/scan_avahi.c b/tools/nut-scanner/scan_avahi.c index 4760368c15..a844e0b337 100644 --- a/tools/nut-scanner/scan_avahi.c +++ b/tools/nut-scanner/scan_avahi.c @@ -508,9 +508,9 @@ static void browse_callback( /* upsdebugx(1, "%s: "(Browser) NEW: service '%s' of type '%s' in domain '%s'", __func__, name, type, domain); */ /* We ignore the returned resolver object. In the callback - function we free it. If the server is terminated before - the callback function is called the server will free - the resolver for us. */ + * function we free it. If the server is terminated before + * the callback function is called the server will free + * the resolver for us. */ #if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_ASSIGN_ENUM) # pragma GCC diagnostic push From 60254cec5d7ee48dbd3c9b03fdff25e5c7aedf2d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 12:10:11 +0100 Subject: [PATCH 058/198] drivers/huawei-ups2000.c: use sizeof not fixed number for snprintf() Signed-off-by: Jim Klimov --- drivers/huawei-ups2000.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/huawei-ups2000.c b/drivers/huawei-ups2000.c index 0a792968c1..a2ee53fb47 100644 --- a/drivers/huawei-ups2000.c +++ b/drivers/huawei-ups2000.c @@ -983,7 +983,7 @@ static int ups2000_update_alarm(void) alarm_count++; - gotlen = snprintf(alarm_buf, 128, "(ID %02d/%02d): %s!", + gotlen = snprintf(alarm_buf, sizeof(alarm_buf), "(ID %02d/%02d): %s!", ups2000_alarm[i].alarm_id, ups2000_alarm[i].alarm_cause_id, ups2000_alarm[i].alarm_name); @@ -1073,7 +1073,7 @@ static int ups2000_update_alarm(void) if (alarm_count > 0) { /* append this to the alarm string as a friendly reminder */ - int gotlen = snprintf(alarm_buf, 128, "Check log for details!"); + int gotlen = snprintf(alarm_buf, sizeof(alarm_buf), "Check log for details!"); if (gotlen < 0 || (uintmax_t)gotlen > SIZE_MAX) { fatalx(EXIT_FAILURE, "alarm_buf preparation over/under-flow!"); @@ -1085,8 +1085,9 @@ static int ups2000_update_alarm(void) /* if the alarm string is too long, replace it with this */ if (all_alarms_len + 1 > ST_MAX_VALUE_LEN) { alarm_init(); /* discard all original alarms */ - snprintf(alarm_buf, 128, "UPS has %d alarms in effect, " - "check log for details!", alarm_count); + snprintf(alarm_buf, sizeof(alarm_buf), + "UPS has %d alarms in effect, " + "check log for details!", alarm_count); alarm_set(alarm_buf); } From 7301498e50c9386edfc545d5bc553824249807db Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 13:36:17 +0100 Subject: [PATCH 059/198] *.{c,h}: rectify indentations and line-wrapping in if/for/while constructs Signed-off-by: Jim Klimov --- clients/upsclient.c | 6 ++--- clients/upslog.c | 35 +++++++++++++++++------------- common/common.c | 18 ++++++++------- common/strptime.c | 8 +++---- drivers/al175.c | 6 +++-- drivers/apcsmart.c | 9 +++++--- drivers/dstate.c | 47 +++++++++++++++++++++------------------- drivers/generic_modbus.c | 4 ++-- drivers/huawei-ups2000.c | 13 ++++++----- drivers/liebert-esp2.c | 8 +++---- drivers/nutdrv_hashx.c | 10 +++++---- drivers/pijuice.c | 26 +++++++++++----------- drivers/powercom.c | 19 ++++++++-------- drivers/powerp-bin.c | 6 ++--- drivers/snmp-ups.c | 26 ++++++++++++---------- drivers/tripplite_usb.c | 6 +++-- drivers/tripplitesu.c | 8 +++++-- drivers/usb-common.c | 7 +++--- server/upsd.c | 4 ++-- 19 files changed, 148 insertions(+), 118 deletions(-) diff --git a/clients/upsclient.c b/clients/upsclient.c index b72d1c36b7..baaeae6fdf 100644 --- a/clients/upsclient.c +++ b/clients/upsclient.c @@ -1167,9 +1167,9 @@ int upscli_tryconnect(UPSCONN_t *ups, const char *host, uint16_t port, int flags close(sock_fd); /* if timeout, break out so client can continue */ /* match Linux behavior that updates timeout struct */ - if (timeout != NULL && - ups->upserror == UPSCLI_ERR_CONNFAILURE && - ups->syserrno == ETIMEDOUT + if (timeout != NULL + && ups->upserror == UPSCLI_ERR_CONNFAILURE + && ups->syserrno == ETIMEDOUT ) { const char *addrstr = xinet_ntopAI(ai); upslogx(LOG_WARNING, "%s: Connection to host timed out: '%s'", diff --git a/clients/upslog.c b/clients/upslog.c index 16b5791cd4..8f957fddf9 100644 --- a/clients/upslog.c +++ b/clients/upslog.c @@ -114,9 +114,10 @@ static void reopen_log(void) { struct logtarget_t *p; - for (p = logfile_anchor; - p != NULL; - p = p->next + for ( + p = logfile_anchor; + p != NULL; + p = p->next ) { /* Never opened, e.g. removed asterisk entry */ if (!p->logfile) @@ -748,9 +749,10 @@ int main(int argc, char **argv) fatalx(EXIT_FAILURE, "No UPS defined for monitoring - use -s -l , or use -m ; consider -m '*,-' to view updates of all known local devices"); /* Split the system specs in a common fashion for tuples and legacy args */ - for (monhost_ups_current = monhost_ups_anchor, monhost_ups_prev = NULL; - monhost_ups_current != NULL; - monhost_ups_current = monhost_ups_current->next + for ( + monhost_ups_current = monhost_ups_anchor, monhost_ups_prev = NULL; + monhost_ups_current != NULL; + monhost_ups_current = monhost_ups_current->next ) { if (upscli_splitname(monhost_ups_current->monhost, &(monhost_ups_current->upsname), &(monhost_ups_current->hostname), &(monhost_ups_current->port)) != 0) { fatalx(EXIT_FAILURE, "Error: invalid UPS definition. Required format: upsname[@hostname[:port]]\n"); @@ -880,9 +882,10 @@ int main(int argc, char **argv) fatalx(EXIT_FAILURE, "No UPS defined for monitoring - use -s -l , or use -m ; consider -m '*,-' to view updates of all known local devices"); /* Report the logged systems, open the log files as needed */ - for (monhost_ups_current = monhost_ups_anchor; - monhost_ups_current != NULL; - monhost_ups_current = monhost_ups_current->next + for ( + monhost_ups_current = monhost_ups_anchor; + monhost_ups_current != NULL; + monhost_ups_current = monhost_ups_current->next ) { printf("logging status of %s to %s (%is intervals)\n", monhost_ups_current->monhost, @@ -969,9 +972,10 @@ int main(int argc, char **argv) upsnotify(NOTIFY_STATE_READY, NULL); } - for (monhost_ups_current = monhost_ups_anchor; - monhost_ups_current != NULL; - monhost_ups_current = monhost_ups_current->next + for ( + monhost_ups_current = monhost_ups_anchor; + monhost_ups_current != NULL; + monhost_ups_current = monhost_ups_current->next ) { /* reconnect if necessary */ if (upscli_fd(monhost_ups_current->ups) < 0) { @@ -1003,9 +1007,10 @@ int main(int argc, char **argv) upslogx(LOG_INFO, "Signal %d: exiting", exit_flag); upsnotify(NOTIFY_STATE_STOPPING, "Signal %d: exiting", exit_flag); - for (monhost_ups_current = monhost_ups_anchor; - monhost_ups_current != NULL; - monhost_ups_current = monhost_ups_current->next + for ( + monhost_ups_current = monhost_ups_anchor; + monhost_ups_current != NULL; + monhost_ups_current = monhost_ups_current->next ) { /* we might have several systems logged into same file; * take care to not close stdout though */ diff --git a/common/common.c b/common/common.c index 10fca114e3..e3f3631349 100644 --- a/common/common.c +++ b/common/common.c @@ -1542,8 +1542,8 @@ int compareprocnames(pid_t pid, const char *procname, const char **prognames) size_t dot = progbasenamedot[i] ? progbasenamedot[i] : procbasenamedot; /* Optimize away procbasename comparisons beyond first */ - if (!strncasecmp(progbasenames[i], procbasename, dot - 1) && - ( (progbasenamedot[i] && !strcasecmp(progbasenames[i] + progbasenamedot[i], ".exe")) + if (!strncasecmp(progbasenames[i], procbasename, dot - 1) + && ( (progbasenamedot[i] && !strcasecmp(progbasenames[i] + progbasenamedot[i], ".exe")) || (i == 0 && procbasenamedot && !strcasecmp(procbasename + procbasenamedot, ".exe")) ) ) { ret = 5; @@ -1868,8 +1868,8 @@ char * getfullpath(char * relative_path) upsdebugx(6, "%s: prefix_in_buf:\t'%s'", __func__, NUT_STRARG(prefix_in_buf)); /* Did we find the prefix and is it followed by some slash? */ - if (prefix_in_buf && - ( *(prefix_in_buf + len_PREFIX) == '/' + if (prefix_in_buf + && ( *(prefix_in_buf + len_PREFIX) == '/' || *(prefix_in_buf + len_PREFIX) == '\\') ) { /* Make the path relative @@ -2253,9 +2253,11 @@ pid_t parsepidfile(const char *pidfn) * for the first time and no opponent PID file exists, * so the cut-off verbosity is higher. */ - if (nut_debug_level > 0 || - nut_sendsignal_debug_level >= NUT_SENDSIGNAL_DEBUG_LEVEL_FOPEN_PIDFILE) + if (nut_debug_level > 0 + || nut_sendsignal_debug_level >= NUT_SENDSIGNAL_DEBUG_LEVEL_FOPEN_PIDFILE + ) { upslog_with_errno(LOG_NOTICE, "fopen %s", pidfn); + } return -3; } @@ -3278,8 +3280,8 @@ int upsnotify(upsnotify_state_t state, const char *fmt, ...) char *s = getenv("NUT_QUIET_INIT_UPSNOTIFY"); /* FIXME: Make an INVERTED server/conf.c::parse_boolean() reusable */ - if (s && *s && - ( (!strcasecmp(s, "false")) || (!strcasecmp(s, "off")) || (!strcasecmp(s, "no")) || (!strcasecmp(s, "0"))) + if (s && *s + && ( (!strcasecmp(s, "false")) || (!strcasecmp(s, "off")) || (!strcasecmp(s, "no")) || (!strcasecmp(s, "0")) ) ) { upsdebugx(1, "Caller WANTS to see all these messages: NUT_QUIET_INIT_UPSNOTIFY=%s", NUT_STRARG(s)); } else { diff --git a/common/strptime.c b/common/strptime.c index 8909aea6cf..3480aa42b3 100644 --- a/common/strptime.c +++ b/common/strptime.c @@ -316,8 +316,8 @@ again: switch (c = *fmt++) { sse *= 10; sse += *bp++ - '0'; rulim /= 10; - } while (((uint64_t)sse * 10 <= TIME_MAX) && - rulim && *bp >= '0' && *bp <= '9'); + } while (((uint64_t)sse * 10 <= TIME_MAX) + && rulim && *bp >= '0' && *bp <= '9'); if (sse < 0 || (uint64_t)sse > TIME_MAX) { bp = NULL; @@ -496,8 +496,8 @@ again: switch (c = *fmt++) { continue; } - if ((*bp >= 'A' && *bp <= 'I') || - (*bp >= 'L' && *bp <= 'Y') + if ((*bp >= 'A' && *bp <= 'I') + || (*bp >= 'L' && *bp <= 'Y') ) { #ifdef TM_GMTOFF /* Argh! No 'J'! */ diff --git a/drivers/al175.c b/drivers/al175.c index fff1bf2d53..026bd9f1b0 100644 --- a/drivers/al175.c +++ b/drivers/al175.c @@ -1003,9 +1003,11 @@ static int al175_read(byte_t *dst, size_t addr, size_t count) if (err==-1) return -1; - if ((rx_data.end - rx_data.begin) < 0 || - (size_t)(rx_data.end - rx_data.begin) != count) + if ((rx_data.end - rx_data.begin) < 0 + || (size_t)(rx_data.end - rx_data.begin) != count + ) { return -1; + } if ( (io.addr != addr) || (io.len != count) ) { upsdebugx(3, "%s: io_head mismatch\t(%" PRIxSIZE ",%" PRIxSIZE " != %" PRIxSIZE ",%" PRIxSIZE ")", diff --git a/drivers/apcsmart.c b/drivers/apcsmart.c index e0471f3f8a..1ceb89a341 100644 --- a/drivers/apcsmart.c +++ b/drivers/apcsmart.c @@ -95,10 +95,13 @@ static apc_vartab_t *vt_lookup_char(char cmdchar) { int i; - for (i = 0; apc_vartab[i].name != NULL; i++) - if ((apc_vartab[i].flags & APC_PRESENT) && - apc_vartab[i].cmd == cmdchar) + for (i = 0; apc_vartab[i].name != NULL; i++) { + if ((apc_vartab[i].flags & APC_PRESENT) + && apc_vartab[i].cmd == cmdchar + ) { return &apc_vartab[i]; + } + } return NULL; } diff --git a/drivers/dstate.c b/drivers/dstate.c index 5b0a13e2d5..d368ce006f 100644 --- a/drivers/dstate.c +++ b/drivers/dstate.c @@ -2254,37 +2254,40 @@ int dstate_detect_phasecount( dstate_getinfo_nonzero(v0, "voltage"); dstate_getinfo_nonzero(c0, "current"); - if ( (v1 && v2 && !v3) || - (v1n && v2n && !v3n) || - (c1 && c2 && !c3) || - (v12 && !v23 && !v31) ) { + if ( (v1 && v2 && !v3) + || (v1n && v2n && !v3n) + || (c1 && c2 && !c3) + || (v12 && !v23 && !v31) + ) { upsdebugx(5, "%s(): determined a 2-phase case", __func__); *num_phases = 2; *inited_phaseinfo = 1; detected_phaseinfo = 1; - } else if ( (v1 && v2 && v3) || - (v1n && v2n && v3n) || - (c1 && (c2 || c3)) || - (c2 && (c1 || c3)) || - (c3 && (c1 || c2)) || - v12 || v23 || v31 ) { + } else if ( (v1 && v2 && v3) + || (v1n && v2n && v3n) + || (c1 && (c2 || c3)) + || (c2 && (c1 || c3)) + || (c3 && (c1 || c2)) + || v12 || v23 || v31 + ) { upsdebugx(5, "%s(): determined a 3-phase case", __func__); *num_phases = 3; *inited_phaseinfo = 1; detected_phaseinfo = 1; } else if ( /* We definitely have only one non-zero line */ - !v12 && !v23 && !v31 && ( - (c0 && !c1 && !c2 && !c3) || - (v0 && !v1 && !v2 && !v3) || - (c1 && !c2 && !c3) || - (!c1 && c2 && !c3) || - (!c1 && !c2 && c3) || - (v1 && !v2 && !v3) || - (!v1 && v2 && !v3) || - (!v1 && !v2 && v3) || - (v1n && !v2n && !v3n) || - (!v1n && v2n && !v3n) || - (!v1n && !v2n && v3n) ) ) { + !v12 && !v23 && !v31 + && ( (c0 && !c1 && !c2 && !c3) + || (v0 && !v1 && !v2 && !v3) + || (c1 && !c2 && !c3) + || (!c1 && c2 && !c3) + || (!c1 && !c2 && c3) + || (v1 && !v2 && !v3) + || (!v1 && v2 && !v3) + || (!v1 && !v2 && v3) + || (v1n && !v2n && !v3n) + || (!v1n && v2n && !v3n) + || (!v1n && !v2n && v3n) ) + ) { *num_phases = 1; *inited_phaseinfo = 1; detected_phaseinfo = 1; diff --git a/drivers/generic_modbus.c b/drivers/generic_modbus.c index 234f5a29e5..bf69925ae8 100644 --- a/drivers/generic_modbus.c +++ b/drivers/generic_modbus.c @@ -582,8 +582,8 @@ int upscmd(const char *cmd, const char *arg) if (!strcasecmp(cmd, "load.off")) { upslog_INSTCMD_POWERSTATE_CHANGE(cmd, arg); - if (sigar[FSD_T].addr != NOTUSED && - (sigar[FSD_T].type == COIL || sigar[FSD_T].type == HOLDING) + if (sigar[FSD_T].addr != NOTUSED + && (sigar[FSD_T].type == COIL || sigar[FSD_T].type == HOLDING) ) { data = 1 ^ sigar[FSD_T].noro; rval = register_write(mbctx, sigar[FSD_T].addr, sigar[FSD_T].type, &data); diff --git a/drivers/huawei-ups2000.c b/drivers/huawei-ups2000.c index a2ee53fb47..f51c8acdd5 100644 --- a/drivers/huawei-ups2000.c +++ b/drivers/huawei-ups2000.c @@ -748,8 +748,8 @@ static int ups2000_update_status(void) * if the register is equal to the "val" we are looking * for, or if register has its n-th "bit" set... */ - if ((flag[j].val != -1 && flag[j].val == val) || - (flag[j].bit != -1 && CHECK_BIT(val, flag[j].bit)) + if ((flag[j].val != -1 && flag[j].val == val) + || (flag[j].bit != -1 && CHECK_BIT(val, flag[j].bit)) ) { /* if it has a corresponding status flag */ if (strlen(flag[j].status_name) != 0) @@ -1002,8 +1002,8 @@ static int ups2000_update_alarm(void) * Log the warning only if it's a new alarm, or if a long time * has paseed since we first warned it. */ - if (!ups2000_alarm[i].active || - difftime(now, alarm_logged_since) >= UPS2000_LOG_INTERVAL + if (!ups2000_alarm[i].active + || difftime(now, alarm_logged_since) >= UPS2000_LOG_INTERVAL ) { int loglevel; const char *alarm_word; @@ -2019,8 +2019,9 @@ static int ups2000_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *des * this register returns invalid values. This is a known problem * and it's not fatal, so we use LOG_INFO. */ - if (retry_status == RETRY_ENABLE && - addr == 12002 && (dest[0] < 2 || dest[0] > 5) + if (retry_status == RETRY_ENABLE + && addr == 12002 + && (dest[0] < 2 || dest[0] > 5) ) { upslogx(LOG_INFO, "Battery status has a non-fatal read failure, it's usually harmless. Retrying... "); sleep(1); diff --git a/drivers/liebert-esp2.c b/drivers/liebert-esp2.c index 4672ed5fd6..68e64826cd 100644 --- a/drivers/liebert-esp2.c +++ b/drivers/liebert-esp2.c @@ -525,10 +525,10 @@ void upsdrv_shutdown(void) char reply[8]; - if(!(do_command(cmd_setOutOffMode, reply, 8) != -1) && - (do_command(cmd_setOutOffDelay, reply, 8) != -1) && - (do_command(cmd_sysLoadKey, reply, 6) != -1) && - (do_command(cmd_shutdown, reply, 8) != -1) + if(!(do_command(cmd_setOutOffMode, reply, 8) != -1) + && (do_command(cmd_setOutOffDelay, reply, 8) != -1) + && (do_command(cmd_sysLoadKey, reply, 6) != -1) + && (do_command(cmd_shutdown, reply, 8) != -1) ) { upslogx(LOG_ERR, "Failed to shutdown UPS"); if (handling_upsdrv_shutdown > 0) diff --git a/drivers/nutdrv_hashx.c b/drivers/nutdrv_hashx.c index 08c316af5d..41a4fd68bb 100644 --- a/drivers/nutdrv_hashx.c +++ b/drivers/nutdrv_hashx.c @@ -284,10 +284,12 @@ void upsdrv_initinfo(void) if ((transferred = ser_send(upsfd, COMMAND_GET_SESSION_HASH"%c", ENDCHAR)) != 4) { fatalx(EXIT_FAILURE, "%s: Failed to get session hash", __func__); } - if ((transferred = hashx_recv(buf, sizeof(buf))) != strlen(SESSION_HASH) + 1 || - (transferred > 0 && strncmp(buf, "#"SESSION_HASH, sizeof(buf)) != 0)) { - fatalx(EXIT_FAILURE, "%s: unexpected hash protocol response: %s", - __func__, buf); + if ((transferred = hashx_recv(buf, sizeof(buf))) != strlen(SESSION_HASH) + 1 + || (transferred > 0 && strncmp(buf, "#"SESSION_HASH, sizeof(buf)) != 0) + ) { + fatalx(EXIT_FAILURE, + "%s: unexpected hash protocol response: %s", + __func__, buf); } /* XXX: Maybe now repeat the same with a random value, without checking diff --git a/drivers/pijuice.c b/drivers/pijuice.c index bc815ec5d7..21af182b1d 100644 --- a/drivers/pijuice.c +++ b/drivers/pijuice.c @@ -410,9 +410,9 @@ static void get_status(void) upsdebugx(1, "Power Input 5v: UNKNOWN"); } - if ( batteryStatus == BATT_NORMAL || - batteryStatus == BATT_CHARGING_FROM_IN || - batteryStatus == BATT_CHARGING_FROM_5V ) + if ( batteryStatus == BATT_NORMAL + || batteryStatus == BATT_CHARGING_FROM_IN + || batteryStatus == BATT_CHARGING_FROM_5V ) { get_charge_level_hi_res(); @@ -432,12 +432,12 @@ static void get_status(void) status_set("RB"); } - if ( batteryStatus <= BATT_NOT_PRESENT && - powerInput <= POWER_PRESENT && - powerInput5vIo <= POWER_PRESENT ) + if ( batteryStatus <= BATT_NOT_PRESENT + && powerInput <= POWER_PRESENT + && powerInput5vIo <= POWER_PRESENT ) { - if ( powerInput == POWER_NOT_PRESENT && - ( powerInput5vIo != POWER_NOT_PRESENT )) + if ( powerInput == POWER_NOT_PRESENT + && ( powerInput5vIo != POWER_NOT_PRESENT )) { if ( usb_power != 1 || gpio_power != 0 ) { @@ -461,9 +461,9 @@ static void get_status(void) dstate_setinfo( "battery.charger.status", "%s", "resting" ); } } - else if ( powerInput5vIo == POWER_NOT_PRESENT && - ( powerInput != POWER_NOT_PRESENT && - powerInput <= POWER_PRESENT )) + else if ( powerInput5vIo == POWER_NOT_PRESENT + && powerInput != POWER_NOT_PRESENT + && powerInput <= POWER_PRESENT ) { if ( gpio_power != 1 || usb_power != 0 ) { @@ -487,8 +487,8 @@ static void get_status(void) dstate_setinfo( "battery.charger.status", "%s", "resting" ); } } - else if ( ( powerInput != POWER_NOT_PRESENT && powerInput <= POWER_PRESENT ) && - ( powerInput5vIo != POWER_NOT_PRESENT && powerInput5vIo <= POWER_PRESENT )) + else if ( ( powerInput != POWER_NOT_PRESENT && powerInput <= POWER_PRESENT ) + && ( powerInput5vIo != POWER_NOT_PRESENT && powerInput5vIo <= POWER_PRESENT )) { if ( usb_power != 1 || gpio_power != 1 ) { diff --git a/drivers/powercom.c b/drivers/powercom.c index 9426f2c788..671ca2d630 100644 --- a/drivers/powercom.c +++ b/drivers/powercom.c @@ -378,12 +378,12 @@ static int validate_raw_data (void) num_of_tests = sizeof types[0].validation / sizeof types[0].validation[0]; - for (i = 0; - i < num_of_tests && - raw_data[ - types[type].validation[i].index_of_byte] == - types[type].validation[i].required_value; - i++) ; + for ( + i = 0; + i < num_of_tests + && raw_data[types[type].validation[i].index_of_byte] + == types[type].validation[i].required_value; + i++) ; return (i < num_of_tests) ? 1 : 0; } @@ -882,9 +882,10 @@ void upsdrv_initups(void) /* get and check type */ if (testvar("type")) { - for (i = 0; - i < NUM_OF_SUBTYPES && strcmp(types[i].name, getval("type")); - i++) ; + for ( + i = 0; + i < NUM_OF_SUBTYPES && strcmp(types[i].name, getval("type")); + i++) ; if (i >= NUM_OF_SUBTYPES) { printf("Given UPS type '%s' isn't valid!\n", getval("type")); exit (1); diff --git a/drivers/powerp-bin.c b/drivers/powerp-bin.c index 67d2d94be9..f7105c9c93 100644 --- a/drivers/powerp-bin.c +++ b/drivers/powerp-bin.c @@ -274,9 +274,9 @@ static int powpan_instcmd(const char *cmdname, const char *extra) upslog_INSTCMD_POWERSTATE_CHECKED(cmdname, extra); ret = powpan_command(cmdtab[i].command, cmdtab[i].len); assert(cmdtab[i].len < SSIZE_MAX); - if (ret >= 0 && - (ret == (ssize_t)(cmdtab[i].len - 1)) && - (!memcmp(powpan_answer, cmdtab[i].command, cmdtab[i].len - 1)) + if (ret >= 0 + && (ret == (ssize_t)(cmdtab[i].len - 1)) + && (!memcmp(powpan_answer, cmdtab[i].command, cmdtab[i].len - 1)) ) { return STAT_INSTCMD_HANDLED; } diff --git a/drivers/snmp-ups.c b/drivers/snmp-ups.c index 961ce346cd..72c93f04c6 100644 --- a/drivers/snmp-ups.c +++ b/drivers/snmp-ups.c @@ -1380,9 +1380,10 @@ static struct snmp_pdu **nut_snmp_walk(const char *OID, int max_iteration) * SNMPv1). This allows to proceed interpreting large * responses when one entry in the middle is rejectable. */ - if (response->variables->type == SNMP_NOSUCHOBJECT || - response->variables->type == SNMP_NOSUCHINSTANCE || - response->variables->type == SNMP_ENDOFMIBVIEW) { + if (response->variables->type == SNMP_NOSUCHOBJECT + || response->variables->type == SNMP_NOSUCHINSTANCE + || response->variables->type == SNMP_ENDOFMIBVIEW + ) { upslogx(LOG_WARNING, "[%s] Warning: type error exception (OID = %s)", upsname?upsname:device_name, OID); snmp_free_pdu(response); @@ -2411,9 +2412,13 @@ const char *su_find_infoval(info_lkp_t *oid2info, void *raw_value) #endif /* WITH_SNMP_LKP_FUN */ /* Otherwise, use the simple values mapping */ - for (info_lkp = oid2info; (info_lkp != NULL) && - (info_lkp->info_value != NULL) && (strcmp(info_lkp->info_value, "NULL")); info_lkp++) { - + for ( + info_lkp = oid2info; + (info_lkp != NULL) + && (info_lkp->info_value != NULL) + && (strcmp(info_lkp->info_value, "NULL")); + info_lkp++ + ) { if (info_lkp->oid_value == value) { upsdebugx(1, "%s: found %s (value: %ld)", __func__, info_lkp->info_value, value); @@ -3451,11 +3456,10 @@ bool_t snmp_ups_walk(int mode) /* Set default value if we cannot fetch it * and set static flag on this element. * Not applicable to outlets (need SU_FLAG_STATIC tagging) */ - if ( - (su_info_p->flags & SU_FLAG_ABSENT) - && !(su_info_p->flags & SU_OUTLET) - && !(su_info_p->flags & SU_OUTLET_GROUP) - && !(su_info_p->flags & SU_AMBIENT_TEMPLATE)) + if ( (su_info_p->flags & SU_FLAG_ABSENT) + && !(su_info_p->flags & SU_OUTLET) + && !(su_info_p->flags & SU_OUTLET_GROUP) + && !(su_info_p->flags & SU_AMBIENT_TEMPLATE)) { if (mode == SU_WALKMODE_INIT) { diff --git a/drivers/tripplite_usb.c b/drivers/tripplite_usb.c index 1e5661be27..e660fd97b5 100644 --- a/drivers/tripplite_usb.c +++ b/drivers/tripplite_usb.c @@ -1600,8 +1600,10 @@ void upsdrv_updateinfo(void) /* - * - * - * - * - * - * - * - * - * - * - * - * - * - * - */ - if( tl_model == TRIPP_LITE_OMNIVS || tl_model == TRIPP_LITE_OMNIVS_2001 || - is_smart_protocol() ) { + if (tl_model == TRIPP_LITE_OMNIVS + || tl_model == TRIPP_LITE_OMNIVS_2001 + || is_smart_protocol() + ) { /* dq ~= sqrt(dV) is a reasonable approximation * Results fit well against the discrete function used in the Tripp Lite * source, but give a continuous result. */ diff --git a/drivers/tripplitesu.c b/drivers/tripplitesu.c index 6f2f8e1050..a9a8e42b3a 100644 --- a/drivers/tripplitesu.c +++ b/drivers/tripplitesu.c @@ -794,9 +794,13 @@ void upsdrv_updateinfo(void) if (ptr) { dstate_setinfo("battery.charge", "%d", atoi(ptr)); ptr2 = getval("lowbatt"); - if (ptr2 && atoi(ptr2) > 0 && atoi(ptr2) <= 99 && - atoi(ptr) <= atoi(ptr2)) + if (ptr2 + && atoi(ptr2) > 0 + && atoi(ptr2) <= 99 + && atoi(ptr) <= atoi(ptr2) + ) { low_battery = 1; + } } ptr = field(response, 6); if (ptr) diff --git a/drivers/usb-common.c b/drivers/usb-common.c index 7a7051c02e..36cb74cbb4 100644 --- a/drivers/usb-common.c +++ b/drivers/usb-common.c @@ -29,9 +29,10 @@ int is_usb_device_supported(usb_device_id_t *usb_device_id_list, USBDevice_t *de upsdebugx(3, "%s: checking if this driver can support USB device VID:PID 0x%04X:0x%04X", __func__, (unsigned int)device->VendorID, (unsigned int)device->ProductID); - for (usbdev = usb_device_id_list; - (usbdev->vendorID != 0 || usbdev->productID != 0 || usbdev->fun != NULL); - usbdev++ + for ( + usbdev = usb_device_id_list; + (usbdev->vendorID != 0 || usbdev->productID != 0 || usbdev->fun != NULL); + usbdev++ ) { upsdebugx(4, "%s: checking table entry for VID:PID 0x%04X:0x%04X " "(custom init handler is%s available)", diff --git a/server/upsd.c b/server/upsd.c index d730d8d4af..145979a7a5 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -1085,8 +1085,8 @@ void server_load(void) return; /* check for edge cases we can let slide */ - if ( (listenersTotal - listenersValid) == - (listenersTotalLocalhost - listenersValidLocalhost) + if ( (listenersTotal - listenersValid) + == (listenersTotalLocalhost - listenersValidLocalhost) ) { /* Note that we can also get into this situation * when "dual-stack" IPv6 listener also handles From c5b6724a8ea8a589089a5912a5799ef8659d4139 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 11:49:24 +0100 Subject: [PATCH 060/198] drivers/apcsmart.c: neuter upsdrv_help(): it brings no new value now that all NUT programs print references to on-line and man page docs Signed-off-by: Jim Klimov --- drivers/apcsmart.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/apcsmart.c b/drivers/apcsmart.c index 1ceb89a341..b0f43e1222 100644 --- a/drivers/apcsmart.c +++ b/drivers/apcsmart.c @@ -4,7 +4,7 @@ * Copyright (C) 1999 Russell Kroll * (C) 2000 Nigel Metheringham * (C) 2011+ Michal Soltys - * (C) 2024 Jim Klimov + * (C) 2024-2026 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 @@ -37,7 +37,7 @@ #include "apcsmart_tabs.h" #define DRIVER_NAME "APC Smart protocol driver" -#define DRIVER_VERSION "3.37" +#define DRIVER_VERSION "3.38" #ifdef WIN32 # ifndef ECANCELED @@ -2164,11 +2164,6 @@ void upsdrv_tweak_prognames(void) void upsdrv_help(void) { - printf( - "\nFor detailed information, please refer to:\n" - " - apcsmart(8)\n" - " - https://www.networkupstools.org/docs/man/apcsmart.html\n" - ); } void upsdrv_initups(void) From e62f741b5c805e1fbf17c586d625ed87efae0abb Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 10:19:00 +0100 Subject: [PATCH 061/198] .github/pull_request_template.md: add a note to disclose AI and other coding aid usage, and that a human is ultimately responsible for the contributions Signed-off-by: Jim Klimov --- .github/pull_request_template.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 3087cbeb6a..cd192b46de 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -27,6 +27,12 @@ of "real" changes in the other commits. Similarly for typo fixes in comments or text documents. +- [ ] Use of coding helper tools and AI should be disclosed in the commit + or PR comments (it is interesting to know which ones do a decent job). + As with other contributions, a human is responsible and thanked for the + quality and content of the change, and is presumed to have the right to + post that code to be published further under the project's license terms. + - [ ] Please star NUT on GitHub, this helps with sponsorships! ;) ## Frequent "underwater rocks" for driver addition/update PRs From 6f1e30e0dcd7fa08dc44dfb8ac8b42d1e98f8ca4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 10:18:07 +0100 Subject: [PATCH 062/198] .github/pull_request_template.md: update notes about ci_build.sh, add NEWS/UPGRADING adoc bumps Signed-off-by: Jim Klimov --- .github/pull_request_template.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index cd192b46de..a381dad424 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -13,6 +13,11 @@ to look out for. PRs to update this template are also welcome :) * Local build iterations can be augmented with the ci_build.sh script. + Note that if your system has both GCC and CLANG, they can expose different + kinds of issues in their static analysis warnings, so incantations like + `CC=clang CXX=clang++ ./ci_build.sh` or `BUILD_TYPE=fightwarn ./ci_build.sh` + (to iterate a matrix of some build dependency combos and compilers) can + be useful. --> ## General points @@ -98,6 +103,10 @@ Also note below, a point about PR posting for NUT DDL ## General documentation updates +- [ ] Added a bullet point into `NEWS.adoc`, possibly also `UPGRADING.adoc` + if there is something packagers or custom-build users should take into + account (new driver categories, configuration options, dependencies...) + - [ ] Updated `docs/acknowledgements.txt` (for vendor-backed device support) - [ ] Added or updated manual page information in `docs/man/*.txt` files From 413c1b32fa6a1baac96418510651d28d79aaa6a7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 09:55:09 +0100 Subject: [PATCH 063/198] scripts/obs/_config: Debian Next builders can not choose between libselinux1-dev (which provides libselinux-dev) and requested libselinux-dev (as dependency of libgio/libmount) so need a nudge [#3293] Signed-off-by: Jim Klimov --- scripts/obs/_config | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/obs/_config b/scripts/obs/_config index 139af5ab1d..4d6a97fba5 100644 --- a/scripts/obs/_config +++ b/scripts/obs/_config @@ -4,6 +4,7 @@ # Unambiguous preference if "Requires: (A or B)" offered both hits: Prefer: libusbx-devel Prefer: libusb-1.0-dev +Prefer: libselinux-dev Prefer: neon-devel Prefer: util-linux From cba82b35bb281a963aadd73027e387bcdf3ac90a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 13:45:50 +0100 Subject: [PATCH 064/198] tools/nut-scanner/nutscan-device.h: comment the added meaning of TYPE_END in nutscan_device_type_t as the array size definition Signed-off-by: Jim Klimov --- tools/nut-scanner/nutscan-device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/nut-scanner/nutscan-device.h b/tools/nut-scanner/nutscan-device.h index 26f47d2ac6..2e536c7294 100644 --- a/tools/nut-scanner/nutscan-device.h +++ b/tools/nut-scanner/nutscan-device.h @@ -55,7 +55,7 @@ typedef enum nutscan_device_type { TYPE_IPMI, TYPE_AVAHI, TYPE_EATON_SERIAL, - TYPE_END + TYPE_END /* Sentinel; numeric value serves as array size at compile time */ } nutscan_device_type_t; /** Device type -> string mapping */ From 7bc59e8be06008e69cf0de34023cc694e3f52c04 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 09:10:52 +0100 Subject: [PATCH 065/198] tools/nut-scanner/*.c: be stricter about "ifdef WITH_SOME_NUT_FEATURE" (we may have some defined but zeroed, so not active for a build) [#3293] Signed-off-by: Jim Klimov --- tools/nut-scanner/nut-scan.h | 4 ++-- tools/nut-scanner/nutscan-init.c | 12 ++++++------ tools/nut-scanner/scan_avahi.c | 2 +- tools/nut-scanner/scan_ipmi.c | 2 +- tools/nut-scanner/scan_snmp.c | 6 +++--- tools/nut-scanner/scan_usb.c | 2 +- tools/nut-scanner/scan_xml_http.c | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/tools/nut-scanner/nut-scan.h b/tools/nut-scanner/nut-scan.h index 4d481b24d5..3d66ba12e8 100644 --- a/tools/nut-scanner/nut-scan.h +++ b/tools/nut-scanner/nut-scan.h @@ -63,8 +63,8 @@ #include "nutscan-device.h" #include "nutscan-ip.h" -#ifdef WITH_IPMI -#include +#if (defined WITH_IPMI) && WITH_IPMI +# include #endif #ifdef HAVE_PTHREAD diff --git a/tools/nut-scanner/nutscan-init.c b/tools/nut-scanner/nutscan-init.c index cb49ebb844..69402d2399 100644 --- a/tools/nut-scanner/nutscan-init.c +++ b/tools/nut-scanner/nutscan-init.c @@ -239,7 +239,7 @@ void nutscan_init(void) * known-compatible SOFILE_LIB first. */ -#ifdef WITH_USB +#if (defined WITH_USB) && WITH_USB # if WITH_LIBUSB_1_0 # ifdef SOFILE_LIBUSB1 @@ -347,8 +347,8 @@ void nutscan_init(void) __func__, "LibUSB"); #endif /* WITH_USB */ -#ifdef WITH_SNMP -# ifdef WITH_SNMP_STATIC +#if (defined WITH_SNMP) && WITH_SNMP +# if (defined WITH_SNMP_STATIC) && WITH_SNMP_STATIC /* This is a rare situation, reserved for platforms where libnetsnmp or * equivalent (some other ucd-snmp descendants) was not packaged, and * thus was custom-built for NUT (so linked statically to avoid potential @@ -416,7 +416,7 @@ void nutscan_init(void) __func__, "LibSNMP"); #endif /* WITH_SNMP */ -#ifdef WITH_NEON +#if (defined WITH_NEON) && WITH_NEON # ifdef SOFILE_LIBNEON if (!libname) { libname = get_libname(SOFILE_LIBNEON); @@ -485,7 +485,7 @@ void nutscan_init(void) __func__, "LibNeon"); #endif /* WITH_NEON */ -#ifdef WITH_AVAHI +#if (defined WITH_AVAHI) && WITH_AVAHI # ifdef SOFILE_LIBAVAHI if (!libname) { libname = get_libname(SOFILE_LIBAVAHI); @@ -532,7 +532,7 @@ void nutscan_init(void) __func__, "LibAvahi"); #endif /* WITH_AVAHI */ -#ifdef WITH_FREEIPMI +#if (defined WITH_FREEIPMI) && WITH_FREEIPMI # ifdef SOFILE_LIBFREEIPMI if (!libname) { libname = get_libname(SOFILE_LIBFREEIPMI); diff --git a/tools/nut-scanner/scan_avahi.c b/tools/nut-scanner/scan_avahi.c index a844e0b337..0501e86744 100644 --- a/tools/nut-scanner/scan_avahi.c +++ b/tools/nut-scanner/scan_avahi.c @@ -30,7 +30,7 @@ /* externally visible to nutscan-init */ int nutscan_unload_avahi_library(void); -#ifdef WITH_AVAHI +#if (defined WITH_AVAHI) && WITH_AVAHI #include #include diff --git a/tools/nut-scanner/scan_ipmi.c b/tools/nut-scanner/scan_ipmi.c index f847a5e931..9aa1e12e54 100644 --- a/tools/nut-scanner/scan_ipmi.c +++ b/tools/nut-scanner/scan_ipmi.c @@ -31,7 +31,7 @@ /* externally visible to nutscan-init */ int nutscan_unload_ipmi_library(void); -#ifdef WITH_IPMI +#if (defined WITH_IPMI) && WITH_IPMI #include #include diff --git a/tools/nut-scanner/scan_snmp.c b/tools/nut-scanner/scan_snmp.c index 3a230b5a8f..a5ad7158c4 100644 --- a/tools/nut-scanner/scan_snmp.c +++ b/tools/nut-scanner/scan_snmp.c @@ -33,7 +33,7 @@ /* externally visible to nutscan-init */ int nutscan_unload_snmp_library(void); -#ifdef WITH_SNMP +#if (defined WITH_SNMP) && WITH_SNMP #ifndef WIN32 # include @@ -195,7 +195,7 @@ int nutscan_unload_library(int *avail, lt_dlhandle *pdl_handle, char **libpath); #endif int nutscan_unload_snmp_library(void) { -#ifdef WITH_SNMP_STATIC +#if (defined WITH_SNMP_STATIC) && WITH_SNMP_STATIC return 0; #else nut_initialized_snmp = 0; @@ -207,7 +207,7 @@ int nutscan_unload_snmp_library(void) int nutscan_load_snmp_library(const char *libname_path); int nutscan_load_snmp_library(const char *libname_path) { -#ifdef WITH_SNMP_STATIC +#if (defined WITH_SNMP_STATIC) && WITH_SNMP_STATIC /* With MinGW, the netsnmp library may be linked statically (no dll) */ NUT_UNUSED_VARIABLE(libname_path); diff --git a/tools/nut-scanner/scan_usb.c b/tools/nut-scanner/scan_usb.c index dd44bd16f7..0f5ae6d43c 100644 --- a/tools/nut-scanner/scan_usb.c +++ b/tools/nut-scanner/scan_usb.c @@ -29,7 +29,7 @@ /* externally visible to nutscan-init */ int nutscan_unload_usb_library(void); -#ifdef WITH_USB +#if (defined WITH_USB) && WITH_USB #include "upsclient.h" #include "nutscan-usb.h" diff --git a/tools/nut-scanner/scan_xml_http.c b/tools/nut-scanner/scan_xml_http.c index a21d9d0e8e..699a8cab16 100644 --- a/tools/nut-scanner/scan_xml_http.c +++ b/tools/nut-scanner/scan_xml_http.c @@ -33,7 +33,7 @@ /* externally visible to nutscan-init */ int nutscan_unload_neon_library(void); -#ifdef WITH_NEON +#if (defined WITH_NEON) && WITH_NEON #ifndef WIN32 # include From 5fa25d15952c66410e35fe50505d8a02ceb75294 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 15:17:54 +0100 Subject: [PATCH 066/198] drivers/apcsmart-old.c: fix git merging typo Signed-off-by: Jim Klimov --- drivers/apcsmart-old.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/apcsmart-old.c b/drivers/apcsmart-old.c index f28812abeb..94b0365684 100644 --- a/drivers/apcsmart-old.c +++ b/drivers/apcsmart-old.c @@ -665,6 +665,8 @@ static void getbaseinfo(void) return; } + upsdebugx(1, "APC - Parsing out command set"); + /* We have the version.alert.cmdchars string * NB the alert chars are normally in IGNCHARS * so will have been pretty much edited out. * You will need to change the ser_get_line above if From 9275ebedea609cdcd14b726283aee3b1d8b24b7f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 15:23:21 +0100 Subject: [PATCH 067/198] NEWS.adoc: fix the entry for tripplitesu [#3273] Signed-off-by: Jim Klimov --- NEWS.adoc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index c8894c0fd2..5d08172d8e 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -204,10 +204,9 @@ https://github.com/networkupstools/nut/milestone/12 PR #3093] * Fixed default `unit_id`, apparently broken by changes in NUT v2.8.1. [issue #3191, PR #3192] - + - `tripplitesu` driver updates: - * Added configurable command delay to prevent read timeouts - [PR #3273] + * Added configurable command delay to prevent read timeouts. [PR #3273] - Introduced a new NUT driver named `nut-upower` which provides support for monitoring UPS and battery devices managed by the UPower daemon From 159da759dc511aa9aca4be0a8c4fa68a50dfcca3 Mon Sep 17 00:00:00 2001 From: Tim Niemueller Date: Sat, 31 Jan 2026 13:55:00 +0100 Subject: [PATCH 068/198] Fix compiler warnings about copy ellision This fixes the build fail triggered on CI farm, and some more that trigger on the more recent version 21 of clang. Signed-off-by: Tim Niemueller Signed-off-by: Jim Klimov --- common/common.c | 4 ++-- common/nutconf.cpp | 33 ++++++++++++++++----------------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/common/common.c b/common/common.c index e3f3631349..87c563ebca 100644 --- a/common/common.c +++ b/common/common.c @@ -5480,7 +5480,7 @@ const char *xinet_ntopSS(struct sockaddr_storage *s) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunreachable-code" #endif - char *addrstr = xcalloc(INETADDRBUF_SIZE, sizeof(char*)); + char *addrstr = (char*)xcalloc(INETADDRBUF_SIZE, sizeof(char*)); const char *ret; if (!addrstr) @@ -5580,7 +5580,7 @@ const char *xinet_ntopAI(struct addrinfo *ai) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunreachable-code" #endif - char *addrstr = xcalloc(INETADDRBUF_SIZE, sizeof(char*)); + char *addrstr = (char*)xcalloc(INETADDRBUF_SIZE, sizeof(char*)); const char *ret; if (!addrstr) diff --git a/common/nutconf.cpp b/common/nutconf.cpp index ea2dd1659f..4345034f18 100644 --- a/common/nutconf.cpp +++ b/common/nutconf.cpp @@ -35,6 +35,7 @@ #include #include +#include #include @@ -270,23 +271,23 @@ NutParser::Token NutParser::parseToken() } else if (c == '[') { token = Token(Token::TOKEN_BRACKET_OPEN, c); popPos(); - return token; + return Token(std::move(token)); } else if (c == ']') { token = Token(Token::TOKEN_BRACKET_CLOSE, c); popPos(); - return token; + return Token(std::move(token)); } else if (c == ':' && !hasOptions(OPTION_IGNORE_COLON)) { token = Token(Token::TOKEN_COLON, c); popPos(); - return token; + return Token(std::move(token)); } else if (c == '=') { token = Token(Token::TOKEN_EQUAL, c); popPos(); - return token; + return Token(std::move(token)); } else if (c == '\r' || c == '\n') { token = Token(Token::TOKEN_EOL, c); popPos(); - return token; + return Token(std::move(token)); } else if (c == '#') { token.type = Token::TOKEN_COMMENT; state = LEXPARSING_STATE_COMMENT; @@ -318,7 +319,7 @@ NutParser::Token NutParser::parseToken() token.str += '"'; } else { popPos(); - return token; + return Token(std::move(token)); } } else if (c == '\\') { if (escaped) { @@ -333,10 +334,10 @@ NutParser::Token NutParser::parseToken() /* WTF ? consider it as correct ? */ back(); popPos(); - return token; + return Token(std::move(token)); } else if (c == 0) /* EOF */ { popPos(); - return token; + return Token(std::move(token)); } else /* Bad character ?? */ { /* WTF ? Keep, Ignore ? */ } @@ -355,7 +356,7 @@ NutParser::Token NutParser::parseToken() } else { back(); popPos(); - return token; + return Token(std::move(token)); } } else if (c == '\\') { if (escaped) { @@ -367,10 +368,10 @@ NutParser::Token NutParser::parseToken() } else if (c == '\r' || c == '\n') /* EOL */{ back(); popPos(); - return token; + return Token(std::move(token)); } else if (c == 0) /* EOF */ { popPos(); - return token; + return Token(std::move(token)); }else if (isgraph(c)) { token.str += c; } else /* Bad character ?? */ { @@ -382,7 +383,7 @@ NutParser::Token NutParser::parseToken() case LEXPARSING_STATE_COMMENT: { if (c == '\r' || c == '\n') { - return token; + return Token(std::move(token)); } else { token.str += c; } @@ -416,7 +417,7 @@ NutParser::Token NutParser::parseToken() } } popPos(); - return token; + return Token(std::move(token)); } std::list NutParser::parseLine() @@ -1044,15 +1045,13 @@ void GenericConfiguration::removeSection(const std::string & section) std::string GenericConfiguration::getStr(const std::string & section, const std::string & entry, bool caseSensitive) const { - std::string str; - ConfigParamList params; if (!get(section, entry, params, caseSensitive)) - return str; + return std::string(); if (params.empty()) - return str; + return std::string(); return params.front(); } From 89fc1ef369a2a5a6fd10a4ac053bad08e6b0e98f Mon Sep 17 00:00:00 2001 From: Tim Niemueller Date: Sun, 1 Feb 2026 11:53:56 +0100 Subject: [PATCH 069/198] Fix unrelated compiler warnings to be able to complete distcheck On the used clang version implicit conversion triggers a warning, the `-Werror` makes those errors. I have used Gemini for some of these, but quota ran out after half an hour and ~120 invocations so I completed the rest manually. Signed-off-by: Tim Niemueller Signed-off-by: Jim Klimov --- clients/cgilib.c | 2 +- clients/nutclientmem.cpp | 10 +++- clients/upsc.c | 2 +- clients/upscmd.c | 4 +- clients/upslog.c | 18 +++---- clients/upsmon.c | 54 +++++++++++---------- clients/upsrw.c | 4 +- clients/upssched.c | 26 +++++----- clients/upsset.c | 10 ++-- clients/upsstats.c | 12 ++--- common/common.c | 20 ++++---- common/parseconf.c | 10 ++-- common/state.c | 12 ++--- drivers/adelsystem_cbi.c | 2 +- drivers/adelsystem_cbi.h | 2 +- drivers/al175.c | 2 +- drivers/apc_modbus.c | 70 +++++++++++++-------------- drivers/apcsmart.c | 8 +-- drivers/bcmxcp.c | 4 +- drivers/bcmxcp_usb.c | 8 +-- drivers/common_voltronic-crc.c | 12 ++--- drivers/dummy-ups.c | 2 +- drivers/ecoflow-hid.c | 2 +- drivers/failover.c | 30 ++++++------ drivers/generic_modbus.c | 20 ++++---- drivers/hidparser.c | 8 +-- drivers/libhid.c | 4 +- drivers/libshut.c | 8 +-- drivers/main.c | 2 +- drivers/mge-hid.c | 2 +- drivers/microdowell.c | 2 +- drivers/nhs_ser.c | 2 +- drivers/nutdrv_qx.c | 17 ++++--- drivers/nutdrv_qx_masterguard.c | 4 +- drivers/rhino.c | 2 +- drivers/serial.c | 6 +-- drivers/snmp-ups.c | 8 +-- drivers/tripplite_usb.c | 8 +-- drivers/upsdrvctl.c | 24 ++++----- drivers/usb-common.c | 8 +-- drivers/usbhid-ups.c | 6 +-- server/conf.c | 4 +- server/desc.c | 2 +- server/upsd.c | 21 ++++---- server/user.c | 26 +++++----- tools/nut-scanner/nutscan-device.c | 2 +- tools/nut-scanner/nutscan-display.c | 2 +- tools/nut-scanner/nutscan-ip.c | 2 +- tools/nut-scanner/nutscan-serial.c | 2 +- tools/nut-scanner/scan_avahi.c | 16 +++--- tools/nut-scanner/scan_eaton_serial.c | 8 +-- tools/nut-scanner/scan_ipmi.c | 8 +-- tools/nut-scanner/scan_nut.c | 12 ++--- tools/nut-scanner/scan_snmp.c | 10 ++-- tools/nut-scanner/scan_usb.c | 4 +- tools/nut-scanner/scan_xml_http.c | 10 ++-- 56 files changed, 300 insertions(+), 286 deletions(-) diff --git a/clients/cgilib.c b/clients/cgilib.c index 687eed8c5b..1817d582f6 100644 --- a/clients/cgilib.c +++ b/clients/cgilib.c @@ -31,7 +31,7 @@ static char *unescape(char *buf) char ch, *newbuf, hex[8]; buflen = strlen(buf) + 2; - newbuf = xmalloc(buflen); + newbuf = (char *)xmalloc(buflen); *newbuf = '\0'; fflush(stdout); diff --git a/clients/nutclientmem.cpp b/clients/nutclientmem.cpp index 45430b29cc..1b8492a06e 100644 --- a/clients/nutclientmem.cpp +++ b/clients/nutclientmem.cpp @@ -37,7 +37,10 @@ Device MemClientStub::getDevice(const std::string& name) std::set MemClientStub::getDeviceNames() { - throw NutException("Not implemented"); + volatile bool not_implemented = true; + if (not_implemented) + throw NutException("Not implemented"); + return std::set(); } std::string MemClientStub::getDeviceDescription(const std::string& name) @@ -176,7 +179,10 @@ TrackingID MemClientStub::executeDeviceCommand(const std::string& dev, const std std::map> MemClientStub::listDeviceClients(void) { - throw NutException("Not implemented"); + volatile bool not_implemented = true; + if (not_implemented) + throw NutException("Not implemented"); + return std::map>(); } std::set MemClientStub::deviceGetClients(const std::string& dev) diff --git a/clients/upsc.c b/clients/upsc.c index d8801f7496..6912e70f01 100644 --- a/clients/upsc.c +++ b/clients/upsc.c @@ -463,7 +463,7 @@ int main(int argc, char **argv) upsdebugx(1, "upsname='%s' hostname='%s' port='%" PRIu16 "'", NUT_STRARG(upsname), NUT_STRARG(hostname), port); - ups = xmalloc(sizeof(*ups)); + ups = (UPSCONN_t *)xmalloc(sizeof(*ups)); if (upscli_connect(ups, hostname, port, UPSCLI_CONN_TRYSSL) < 0) { fatalx_error_json_simple(0, upscli_strerror(ups)); diff --git a/clients/upscmd.c b/clients/upscmd.c index 53761a99dc..963153cdc8 100644 --- a/clients/upscmd.c +++ b/clients/upscmd.c @@ -135,7 +135,7 @@ static void listcmds(void) /* we must first read the entire list of commands, * before we can start reading the descriptions */ - ltmp = xcalloc(1, sizeof(*ltmp)); + ltmp = (struct list_t *)xcalloc(1, sizeof(*ltmp)); ltmp->name = xstrdup(answer[2]); if (llast) { @@ -377,7 +377,7 @@ int main(int argc, char **argv) fatalx(EXIT_FAILURE, "Error: invalid UPS definition. Required format: upsname[@hostname[:port]]"); } - ups = xcalloc(1, sizeof(*ups)); + ups = (UPSCONN_t *)xcalloc(1, sizeof(*ups)); if (upscli_connect(ups, hostname, port, UPSCLI_CONN_TRYSSL) < 0) { fatalx(EXIT_FAILURE, "Error: %s", upscli_strerror(ups)); diff --git a/clients/upslog.c b/clients/upslog.c index 8f957fddf9..52820c126b 100644 --- a/clients/upslog.c +++ b/clients/upslog.c @@ -99,7 +99,7 @@ static struct logtarget_t *add_logfile(const char *logfn_arg) if (!logfn_arg || !(*logfn_arg)) return p; - p = xcalloc(1, sizeof(struct monhost_ups_t)); + p = (struct logtarget_t *)xcalloc(1, sizeof(struct logtarget_t)); p->logfn = xstrdup(logfn_arg); p->logfile = NULL; @@ -374,7 +374,7 @@ static void add_call(void (*fptr)(const char *arg, const struct monhost_ups_t *m tmp = tmp->next; } - tmp = xmalloc(sizeof(flist_t)); + tmp = (flist_t *)xmalloc(sizeof(flist_t)); tmp->fptr = fptr; @@ -543,7 +543,7 @@ int main(int argc, char **argv) char *m_arg, *s; monhost_ups_prev = monhost_ups_current; - monhost_ups_current = xmalloc(sizeof(struct monhost_ups_t)); + monhost_ups_current = (struct monhost_ups_t *)xmalloc(sizeof(struct monhost_ups_t)); if (monhost_ups_anchor == NULL) monhost_ups_anchor = monhost_ups_current; else @@ -685,7 +685,7 @@ int main(int argc, char **argv) if (argc >= 4) { /* read out the remaining argv entries to the format string */ - logformat = xmalloc(LARGEBUF); + logformat = (char *)xmalloc(LARGEBUF); memset(logformat, '\0', LARGEBUF); logformat_allocated = 1; @@ -703,7 +703,7 @@ int main(int argc, char **argv) /* May be or not be NULL here: */ monhost_ups_prev = monhost_ups_current; - monhost_ups_current = xmalloc(sizeof(struct monhost_ups_t)); + monhost_ups_current = (struct monhost_ups_t *)xmalloc(sizeof(struct monhost_ups_t)); if (monhost_ups_anchor == NULL) { /* Become the single-entry list */ monhost_ups_anchor = monhost_ups_current; @@ -731,7 +731,7 @@ int main(int argc, char **argv) char *s = xstrdup(logformat); if (s) { if (!logformat_allocated) { - logformat = xmalloc(LARGEBUF); + logformat = (char *)xmalloc(LARGEBUF); if (!logformat) fatalx(EXIT_FAILURE, "Failed re-allocation to prepend UPSHOST to formatting string"); memset(logformat, '\0', LARGEBUF); @@ -783,7 +783,7 @@ int main(int argc, char **argv) monhost_ups_current->port ); - conn = xmalloc(sizeof(*conn)); + conn = (UPSCONN_t *)xmalloc(sizeof(*conn)); if (upscli_connect(conn, monhost_ups_current->hostname, monhost_ups_current->port, UPSCLI_CONN_TRYSSL) < 0) { fatalx(EXIT_FAILURE, "Error: %s", upscli_strerror(conn)); @@ -811,7 +811,7 @@ int main(int argc, char **argv) found++; upsdebugx(1, "FOUND: %s: %s", answer[1], answer[2]); - mu = xmalloc(sizeof(struct monhost_ups_t)); + mu = (struct monhost_ups_t *)xmalloc(sizeof(struct monhost_ups_t)); snprintf(buf, sizeof(buf), "%s@%s:%" PRIu16, answer[1], monhost_ups_current->hostname, @@ -897,7 +897,7 @@ int main(int argc, char **argv) fatalx(EXIT_FAILURE, "Error: invalid UPS definition. Required format: upsname[@hostname[:port]]\n"); } - monhost_ups_current->ups = xmalloc(sizeof(UPSCONN_t)); + monhost_ups_current->ups = (UPSCONN_t *)xmalloc(sizeof(UPSCONN_t)); if (upscli_connect(monhost_ups_current->ups, monhost_ups_current->hostname, monhost_ups_current->port, UPSCLI_CONN_TRYSSL) < 0) fprintf(stderr, "Warning: initial connect failed: %s\n", diff --git a/clients/upsmon.c b/clients/upsmon.c index 89386bf29f..70f7a2c030 100644 --- a/clients/upsmon.c +++ b/clients/upsmon.c @@ -1104,7 +1104,7 @@ static void doshutdown(void) /* Contact the data server(s) regularly so this * client is not assumed dead while looping */ - for (ups = firstups; ups != NULL && !exit_flag; ups = ups->next) { + for (ups = firstups; ups != NULL && !exit_flag; ups = (utype_t *)ups->next) { set_alarm(); if (get_var(ups, "numlogins", temp, sizeof(temp)) >= 0) { @@ -1337,7 +1337,7 @@ static void sync_secondaries(void) upsnotify(NOTIFY_STATE_WATCHDOG, NULL); - for (ups = firstups; ups != NULL; ups = ups->next) { + for (ups = firstups; ups != NULL; ups = (utype_t *)ups->next) { /* only check login count on devices we are the primary for */ if (!flag_isset(ups->status, ST_PRIMARY)) @@ -1404,7 +1404,7 @@ static void forceshutdown(void) userfsd, exit_flag, use_pipe); /* set FSD on any "primary" UPS entries (forced shutdown in progress) */ - for (ups = firstups; ups != NULL; ups = ups->next) + for (ups = firstups; ups != NULL; ups = (utype_t *)ups->next) if (flag_isset(ups->status, ST_PRIMARY)) { isaprimary = 1; upsdebugx(2, "%s: tell data server to setfsd(%s@%s)", @@ -1723,7 +1723,7 @@ static void recalc(void) else val_ol += ups->pv; - ups = ups->next; + ups = (utype_t *)ups->next; } upsdebugx(3, "Current power value: %u", val_ol); @@ -2130,10 +2130,10 @@ static void addups(int reloading, const char *sys, const char *pvs, return; } - tmp = tmp->next; + tmp = (utype_t *)tmp->next; } - tmp = xcalloc(1, sizeof(utype_t)); + tmp = (utype_t *)xcalloc(1, sizeof(utype_t)); /* TOTHINK: init (UPSCONN_t)tmp->conn struct fields too? */ tmp->sys = xstrdup(sys); tmp->pv = pv; @@ -2620,7 +2620,7 @@ static void loadconfig(void) while (ups) { ups->pollfail_log_throttle_count = -1; ups->pollfail_log_throttle_state = UPSCLI_ERR_NONE; - ups = ups->next; + ups = (utype_t *)ups->next; } } } @@ -2740,7 +2740,7 @@ static void upsmon_cleanup(void) utmp = firstups; while (utmp) { - unext = utmp->next; + unext = (utype_t *)utmp->next; drop_connection(utmp); ups_free(utmp); @@ -3625,7 +3625,7 @@ static void delete_ups(utype_t *target) /* about to delete the first ups? */ if (ptr == last) - firstups = ptr->next; + firstups = (utype_t *)ptr->next; else last->next = ptr->next; @@ -3637,7 +3637,7 @@ static void delete_ups(utype_t *target) } last = ptr; - ptr = ptr->next; + ptr = (utype_t *)ptr->next; } /* shouldn't happen */ @@ -3677,7 +3677,7 @@ static void reload_conf(void) while (tmp) { tmp->retain = 0; - tmp = tmp->next; + tmp = (utype_t *)tmp->next; } /* reset paranoia checker */ @@ -3687,17 +3687,16 @@ static void reload_conf(void) loadconfig(); /* go through the utype_t struct again */ - tmp = firstups; - - while (tmp) { - next = tmp->next; + tmp = firstups; + while (tmp) { + next = (utype_t *)tmp->next; - /* !retain means it wasn't in the .conf this time around */ - if (tmp->retain == 0) - delete_ups(tmp); + /* !retain means it wasn't in the .conf this time around */ + if (tmp->retain == 0) + delete_ups(tmp); - tmp = next; - } + tmp = next; + } /* see if the user just blew off a foot */ if (totalpv < minsupplies) { @@ -3816,9 +3815,14 @@ int main(int argc, char *argv[]) print_banner_once(prog, 0); /* if no configuration file is specified on the command line, use default */ - configfile = xmalloc(SMALLBUF); - snprintf(configfile, SMALLBUF, "%s/upsmon.conf", confpath()); - configfile = xrealloc(configfile, strlen(configfile) + 1); + /* get the real filename */ + if (configfile) { + configfile = (char *)xrealloc(configfile, strlen(configfile) + 1); + } else { + configfile = (char *)xmalloc(SMALLBUF); + snprintf(configfile, SMALLBUF, "%s/upsmon.conf", confpath()); + configfile = (char *)xrealloc(configfile, strlen(configfile) + 1); + } run_as_user = xstrdup(RUN_AS_USER); @@ -4258,7 +4262,7 @@ int main(int argc, char *argv[]) gettimeofday(&now, NULL); time(&ttNow); - for (ups = firstups; ups != NULL; ups = ups->next) { + for (ups = firstups; ups != NULL; ups = (utype_t *)ups->next) { ups->status = 0; ups->lastpoll = ttNow; } @@ -4280,7 +4284,7 @@ int main(int argc, char *argv[]) /* Reset the value, regardless of support */ sleep_inhibitor_status = -2; - for (ups = firstups; ups != NULL; ups = ups->next) { + for (ups = firstups; ups != NULL; ups = (utype_t *)ups->next) { if (isPreparingForSleepSupported() && (sleep_inhibitor_status = isPreparingForSleep()) >= 0) { upsdebugx(2, "Aborting UPS polling sub-loop because OS is preparing for sleep or just woke up"); goto end_loop_cycle; diff --git a/clients/upsrw.c b/clients/upsrw.c index 79c6ffa87e..97ca368b57 100644 --- a/clients/upsrw.c +++ b/clients/upsrw.c @@ -617,7 +617,7 @@ static void print_rwlist(void) /* sock this entry away for later */ - ltmp = xmalloc(sizeof(struct list_t)); + ltmp = (struct list_t *)xmalloc(sizeof(struct list_t)); ltmp->name = xstrdup(answer[2]); ltmp->next = NULL; @@ -731,7 +731,7 @@ int main(int argc, char **argv) fatalx(EXIT_FAILURE, "Error: invalid UPS definition. Required format: upsname[@hostname[:port]]"); } - ups = xcalloc(1, sizeof(*ups)); + ups = (UPSCONN_t *)xcalloc(1, sizeof(*ups)); if (upscli_connect(ups, hostname, port, UPSCLI_CONN_TRYSSL) < 0) { fatalx(EXIT_FAILURE, "Error: %s", upscli_strerror(ups)); diff --git a/clients/upssched.c b/clients/upssched.c index 1cb7177aff..b201d82c1d 100644 --- a/clients/upssched.c +++ b/clients/upssched.c @@ -151,7 +151,7 @@ static char* collect_string(char **string_arr, char *logtag, char *sep, size_t * if (!string_arr || !(*string_arr) || !(**string_arr)) return NULL; - buf = xcalloc(bufsize, sizeof(char)); + buf = (char *)xcalloc(bufsize, sizeof(char)); if (!buf) { upsdebugx(1, "%s: failed to allocate buffer, will not report any %s values", __func__, logtag); return NULL; @@ -187,7 +187,7 @@ static char* collect_string(char **string_arr, char *logtag, char *sep, size_t * if (bufsize < SIZE_MAX - LARGEBUF) { bufsize += LARGEBUF; upsdebugx(1, "%s: buffer overflowed, trying to re-allocate as %" PRIuSIZE, __func__, bufsize); - buf = realloc(buf, bufsize); + buf = (char *)realloc(buf, bufsize); if (!buf) { upsdebugx(1, "%s: buffer overflowed and failed to re-allocate, will not report any %s values", __func__, logtag); @@ -435,12 +435,12 @@ static void start_timer(const char *name, const char *ofsstr, const char *notify } if (*ps == NULL) { - tmp->notifytypes = xrealloc(tmp->notifytypes, count + 2); + tmp->notifytypes = (char **)xrealloc(tmp->notifytypes, count + 2); tmp->notifytypes[count] = xstrdup(notifytype); tmp->notifytypes[count + 1] = NULL; } } else { - tmp->notifytypes = xcalloc(2, sizeof(char*)); + tmp->notifytypes = (char **)xcalloc(2, sizeof(char*)); tmp->notifytypes[0] = xstrdup(notifytype); tmp->notifytypes[1] = NULL; } @@ -458,12 +458,12 @@ static void start_timer(const char *name, const char *ofsstr, const char *notify } if (*ps == NULL) { - tmp->notifymsgs = xrealloc(tmp->notifymsgs, count + 2); + tmp->notifymsgs = (char **)xrealloc(tmp->notifymsgs, count + 2); tmp->notifymsgs[count] = xstrdup(notifymsg); tmp->notifymsgs[count + 1] = NULL; } } else { - tmp->notifymsgs = xcalloc(2, sizeof(char*)); + tmp->notifymsgs = (char **)xcalloc(2, sizeof(char*)); tmp->notifymsgs[0] = xstrdup(notifymsg); tmp->notifymsgs[1] = NULL; } @@ -481,12 +481,12 @@ static void start_timer(const char *name, const char *ofsstr, const char *notify } if (*ps == NULL) { - tmp->upsnames = xrealloc(tmp->upsnames, count + 2); + tmp->upsnames = (char **)xrealloc(tmp->upsnames, count + 2); tmp->upsnames[count] = xstrdup(upsname); tmp->upsnames[count + 1] = NULL; } } else { - tmp->upsnames = xcalloc(2, sizeof(char*)); + tmp->upsnames = (char **)xcalloc(2, sizeof(char*)); tmp->upsnames[0] = xstrdup(upsname); tmp->upsnames[1] = NULL; } @@ -515,7 +515,7 @@ static void start_timer(const char *name, const char *ofsstr, const char *notify } } /* else we already know */ - tmp = xmalloc(sizeof(ttype_t)); + tmp = (ttype_t *)xmalloc(sizeof(ttype_t)); tmp->name = xstrdup(name); tmp->etime = now + ofs; tmp->notifytypes = NULL; @@ -524,19 +524,19 @@ static void start_timer(const char *name, const char *ofsstr, const char *notify tmp->next = NULL; if (notifytype && *notifytype) { - tmp->notifytypes = xcalloc(2, sizeof(char*)); + tmp->notifytypes = (char **)xcalloc(2, sizeof(char*)); tmp->notifytypes[0] = xstrdup(notifytype); tmp->notifytypes[1] = NULL; } if (notifymsg && *notifymsg) { - tmp->notifymsgs = xcalloc(2, sizeof(char*)); + tmp->notifymsgs = (char **)xcalloc(2, sizeof(char*)); tmp->notifymsgs[0] = xstrdup(notifymsg); tmp->notifymsgs[1] = NULL; } if (upsname && *upsname) { - tmp->upsnames = xcalloc(2, sizeof(char*)); + tmp->upsnames = (char **)xcalloc(2, sizeof(char*)); tmp->upsnames[0] = xstrdup(upsname); tmp->upsnames[1] = NULL; } @@ -927,7 +927,7 @@ static TYPE_FD conn_add(TYPE_FD sockfd) tmp = tmp->next; } - tmp = xmalloc(sizeof(conn_t)); + tmp = (conn_t *)xmalloc(sizeof(conn_t)); tmp->fd = acc; tmp->next = NULL; diff --git a/clients/upsset.c b/clients/upsset.c index 4b6c302822..f952846973 100644 --- a/clients/upsset.c +++ b/clients/upsset.c @@ -91,10 +91,10 @@ void parsearg(char *var, char *value) tmp = last = firstuv; while (tmp) { last = tmp; - tmp = tmp->next; + tmp = (uvtype_t *)tmp->next; } - tmp = xmalloc(sizeof(uvtype_t)); + tmp = (uvtype_t *)xmalloc(sizeof(uvtype_t)); tmp->var = xstrdup(ptr); tmp->value = xstrdup(value); tmp->next = NULL; @@ -437,7 +437,7 @@ static void showcmds(void) return; } - ltmp = xmalloc(sizeof(struct list_t)); + ltmp = (struct list_t *)xmalloc(sizeof(struct list_t)); ltmp->name = xstrdup(answer[2]); ltmp->next = NULL; @@ -871,7 +871,7 @@ static void showsettings(void) /* sock this entry away for later */ - ltmp = xmalloc(sizeof(struct list_t)); + ltmp = (struct list_t *)xmalloc(sizeof(struct list_t)); ltmp->name = xstrdup(answer[2]); ltmp->next = NULL; @@ -1002,7 +1002,7 @@ static void savesettings(void) while (upsvar) { changed += setvar(upsvar->var, upsvar->value); - upsvar = upsvar->next; + upsvar = (uvtype_t *)upsvar->next; } if (changed == 0) diff --git a/clients/upsstats.c b/clients/upsstats.c index 4ec650c451..5a0bf47521 100644 --- a/clients/upsstats.c +++ b/clients/upsstats.c @@ -940,7 +940,7 @@ static int do_command(char *cmd) upsdebugx(2, "%s: ENDFOR: done with UPS [%s] [%s]", __func__, NUT_STRARG(currups->sys), NUT_STRARG(currups->desc)); upsdebugx(2, "%s: current skip_clause=%d skip_block=%d", __func__, skip_clause, skip_block); - currups = currups->next; + currups = (ulist_t *)currups->next; if (currups) { upsdebugx(2, "%s: ENDFOR: proceed with next UPS [%s]", __func__, NUT_STRARG(currups->desc)); @@ -1216,10 +1216,10 @@ static void add_ups(char *sys, char *desc) while (tmp) { last = tmp; - tmp = tmp->next; + tmp = (ulist_t *)tmp->next; } - tmp = xmalloc(sizeof(ulist_t)); + tmp = (ulist_t *)xmalloc(sizeof(ulist_t)); tmp->sys = xstrdup(sys); tmp->desc = xstrdup(desc); @@ -1387,7 +1387,7 @@ static void display_json(void) } /* Loop through all devices (in single-host mode, this is just one) */ - for (currups = ulhead; currups != NULL; currups = currups->next) { + for (currups = ulhead; currups != NULL; currups = (ulist_t *)currups->next) { ups_connect(); if (!is_first_ups) printf(",\n"); @@ -1533,7 +1533,7 @@ int main(int argc, char **argv) /* Clean up memory */ free(monhost); while (ulhead) { - currups = ulhead->next; + currups = (ulist_t *)ulhead->next; free(ulhead->sys); free(ulhead->desc); free(ulhead); @@ -1567,7 +1567,7 @@ int main(int argc, char **argv) free(upsname); free(hostname); while (ulhead) { - currups = ulhead->next; + currups = (ulist_t *)ulhead->next; free(ulhead->sys); free(ulhead->desc); free(ulhead); diff --git a/common/common.c b/common/common.c index 87c563ebca..903b77880a 100644 --- a/common/common.c +++ b/common/common.c @@ -1464,17 +1464,17 @@ int compareprocnames(pid_t pid, const char *procname, const char **prognames) goto finish; } - progbasenames = xcalloc(total_prognames, sizeof(char*)); + progbasenames = (char **)xcalloc(total_prognames, sizeof(char*)); if (!progbasenames) { ret = -2; goto finish; } - progbasenamelen = xcalloc(total_prognames, sizeof(size_t)); + progbasenamelen = (size_t *)xcalloc(total_prognames, sizeof(size_t)); if (!progbasenamelen) { ret = -2; goto finish; } - progbasenamedot = xcalloc(total_prognames, sizeof(size_t)); + progbasenamedot = (size_t *)xcalloc(total_prognames, sizeof(size_t)); if (!progbasenamedot) { ret = -2; goto finish; @@ -1482,7 +1482,7 @@ int compareprocnames(pid_t pid, const char *procname, const char **prognames) memset(all_progbasenames, 0, sizeof(all_progbasenames)); for (i = 0; i < total_prognames - 1; i++) { - progbasenames[i] = xcalloc(NUT_PATH_MAX + 1, sizeof(char)); + progbasenames[i] = (char *)xcalloc(NUT_PATH_MAX + 1, sizeof(char)); if (!progbasenames[i]) { ret = -2; @@ -3550,7 +3550,7 @@ int validate_formatting_string(const char *fmt_dynamic, const char *fmt_referenc */ size_t lenD = strlen(fmt_dynamic) + 1; size_t lenR = strlen(fmt_reference) + 1; - char *bufD = xcalloc(lenD, sizeof(char)), *bufR = xcalloc(lenR, sizeof(char)); + char *bufD = (char *)xcalloc(lenD, sizeof(char)), *bufR = (char *)xcalloc(lenR, sizeof(char)); size_t lenBufD; if (!bufD || !bufR) { @@ -3765,7 +3765,7 @@ static void vupslog(int priority, const char *fmt, va_list va, int use_strerror) { int ret, errno_orig = errno; size_t bufsize = LARGEBUF; - char *buf = xcalloc(bufsize, sizeof(char)); + char *buf = (char *)xcalloc(bufsize, sizeof(char)); /* Be pedantic about our limitations */ bufsize *= sizeof(char); @@ -3844,7 +3844,7 @@ static void vupslog(int priority, const char *fmt, va_list va, int use_strerror) newbufsize); } bufsize = newbufsize; - buf = xrealloc(buf, bufsize); + buf = (char *)xrealloc(buf, bufsize); continue; } } else { @@ -4207,7 +4207,7 @@ void setproctag(const char *tag) proctag = xstrdup(tag); proctag_for_upsdebug_buflen = strlen(tag) + 2; - proctag_for_upsdebug = xcalloc(proctag_for_upsdebug_buflen, sizeof(char)); + proctag_for_upsdebug = (char *)xcalloc(proctag_for_upsdebug_buflen, sizeof(char)); if (proctag_for_upsdebug) { snprintf(proctag_for_upsdebug, proctag_for_upsdebug_buflen, ":%s", tag); } @@ -4823,7 +4823,7 @@ void nut_prepare_search_paths(void) { count_builtin = i + 1; /* +1 for the NULL */ /* Bytes inside should all be zeroed... */ - filtered_search_paths = xcalloc(count_builtin, sizeof(const char *)); + filtered_search_paths = (const char **)xcalloc(count_builtin, sizeof(const char *)); /* FIXME: here "count_builtin" means size of filtered_search_paths[] * and may later be more, if we would consider other data sources */ @@ -5317,7 +5317,7 @@ int compile_regex(regex_t **compiled, const char *regex, const int cflags) return 0; } - preg = malloc(sizeof(*preg)); + preg = (regex_t *)malloc(sizeof(*preg)); if (!preg) { return -1; } diff --git a/common/parseconf.c b/common/parseconf.c index cebf27f839..a9b7815990 100644 --- a/common/parseconf.c +++ b/common/parseconf.c @@ -132,13 +132,13 @@ static void add_arg_word(PCONF_CTX_t *ctx) ctx->maxargs = ctx->numargs; /* resize the lists */ - ctx->arglist = realloc(ctx->arglist, + ctx->arglist = (char **)realloc(ctx->arglist, sizeof(char *) * ctx->numargs); if (!ctx->arglist) pconf_fatal(ctx, "realloc arglist failed"); - ctx->argsize = realloc(ctx->argsize, + ctx->argsize = (size_t *)realloc(ctx->argsize, sizeof(size_t) * ctx->numargs); if (!ctx->argsize) @@ -159,7 +159,7 @@ static void add_arg_word(PCONF_CTX_t *ctx) newlen = wbuflen + 1; /* expand the string storage */ - ctx->arglist[argpos] = realloc(ctx->arglist[argpos], newlen); + ctx->arglist[argpos] = (char *)realloc(ctx->arglist[argpos], newlen); if (!ctx->arglist[argpos]) pconf_fatal(ctx, "realloc arglist member failed"); @@ -200,7 +200,7 @@ static void addchar(PCONF_CTX_t *ctx) if (wbuflen >= (ctx->wordbufsize - 1)) { ctx->wordbufsize += 8; - ctx->wordbuf = realloc(ctx->wordbuf, ctx->wordbufsize); + ctx->wordbuf = (char *)realloc(ctx->wordbuf, ctx->wordbufsize); if (!ctx->wordbuf) pconf_fatal(ctx, "realloc wordbuf failed"); @@ -415,7 +415,7 @@ int pconf_init(PCONF_CTX_t *ctx, void errhandler(const char *)) ctx->argsize = NULL; ctx->wordbufsize = 16; - ctx->wordbuf = calloc(1, ctx->wordbufsize); + ctx->wordbuf = (char *)calloc(1, ctx->wordbufsize); if (!ctx->wordbuf) pconf_fatal(ctx, "malloc wordbuf failed"); diff --git a/common/state.c b/common/state.c index 877e9a9bf1..f78ad7aea5 100644 --- a/common/state.c +++ b/common/state.c @@ -54,7 +54,7 @@ static void val_escape(st_tree_t *node) /* if the escaped value grew, deal with it */ if (node->safesize < (strlen(etmp) + 1)) { node->safesize = strlen(etmp) + 1; - node->safe = xrealloc(node->safe, node->safesize); + node->safe = (char *)xrealloc(node->safe, node->safesize); } snprintf(node->safe, node->safesize, "%s", etmp); @@ -310,7 +310,7 @@ int state_setinfo(st_tree_t **nptr, const char *var, const char *val) /* expand the buffer if the value grows */ if (node->rawsize < (strlen(val) + 1)) { node->rawsize = strlen(val) + 1; - node->raw = xrealloc(node->raw, node->rawsize); + node->raw = (char *)xrealloc(node->raw, node->rawsize); } /* store the literal value for later comparisons */ @@ -321,7 +321,7 @@ int state_setinfo(st_tree_t **nptr, const char *var, const char *val) return 1; /* changed */ } - *nptr = xcalloc(1, sizeof(**nptr)); + *nptr = (st_tree_t *)xcalloc(1, sizeof(**nptr)); (*nptr)->var = xstrdup(var); (*nptr)->raw = xstrdup(val); @@ -347,7 +347,7 @@ static int st_tree_enum_add(enum_t **list, const char *enc) return 0; /* duplicate */ } - item = xcalloc(1, sizeof(*item)); + item = (enum_t *)xcalloc(1, sizeof(*item)); item->val = xstrdup(enc); item->next = *list; @@ -392,7 +392,7 @@ static int st_tree_range_add(range_t **list, const int min, const int max) return 0; /* duplicate */ } - item = xcalloc(1, sizeof(*item)); + item = (range_t *)xcalloc(1, sizeof(*item)); item->min = min; item->max = max; item->next = *list; @@ -581,7 +581,7 @@ int state_addcmd(cmdlist_t **list, const char *cmd) return 0; /* duplicate */ } - item = xcalloc(1, sizeof(*item)); + item = (cmdlist_t *)xcalloc(1, sizeof(*item)); item->name = xstrdup(cmd); item->next = *list; diff --git a/drivers/adelsystem_cbi.c b/drivers/adelsystem_cbi.c index f7f3e904fd..48e7d0f355 100644 --- a/drivers/adelsystem_cbi.c +++ b/drivers/adelsystem_cbi.c @@ -1336,7 +1336,7 @@ modbus_t *modbus_new(const char *port) upslogx(LOG_ERR, "modbus_new_rtu: Unable to open serial port context"); } } else if ((sp = strchr(port, ':')) != NULL) { - char *tcp_port = xmalloc(sizeof(sp)); + char *tcp_port = (char*)xmalloc(sizeof(sp)); strncpy(tcp_port, sp + 1, sizeof(sp)); *sp = '\0'; mb = modbus_new_tcp(port, (int)strtoul(tcp_port, NULL, 10)); diff --git a/drivers/adelsystem_cbi.h b/drivers/adelsystem_cbi.h index 5551414d03..1fd2139494 100644 --- a/drivers/adelsystem_cbi.h +++ b/drivers/adelsystem_cbi.h @@ -257,7 +257,7 @@ typedef struct alrm_ar alrm_ar_t; static inline alrm_ar_t *alloc_alrm_ar(int as, size_t extra) { - alrm_ar_t *ret = xcalloc(1, sizeof(alrm_t) + extra); + alrm_ar_t *ret = (alrm_ar_t*)xcalloc(1, sizeof(alrm_t) + extra); if (ret) { memcpy(ret, &(alrm_ar_t const) { diff --git a/drivers/al175.c b/drivers/al175.c index 026bd9f1b0..66c2cb9a92 100644 --- a/drivers/al175.c +++ b/drivers/al175.c @@ -118,7 +118,7 @@ static raw_data_t raw_xmalloc(size_t size) { raw_data_t data; - data.buf = xmalloc(size); + data.buf = (byte_t *)xmalloc(size); data.buf_size = size; data.begin = data.buf; diff --git a/drivers/apc_modbus.c b/drivers/apc_modbus.c index 2dfc5f14f0..d5198426b7 100644 --- a/drivers/apc_modbus.c +++ b/drivers/apc_modbus.c @@ -834,46 +834,46 @@ typedef struct { /* Values that only need to be updated once on startup */ static apc_modbus_register_t apc_modbus_register_map_inventory[] = { - { "ups.firmware", 516, 8, APC_VT_STRING, 0, NULL, "%s", 0, NULL }, - { "ups.model", 532, 16, APC_VT_STRING, 0, NULL, "%s", 0, NULL }, /* also device.model, filled automatically */ - { "ups.serial", 564, 8, APC_VT_STRING, 0, NULL, "%s", 0, NULL }, /* also device.serial, filled automatically */ - { "ups.power.nominal", 588, 1, APC_VT_UINT, 0, &_apc_modbus_double_conversion, "%.0f", 0, &power_nominal }, - { "ups.realpower.nominal", 589, 1, APC_VT_UINT, 0, &_apc_modbus_double_conversion, "%.0f", 0, &realpower_nominal }, - { "ups.mfr.date", 591, 1, APC_VT_UINT, 0, &_apc_modbus_date_conversion, NULL, 0, NULL }, - { "battery.date", 595, 1, APC_VT_UINT, APC_VF_RW, &_apc_modbus_date_conversion, NULL, 0, NULL }, - { "ups.id", 596, 8, APC_VT_STRING, APC_VF_RW, NULL, "%s", 0, NULL }, - { "outlet.group.0.name", 604, 8, APC_VT_STRING, APC_VF_RW, NULL, "%s", 0, NULL }, - { "outlet.group.1.name", 612, 8, APC_VT_STRING, APC_VF_RW, NULL, "%s", 0, NULL }, - { "outlet.group.2.name", 620, 8, APC_VT_STRING, APC_VF_RW, NULL, "%s", 0, NULL }, - { "outlet.group.3.name", 628, 8, APC_VT_STRING, APC_VF_RW, NULL, "%s", 0, NULL }, - { NULL, 0, 0, 0, 0, NULL, NULL, 0.0f, NULL } + { "ups.firmware", 516, 8, APC_VT_STRING, APC_VF_NONE, NULL, "%s", 0, NULL }, + { "ups.model", 532, 16, APC_VT_STRING, APC_VF_NONE, NULL, "%s", 0, NULL }, /* also device.model, filled automatically */ + { "ups.serial", 564, 8, APC_VT_STRING, APC_VF_NONE, NULL, "%s", 0, NULL }, /* also device.serial, filled automatically */ + { "ups.power.nominal", 588, 1, APC_VT_UINT, APC_VF_NONE, &_apc_modbus_double_conversion, "%.0f", 0, &power_nominal }, + { "ups.realpower.nominal", 589, 1, APC_VT_UINT, APC_VF_NONE, &_apc_modbus_double_conversion, "%.0f", 0, &realpower_nominal }, + { "ups.mfr.date", 591, 1, APC_VT_UINT, APC_VF_NONE, &_apc_modbus_date_conversion, NULL, 0, NULL }, + { "battery.date", 595, 1, APC_VT_UINT, APC_VF_RW, &_apc_modbus_date_conversion, NULL, 0, NULL }, + { "ups.id", 596, 8, APC_VT_STRING, APC_VF_RW, NULL, "%s", 0, NULL }, + { "outlet.group.0.name", 604, 8, APC_VT_STRING, APC_VF_RW, NULL, "%s", 0, NULL }, + { "outlet.group.1.name", 612, 8, APC_VT_STRING, APC_VF_RW, NULL, "%s", 0, NULL }, + { "outlet.group.2.name", 620, 8, APC_VT_STRING, APC_VF_RW, NULL, "%s", 0, NULL }, + { "outlet.group.3.name", 628, 8, APC_VT_STRING, APC_VF_RW, NULL, "%s", 0, NULL }, + { NULL, 0, 0, APC_VT_INT, APC_VF_NONE, NULL, NULL, 0.0f, NULL } }; static apc_modbus_register_t apc_modbus_register_map_status[] = { - { "input.transfer.reason", 2, 1, APC_VT_UINT, 0, &_apc_modbus_status_change_cause_conversion, NULL, 0, NULL }, - { "ups.test.result", 23, 1, APC_VT_UINT, 0, &_apc_modbus_battery_test_status_conversion, NULL, 0, NULL }, - { NULL, 0, 0, 0, 0, NULL, NULL, 0.0f, NULL } + { "input.transfer.reason", 2, 1, APC_VT_UINT, APC_VF_NONE, &_apc_modbus_status_change_cause_conversion, NULL, 0, NULL }, + { "ups.test.result", 23, 1, APC_VT_UINT, APC_VF_NONE, &_apc_modbus_battery_test_status_conversion, NULL, 0, NULL }, + { NULL, 0, 0, APC_VT_INT, APC_VF_NONE, NULL, NULL, 0.0f, NULL } }; static apc_modbus_register_t apc_modbus_register_map_dynamic[] = { - { "battery.runtime", 128, 2, APC_VT_UINT, 0, NULL, "%" PRIu64, 0, NULL }, - { "battery.charge", 130, 1, APC_VT_UINT, 0, &_apc_modbus_double_conversion, "%.2f", 9, NULL }, - { "battery.voltage", 131, 1, APC_VT_INT, 0, &_apc_modbus_double_conversion, "%.2f", 5, NULL }, - { "battery.date.maintenance", 133, 1, APC_VT_UINT, 0, &_apc_modbus_date_conversion, NULL, 0, NULL }, - { "battery.temperature", 135, 1, APC_VT_INT, 0, &_apc_modbus_double_conversion, "%.2f", 7, NULL }, - { "ups.load", 136, 1, APC_VT_UINT, 0, &_apc_modbus_double_conversion, "%.2f", 8, NULL }, - { "ups.realpower", 136, 1, APC_VT_UINT, 0, &_apc_modbus_power_conversion, "%.2f", 8, &realpower_nominal }, - { "ups.power", 138, 1, APC_VT_UINT, 0, &_apc_modbus_power_conversion, "%.2f", 8, &power_nominal }, - { "output.current", 140, 1, APC_VT_UINT, 0, &_apc_modbus_double_conversion, "%.2f", 5, NULL }, - { "output.voltage", 142, 1, APC_VT_UINT, 0, &_apc_modbus_double_conversion, "%.2f", 6, NULL }, - { "output.frequency", 144, 1, APC_VT_UINT, 0, &_apc_modbus_double_conversion, "%.2f", 7, NULL }, - { "experimental.output.energy", 145, 2, APC_VT_UINT, 0, NULL, "%" PRIu64, 0, NULL }, - { "input.voltage", 151, 1, APC_VT_UINT, 0, &_apc_modbus_voltage_conversion, "%.2f", 6, NULL }, - { "ups.efficiency", 154, 1, APC_VT_INT, 0, &_apc_modbus_efficiency_conversion, "%.1f", 7, NULL }, - { "ups.timer.shutdown", 155, 1, APC_VT_INT, 0, NULL, "%" PRIi64, 0, NULL }, - { "ups.timer.start", 156, 1, APC_VT_INT, 0, NULL, "%" PRIi64, 0, NULL }, - { "ups.timer.reboot", 157, 2, APC_VT_INT, 0, NULL, "%" PRIi64, 0, NULL }, - { NULL, 0, 0, 0, 0, NULL, NULL, 0.0f, NULL } + { "battery.runtime", 128, 2, APC_VT_UINT, APC_VF_NONE, NULL, "%" PRIu64, 0, NULL }, + { "battery.charge", 130, 1, APC_VT_UINT, APC_VF_NONE, &_apc_modbus_double_conversion, "%.2f", 9, NULL }, + { "battery.voltage", 131, 1, APC_VT_INT, APC_VF_NONE, &_apc_modbus_double_conversion, "%.2f", 5, NULL }, + { "battery.date.maintenance", 133, 1, APC_VT_UINT, APC_VF_NONE, &_apc_modbus_date_conversion, NULL, 0, NULL }, + { "battery.temperature", 135, 1, APC_VT_INT, APC_VF_NONE, &_apc_modbus_double_conversion, "%.2f", 7, NULL }, + { "ups.load", 136, 1, APC_VT_UINT, APC_VF_NONE, &_apc_modbus_double_conversion, "%.2f", 8, NULL }, + { "ups.realpower", 136, 1, APC_VT_UINT, APC_VF_NONE, &_apc_modbus_power_conversion, "%.2f", 8, &realpower_nominal }, + { "ups.power", 138, 1, APC_VT_UINT, APC_VF_NONE, &_apc_modbus_power_conversion, "%.2f", 8, &power_nominal }, + { "output.current", 140, 1, APC_VT_UINT, APC_VF_NONE, &_apc_modbus_double_conversion, "%.2f", 5, NULL }, + { "output.voltage", 142, 1, APC_VT_UINT, APC_VF_NONE, &_apc_modbus_double_conversion, "%.2f", 6, NULL }, + { "output.frequency", 144, 1, APC_VT_UINT, APC_VF_NONE, &_apc_modbus_double_conversion, "%.2f", 7, NULL }, + { "experimental.output.energy", 145, 2, APC_VT_UINT, APC_VF_NONE, NULL, "%" PRIu64, 0, NULL }, + { "input.voltage", 151, 1, APC_VT_UINT, APC_VF_NONE, &_apc_modbus_voltage_conversion, "%.2f", 6, NULL }, + { "ups.efficiency", 154, 1, APC_VT_INT, APC_VF_NONE, &_apc_modbus_efficiency_conversion, "%.1f", 7, NULL }, + { "ups.timer.shutdown", 155, 1, APC_VT_INT, APC_VF_NONE, NULL, "%" PRIi64, 0, NULL }, + { "ups.timer.start", 156, 1, APC_VT_INT, APC_VF_NONE, NULL, "%" PRIi64, 0, NULL }, + { "ups.timer.reboot", 157, 2, APC_VT_INT, APC_VF_NONE, NULL, "%" PRIi64, 0, NULL }, + { NULL, 0, 0, APC_VT_INT, APC_VF_NONE, NULL, NULL, 0.0f, NULL } }; static apc_modbus_register_t apc_modbus_register_map_static[] = { @@ -894,7 +894,7 @@ static apc_modbus_register_t apc_modbus_register_map_static[] = { { "outlet.group.3.delay.shutdown", 1044, 1, APC_VT_INT, APC_VF_RW, NULL, "%" PRIi64, 0, NULL }, { "outlet.group.3.delay.start", 1045, 1, APC_VT_INT, APC_VF_RW, NULL, "%" PRIi64, 0, NULL }, { "outlet.group.3.delay.reboot", 1046, 2, APC_VT_INT, APC_VF_RW, NULL, "%" PRIi64, 0, NULL }, - { NULL, 0, 0, 0, 0, NULL, NULL, 0.0f, NULL } + { NULL, 0, 0, APC_VT_INT, APC_VF_NONE, NULL, NULL, 0.0f, NULL } }; static apc_modbus_register_t* apc_modbus_register_maps[] = { diff --git a/drivers/apcsmart.c b/drivers/apcsmart.c index b0f43e1222..5d96dd052c 100644 --- a/drivers/apcsmart.c +++ b/drivers/apcsmart.c @@ -708,7 +708,7 @@ static void apc_dstate_delinfo(apc_vartab_t *vt, int skip) return; } - if ( !(name = xmalloc(sizeof(char) * vt->nlen0)) ) { + if ( !(name = (char *)xmalloc(sizeof(char) * vt->nlen0)) ) { upslogx(LOG_ERR, "apc_dstate_delinfo() failed to allocate buffer"); return; } @@ -740,12 +740,12 @@ static void apc_dstate_setinfo(apc_vartab_t *vt, const char *upsval) return; } - if ( !(name = xmalloc(sizeof(char) * vt->nlen0)) ) { + if ( !(name = (char *)xmalloc(sizeof(char) * vt->nlen0)) ) { upslogx(LOG_ERR, "apc_dstate_setinfo() failed to allocate buffer"); return; } - if ( !(temp = xmalloc(sizeof(char) * (upsvallen + 2))) ) { + if ( !(temp = (char *)xmalloc(sizeof(char) * (upsvallen + 2))) ) { /* +2 seems like an overkill, but helps hush compiler warnings */ upslogx(LOG_ERR, "apc_dstate_setinfo() failed to allocate buffer"); free(name); @@ -1586,7 +1586,7 @@ static int sdcmd_AT(const void *str) { ssize_t ret; size_t cnt, padto, i; - const char *awd = str; + const char *awd = (const char *)str; char temp[APC_SBUF], *ptr; memset(temp, '\0', sizeof(temp)); diff --git a/drivers/bcmxcp.c b/drivers/bcmxcp.c index d66d38f6c2..d4695ed6ee 100644 --- a/drivers/bcmxcp.c +++ b/drivers/bcmxcp.c @@ -1419,7 +1419,7 @@ void upsdrv_initinfo(void) /* No overflow checks, len value is byte-sized here */ buf = len * 11; - pTmp = xmalloc(buf+1); + pTmp = (char *)xmalloc(buf+1); pTmp[0] = 0; /* If there is one or more CPU number, get it */ @@ -1471,7 +1471,7 @@ void upsdrv_initinfo(void) len = answer[iIndex++]; /* Extract and reformat the model string */ - pTmp = xmalloc(len+15); + pTmp = (char *)xmalloc(len+15); snprintf(pTmp, len + 1, "%s", answer + iIndex); pTmp[len+1] = 0; iIndex += len; diff --git a/drivers/bcmxcp_usb.c b/drivers/bcmxcp_usb.c index aed7f22842..6a726bc263 100644 --- a/drivers/bcmxcp_usb.c +++ b/drivers/bcmxcp_usb.c @@ -53,7 +53,7 @@ static int (*usb_set_descriptor)(usb_dev_handle *udev, unsigned char type, static int usb_set_powerware(usb_dev_handle *udev, unsigned char type, unsigned char index, void *buf, size_t size) { assert (size < INT_MAX); - return usb_control_msg(udev, USB_ENDPOINT_OUT, USB_REQ_SET_DESCRIPTOR, (type << 8) + index, 0, buf, (int)size, 1000); + return usb_control_msg(udev, USB_ENDPOINT_OUT, USB_REQ_SET_DESCRIPTOR, (type << 8) + index, 0, (usb_ctrl_charbuf)buf, (int)size, 1000); } static void *powerware_ups(USBDevice_t *device) { @@ -69,7 +69,7 @@ static int usb_set_phoenixtec(usb_dev_handle *udev, unsigned char type, unsigned NUT_UNUSED_VARIABLE(index); NUT_UNUSED_VARIABLE(type); assert (size < INT_MAX); - return usb_control_msg(udev, 0x42, 0x0d, (0x00 << 8) + 0x0, 0, buf, (int)size, 1000); + return usb_control_msg(udev, 0x42, 0x0d, (0x00 << 8) + 0x0, 0, (usb_ctrl_charbuf)buf, (int)size, 1000); } static void *phoenixtec_ups(USBDevice_t *device) { @@ -233,7 +233,7 @@ ssize_t get_answer(unsigned char *data, unsigned char command) if ( my_buf[0] != PW_COMMAND_START_BYTE ) { upsdebugx(2, "get_answer: wrong header 0xab vs. %02x", my_buf[0]); /* Sometime we read something wrong. bad cables? bad ports? */ - my_buf = memchr(my_buf, PW_COMMAND_START_BYTE, bytes_read); + my_buf = (unsigned char*)memchr(my_buf, PW_COMMAND_START_BYTE, bytes_read); if (!my_buf) return -1; } @@ -302,7 +302,7 @@ ssize_t get_answer(unsigned char *data, unsigned char command) tail = (ssize_t)bytes_read; tail -= (ssize_t)(length + PW_HEADER_SIZE); if (tail > 0) - my_buf = memmove(&buf[0], my_buf + length + PW_HEADER_SIZE, (size_t)tail); + my_buf = (unsigned char*)memmove(&buf[0], my_buf + length + PW_HEADER_SIZE, (size_t)tail); else if (tail == 0) my_buf = &buf[0]; else { /* if (tail < 0) */ diff --git a/drivers/common_voltronic-crc.c b/drivers/common_voltronic-crc.c index 2e05603883..48af385655 100644 --- a/drivers/common_voltronic-crc.c +++ b/drivers/common_voltronic-crc.c @@ -106,7 +106,7 @@ unsigned short common_voltronic_crc_compute(const char *input, const size_t len) unsigned short common_voltronic_crc_calc(const char *input, const size_t inputlen) { size_t len; - char *cr = memchr(input, '\r', inputlen); + char *cr = (char*)memchr(input, '\r', inputlen); /* No CR, fall back to string length (and hope *input* doesn't contain inner '\0's) */ if (cr == NULL) @@ -127,7 +127,7 @@ int common_voltronic_crc_calc_and_add(const char *input, const size_t inputlen, { unsigned short crc, crc_MSB, crc_LSB; size_t len; - char *cr = memchr(input, '\r', inputlen); + char *cr = (char*)memchr(input, '\r', inputlen); /* No CR, fall back to string length (and hope *input* doesn't contain inner '\0's) */ if (cr == NULL) @@ -173,7 +173,7 @@ int common_voltronic_crc_calc_and_add(const char *input, const size_t inputlen, int common_voltronic_crc_calc_and_add_m(char *input, const size_t inputlen) { int len; - char *buf = xcalloc(inputlen, sizeof(char)); + char *buf = (char*)xcalloc(inputlen, sizeof(char)); if (!buf) return -1; @@ -203,7 +203,7 @@ int common_voltronic_crc_calc_and_add_m(char *input, const size_t inputlen) int common_voltronic_crc_check(const char *input, const size_t inputlen) { unsigned short crc, crc_MSB, crc_LSB; - char *cr = memchr(input, '\r', inputlen); + char *cr = (char*)memchr(input, '\r', inputlen); size_t len; /* No CR, fall back to string length (and hope *input* doesn't contain inner '\0's) */ @@ -244,7 +244,7 @@ int common_voltronic_crc_check_and_remove(const char *input, const size_t inputl /* *input* successfully validated -> remove CRC bytes */ - cr = memchr(input, '\r', inputlen); + cr = (char*)memchr(input, '\r', inputlen); /* No CR, fall back to string length */ if (cr == NULL) len = strlen(input); @@ -277,7 +277,7 @@ int common_voltronic_crc_check_and_remove(const char *input, const size_t inputl int common_voltronic_crc_check_and_remove_m(char *input, const size_t inputlen) { int len; - char *buf = xcalloc(inputlen, sizeof(char)); + char *buf = (char*)xcalloc(inputlen, sizeof(char)); if (!buf) return -1; diff --git a/drivers/dummy-ups.c b/drivers/dummy-ups.c index 4b3f410d07..a4b455b64a 100644 --- a/drivers/dummy-ups.c +++ b/drivers/dummy-ups.c @@ -156,7 +156,7 @@ void upsdrv_initinfo(void) fatalx(EXIT_FAILURE, "Error: invalid UPS definition.\nRequired format: upsname[@hostname[:port]]"); } /* Connect to the target */ - ups = xmalloc(sizeof(*ups)); + ups = (UPSCONN_t *)xmalloc(sizeof(*ups)); if (upscli_connect(ups, hostname, port, UPSCLI_CONN_TRYSSL) < 0) { if(repeater_disable_strict_start == 1) diff --git a/drivers/ecoflow-hid.c b/drivers/ecoflow-hid.c index 28119dc9bc..5c4b47cb05 100644 --- a/drivers/ecoflow-hid.c +++ b/drivers/ecoflow-hid.c @@ -73,7 +73,7 @@ static const char *ecoflow_battery_runtime_conversion(double hid_value) { converted_runtime = hid_value * 60.0; /* Allocate memory for string representation */ - converted_value = xmalloc(HU_INFOSIZE); + converted_value = (char*)xmalloc(HU_INFOSIZE); snprintf(converted_value, HU_INFOSIZE, "%.0f", converted_runtime); return converted_value; } diff --git a/drivers/failover.c b/drivers/failover.c index a8335cf993..b79edb65b7 100644 --- a/drivers/failover.c +++ b/drivers/failover.c @@ -595,10 +595,10 @@ static void parse_port_argument(void) continue; } - new_ups = xcalloc(1, sizeof(**ups_list)); + new_ups = (ups_device_t *)xcalloc(1, sizeof(**ups_list)); new_ups->socketname = xstrdup(token); - ups_list = xrealloc(ups_list, sizeof(*ups_list) * (ups_count + 1)); + ups_list = (ups_device_t **)xrealloc(ups_list, sizeof(*ups_list) * (ups_count + 1)); ups_list[ups_count] = new_ups; ups_count++; @@ -1428,7 +1428,7 @@ static ups_device_t *get_primary_candidate(void) __func__, ups->socketname, priority, rt, rt_low); } - ups->priority = priority; + ups->priority = (ups_priority_t)priority; } ups_primary_count = primaries; @@ -1707,12 +1707,12 @@ static int ups_add_cmd(ups_device_t *ups, const char *val) } if (ups->cmd_count >= ups->cmd_allocs) { - ups->cmd_list = xrealloc(ups->cmd_list, sizeof(*ups->cmd_list) * (ups->cmd_allocs + CMD_ALLOC_BATCH)); + ups->cmd_list = (ups_cmd_t **)xrealloc(ups->cmd_list, sizeof(*ups->cmd_list) * (ups->cmd_allocs + CMD_ALLOC_BATCH)); memset(ups->cmd_list + ups->cmd_allocs, 0, sizeof(*ups->cmd_list) * CMD_ALLOC_BATCH); ups->cmd_allocs = ups->cmd_allocs + CMD_ALLOC_BATCH; } - new_cmd = xcalloc(1, sizeof(**ups->cmd_list)); + new_cmd = (ups_cmd_t *)xcalloc(1, sizeof(**ups->cmd_list)); new_cmd->value = xstrdup(val); new_cmd->needs_export = 1; @@ -1756,7 +1756,7 @@ static int ups_del_cmd(ups_device_t *ups, const char *val) ups->cmd_allocs = 0; } else if (ups->cmd_count % CMD_ALLOC_BATCH == 0) { - ups->cmd_list = xrealloc(ups->cmd_list, sizeof(*ups->cmd_list) * ups->cmd_count); + ups->cmd_list = (ups_cmd_t **)xrealloc(ups->cmd_list, sizeof(*ups->cmd_list) * ups->cmd_count); ups->cmd_allocs = ups->cmd_count; } @@ -1811,12 +1811,12 @@ static int ups_set_var(ups_device_t *ups, const char *key, const char *value) } if (ups->var_count >= ups->var_allocs) { - ups->var_list = xrealloc(ups->var_list, sizeof(*ups->var_list) * (ups->var_allocs + VAR_ALLOC_BATCH)); + ups->var_list = (ups_var_t **)xrealloc(ups->var_list, sizeof(*ups->var_list) * (ups->var_allocs + VAR_ALLOC_BATCH)); memset(ups->var_list + ups->var_allocs, 0, sizeof(*ups->var_list) * VAR_ALLOC_BATCH); ups->var_allocs = ups->var_allocs + VAR_ALLOC_BATCH; } - new_var = xcalloc(1, sizeof(**ups->var_list)); + new_var = (ups_var_t *)xcalloc(1, sizeof(**ups->var_list)); new_var->key = xstrdup(key); new_var->value = xstrdup(value); new_var->needs_export = 1; @@ -1877,7 +1877,7 @@ static int ups_del_var(ups_device_t *ups, const char *key) ups->var_allocs = 0; } else if (ups->var_count % VAR_ALLOC_BATCH == 0) { - ups->var_list = xrealloc(ups->var_list, sizeof(*ups->var_list) * ups->var_count); + ups->var_list = (ups_var_t **)xrealloc(ups->var_list, sizeof(*ups->var_list) * ups->var_count); ups->var_allocs = ups->var_count; } @@ -1970,12 +1970,12 @@ static int ups_add_range(ups_device_t *ups, const char *key, const int min, cons } if (var->range_count >= var->range_allocs) { - var->range_list = xrealloc(var->range_list, sizeof(*var->range_list) * (var->range_allocs + SUBVAR_ALLOC_BATCH)); + var->range_list = (var_range_t **)xrealloc(var->range_list, sizeof(*var->range_list) * (var->range_allocs + SUBVAR_ALLOC_BATCH)); memset(var->range_list + var->range_allocs, 0, sizeof(*var->range_list) * SUBVAR_ALLOC_BATCH); var->range_allocs = var->range_allocs + SUBVAR_ALLOC_BATCH; } - new_range = xcalloc(1, sizeof(**var->range_list)); + new_range = (var_range_t *)xcalloc(1, sizeof(**var->range_list)); new_range->min = min; new_range->max = max; @@ -2029,7 +2029,7 @@ static int ups_del_range(ups_device_t *ups, const char *key, const int min, cons var->range_allocs = 0; } else if (var->range_count % SUBVAR_ALLOC_BATCH == 0) { - var->range_list = xrealloc(var->range_list, sizeof(*var->range_list) * var->range_count); + var->range_list = (var_range_t **)xrealloc(var->range_list, sizeof(*var->range_list) * var->range_count); var->range_allocs = var->range_count; } @@ -2062,7 +2062,7 @@ static int ups_add_enum(ups_device_t *ups, const char *key, const char *val) } if (var->enum_count >= var->enum_allocs) { - var->enum_list = xrealloc(var->enum_list, sizeof(*var->enum_list) * (var->enum_allocs + SUBVAR_ALLOC_BATCH)); + var->enum_list = (char **)xrealloc(var->enum_list, sizeof(*var->enum_list) * (var->enum_allocs + SUBVAR_ALLOC_BATCH)); memset(var->enum_list + var->enum_allocs, 0, sizeof(*var->enum_list) * SUBVAR_ALLOC_BATCH); var->enum_allocs = var->enum_allocs + SUBVAR_ALLOC_BATCH; } @@ -2118,7 +2118,7 @@ static int ups_del_enum(ups_device_t *ups, const char *key, const char *val) var->enum_allocs = 0; } else if (var->enum_count % SUBVAR_ALLOC_BATCH == 0) { - var->enum_list = xrealloc(var->enum_list, sizeof(*var->enum_list) * var->enum_count); + var->enum_list = (char **)xrealloc(var->enum_list, sizeof(*var->enum_list) * var->enum_count); var->enum_allocs = var->enum_count; } @@ -2346,7 +2346,7 @@ static ssize_t csv_arg_to_array(const char *arg, const char *argcsv, char ***arr str = xstrdup(token); - *array = xrealloc(*array, sizeof(**array) * (*countvar + 1)); + *array = (char **)xrealloc(*array, sizeof(**array) * (*countvar + 1)); (*array)[*countvar] = str; (*countvar)++; diff --git a/drivers/generic_modbus.c b/drivers/generic_modbus.c index bf69925ae8..2f80f45695 100644 --- a/drivers/generic_modbus.c +++ b/drivers/generic_modbus.c @@ -688,7 +688,7 @@ int get_signal_state(devstate_t state) { int rval = -1; int reg_val; - regtype_t rtype = 0; /* register type */ + regtype_t rtype = (regtype_t)0; /* register type */ int addr = -1; /* register address */ /* assign register address and type */ @@ -855,7 +855,7 @@ void get_config_vars(void) /* check if OL register type is set and get the value otherwise set to INPUT_B */ if (testvar("OL_regtype")) { - sigar[OL_T].type = (unsigned int)strtol(getval("OL_regtype"), NULL, 10); + sigar[OL_T].type = (regtype_t)(unsigned int)strtol(getval("OL_regtype"), NULL, 10); if (sigar[OL_T].type < COIL || sigar[OL_T].type > HOLDING) { sigar[OL_T].type = INPUT_B; } @@ -876,7 +876,7 @@ void get_config_vars(void) /* check if OB register type is set and get the value otherwise set to INPUT_B */ if (testvar("OB_regtype")) { - sigar[OB_T].type = (unsigned int)strtol(getval("OB_regtype"), NULL, 10); + sigar[OB_T].type = (regtype_t)(unsigned int)strtol(getval("OB_regtype"), NULL, 10); if (sigar[OB_T].type < COIL || sigar[OB_T].type > HOLDING) { sigar[OB_T].type = INPUT_B; } @@ -897,7 +897,7 @@ void get_config_vars(void) /* check if LB register type is set and get the value otherwise set to INPUT_B */ if (testvar("LB_regtype")) { - sigar[LB_T].type = (unsigned int)strtol(getval("OB_regtype"), NULL, 10); + sigar[LB_T].type = (regtype_t)(unsigned int)strtol(getval("OB_regtype"), NULL, 10); if (sigar[LB_T].type < COIL || sigar[LB_T].type > HOLDING) { sigar[LB_T].type = INPUT_B; } @@ -918,7 +918,7 @@ void get_config_vars(void) /* check if HB register type is set and get the value otherwise set to INPUT_B */ if (testvar("HB_regtype")) { - sigar[HB_T].type = (unsigned int)strtol(getval("HB_regtype"), NULL, 10); + sigar[HB_T].type = (regtype_t)(unsigned int)strtol(getval("HB_regtype"), NULL, 10); if (sigar[HB_T].type < COIL || sigar[HB_T].type > HOLDING) { sigar[HB_T].type = INPUT_B; } @@ -939,7 +939,7 @@ void get_config_vars(void) /* check if RB register type is set and get the value otherwise set to INPUT_B */ if (testvar("RB_regtype")) { - sigar[RB_T].type = (unsigned int)strtol(getval("RB_regtype"), NULL, 10); + sigar[RB_T].type = (regtype_t)(unsigned int)strtol(getval("RB_regtype"), NULL, 10); if (sigar[RB_T].type < COIL || sigar[RB_T].type > HOLDING) { sigar[RB_T].type = INPUT_B; } @@ -960,7 +960,7 @@ void get_config_vars(void) /* check if CHRG register type is set and get the value otherwise set to INPUT_B */ if (testvar("CHRG_regtype")) { - sigar[CHRG_T].type = (unsigned int)strtol(getval("CHRG_regtype"), NULL, 10); + sigar[CHRG_T].type = (regtype_t)(unsigned int)strtol(getval("CHRG_regtype"), NULL, 10); if (sigar[CHRG_T].type < COIL || sigar[CHRG_T].type > HOLDING) { sigar[CHRG_T].type = INPUT_B; } @@ -981,7 +981,7 @@ void get_config_vars(void) /* check if DISCHRG register type is set and get the value otherwise set to INPUT_B */ if (testvar("DISCHRG_regtype")) { - sigar[DISCHRG_T].type = (unsigned int)strtol(getval("DISCHRG_regtype"), NULL, 10); + sigar[DISCHRG_T].type = (regtype_t)(unsigned int)strtol(getval("DISCHRG_regtype"), NULL, 10); if (sigar[DISCHRG_T].type < COIL || sigar[DISCHRG_T].type > HOLDING) { sigar[DISCHRG_T].type = INPUT_B; } @@ -1002,7 +1002,7 @@ void get_config_vars(void) /* check if FSD register type is set and get the value otherwise set to COIL */ if (testvar("FSD_regtype")) { - sigar[FSD_T].type = (unsigned int)strtol(getval("FSD_regtype"), NULL, 10); + sigar[FSD_T].type = (regtype_t)(unsigned int)strtol(getval("FSD_regtype"), NULL, 10); if (sigar[FSD_T].type < COIL || sigar[FSD_T].type > HOLDING) { sigar[FSD_T].type = COIL; } @@ -1068,7 +1068,7 @@ modbus_t *modbus_new(const char *port) upslogx(LOG_ERR, "modbus_new_rtu: Unable to open serial port context\n"); } } else if ((sp = strchr(port, ':')) != NULL) { - char *tcp_port = xmalloc(sizeof(sp)); + char *tcp_port = (char*)xmalloc(sizeof(sp)); strncpy(tcp_port, sp + 1, sizeof(sp)); *sp = '\0'; mb = modbus_new_tcp(port, (int)strtoul(tcp_port, NULL, 10)); diff --git a/drivers/hidparser.c b/drivers/hidparser.c index bce04a32e7..87c8dab53a 100644 --- a/drivers/hidparser.c +++ b/drivers/hidparser.c @@ -677,7 +677,7 @@ HIDDesc_t *Parse_ReportDesc(const usb_ctrl_charbuf ReportDesc, const usb_ctrl_ch HIDDesc_t *pDesc_var; HIDParser_t *parser; - pDesc_var = calloc(1, sizeof(*pDesc_var)); + pDesc_var = (HIDDesc_t *)calloc(1, sizeof(*pDesc_var)); #if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE) ) # pragma GCC diagnostic push #endif @@ -712,13 +712,13 @@ HIDDesc_t *Parse_ReportDesc(const usb_ctrl_charbuf ReportDesc, const usb_ctrl_ch # pragma GCC diagnostic pop #endif - pDesc_var->item = calloc(MAX_REPORT, sizeof(*pDesc_var->item)); + pDesc_var->item = (HIDData_t *)calloc(MAX_REPORT, sizeof(*pDesc_var->item)); if (!pDesc_var->item) { Free_ReportDesc(pDesc_var); return NULL; } - parser = calloc(1, sizeof(*parser)); + parser = (HIDParser_t *)calloc(1, sizeof(*parser)); if (!parser) { Free_ReportDesc(pDesc_var); return NULL; @@ -762,7 +762,7 @@ HIDDesc_t *Parse_ReportDesc(const usb_ctrl_charbuf ReportDesc, const usb_ctrl_ch return NULL; } - pDesc_var->item = realloc(pDesc_var->item, pDesc_var->nitems * sizeof(*pDesc_var->item)); + pDesc_var->item = (HIDData_t *)realloc(pDesc_var->item, pDesc_var->nitems * sizeof(*pDesc_var->item)); return pDesc_var; } diff --git a/drivers/libhid.c b/drivers/libhid.c index 0ead97b34c..42509e36c5 100644 --- a/drivers/libhid.c +++ b/drivers/libhid.c @@ -111,7 +111,7 @@ reportbuf_t *new_report_buffer(HIDDesc_t *arg_pDesc) if (!arg_pDesc) return NULL; - rbuf = calloc(1, sizeof(*rbuf)); + rbuf = (reportbuf_t *)calloc(1, sizeof(*rbuf)); if (!rbuf) { return NULL; } @@ -135,7 +135,7 @@ reportbuf_t *new_report_buffer(HIDDesc_t *arg_pDesc) continue; } - rbuf->data[id] = calloc(rbuf->len[id], sizeof(*(rbuf->data[id]))); + rbuf->data[id] = (unsigned char *)calloc(rbuf->len[id], sizeof(*(rbuf->data[id]))); if (rbuf->data[id]) continue; diff --git a/drivers/libshut.c b/drivers/libshut.c index ec68db5eda..803727308e 100644 --- a/drivers/libshut.c +++ b/drivers/libshut.c @@ -876,7 +876,7 @@ int shut_synchronise(usb_dev_handle arg_upsfd) { int retCode = 0; unsigned char c = SHUT_SYNC_OFF, reply; - int try; + int attempt; upsdebugx (2, "entering shut_synchronise()"); reply = '\0'; @@ -898,9 +898,9 @@ int shut_synchronise(usb_dev_handle arg_upsfd) */ /* Sync with the UPS according to notification */ - for (try = 0; try < MAX_TRY; try++) + for (attempt = 0; attempt < MAX_TRY; attempt++) { - upsdebugx (3, "Syncing communication (try %i)", try); + upsdebugx (3, "Syncing communication (try %i)", attempt); if ((ser_send_char(arg_upsfd, c)) == -1) { @@ -1157,7 +1157,7 @@ static int shut_get_descriptor( type, size); return shut_control_msg(arg_upsfd, USB_ENDPOINT_IN+(type>=USB_DT_HID?1:0), - USB_REQ_GET_DESCRIPTOR, (type << 8) + index, 0, buf, size, SHUT_TIMEOUT); + USB_REQ_GET_DESCRIPTOR, (type << 8) + index, 0, (usb_ctrl_charbuf)buf, size, SHUT_TIMEOUT); } /* Take care of a SHUT transfer (sending and receiving data) */ diff --git a/drivers/main.c b/drivers/main.c index 9a8a4fc043..9f42910978 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -799,7 +799,7 @@ static void do_addvar(int vartype, const char *name, const char *desc, int reloa tmp = tmp->next; } - tmp = xmalloc(sizeof(vartab_t)); + tmp = (vartab_t *)xmalloc(sizeof(vartab_t)); tmp->vartype = vartype; tmp->var = xstrdup(name); diff --git a/drivers/mge-hid.c b/drivers/mge-hid.c index 07863bd484..265b2e1f97 100644 --- a/drivers/mge-hid.c +++ b/drivers/mge-hid.c @@ -1971,7 +1971,7 @@ static models_name_t mge_model_names [] = { "GALAXY", "3000_30", MGE_DEFAULT, "Galaxy 3000 30 kVA" }, /* end of structure. */ - { NULL, NULL, 0, NULL } + { NULL, NULL, MGE_DEFAULT_OFFLINE, NULL } }; diff --git a/drivers/microdowell.c b/drivers/microdowell.c index fd522a118a..62d020ca7d 100644 --- a/drivers/microdowell.c +++ b/drivers/microdowell.c @@ -270,7 +270,7 @@ static unsigned char * CmdSerial(unsigned char *OutBuffer, size_t Len, unsigned if (ups.ErrCount > 100) ups.ErrCount = 100 ; } - return(NULL) ; /* There have been errors in the reading of the data */ + return((unsigned char *)NULL) ; /* There have been errors in the reading of the data */ } static int detect_hardware(void) diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index a7dbfe0954..5b08856c7f 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -945,7 +945,7 @@ static int write_serial_int(int fd, const unsigned int *data, size_t size) { uint8_t *message = NULL; size_t i = 0; - message = xcalloc(size, sizeof(uint8_t)); + message = (uint8_t *)xcalloc(size, sizeof(uint8_t)); for (i = 0; i < size; i++) { message[i] = (uint8_t)data[i]; /* //upsdebugx(5, "%d %c %u %d %c %u", message[i], message[i], data[i], data[i]); */ diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index ea2a695a82..06588bb08f 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -333,7 +333,7 @@ static void analyze_mapping_usage(void) { return; } - unused_names = xcalloc(unused_bufsize, sizeof(char)); + unused_names = (char *)xcalloc(unused_bufsize, sizeof(char)); for (item = subdriver->qx2nut; item->info_type != NULL; item++) { if (!item) @@ -385,7 +385,7 @@ static void analyze_mapping_usage(void) { if (*pBufSize < SIZE_MAX - LARGEBUF) { *pBufSize = *pBufSize + LARGEBUF; upsdebugx(1, "%s: buffer overflowed, trying to re-allocate as %" PRIuSIZE, __func__, *pBufSize); - *pNames = realloc(*pNames, *pBufSize); + *pNames = (char *)realloc(*pNames, *pBufSize); if (!*pNames) { upsdebugx(1, "%s: buffer overflowed, will not report unused descriptor names", __func__); @@ -1798,7 +1798,7 @@ static int phoenixtec_command(const char *cmd, size_t cmdlen, char *buf, size_t *buf = '\0'; return ret; } - if ((e = memchr(p, '\r', (size_t)ret)) != NULL) break; + if ((e = (char *)memchr(p, '\r', (size_t)ret)) != NULL) break; } if (e != NULL && ++e < buf + buflen) { *e = '\0'; @@ -2252,12 +2252,12 @@ static int armac_command(const char *cmd, size_t cmdlen, char *buf, size_t bufle #if WITH_LIBUSB_1_0 /* Be conservative and do not break old Armac UPSes */ - use_interrupt = armac_endpoint_cache.ok + use_interrupt = (bool_t)(armac_endpoint_cache.ok && armac_endpoint_cache.in_endpoint_address == 0x82 && armac_endpoint_cache.in_bmAttributes & LIBUSB_TRANSFER_TYPE_INTERRUPT && armac_endpoint_cache.out_endpoint_address == 0x02 && armac_endpoint_cache.out_bmAttributes & LIBUSB_TRANSFER_TYPE_INTERRUPT - && armac_endpoint_cache.in_wMaxPacketSize == 64; + && armac_endpoint_cache.in_wMaxPacketSize == 64); #endif /* WITH_LIBUSB_1_0 */ if (use_interrupt && cmddatalen < armac_endpoint_cache.in_wMaxPacketSize) { @@ -4739,8 +4739,11 @@ int qx_process(item_t *item, const char *command) size_t cmdsz = (sizeof(char) * cmdlen); /* in bytes, to be pedantic */ int cmd_len; - if ( !(cmd = xmalloc(cmdsz)) ) { - upslogx(LOG_ERR, "qx_process() failed to allocate buffer"); + /* + * (see comments in `mecer.c` and `blazer.c` / `blazer_ser.c`). + */ + if ( !(cmd = (char *)xmalloc(cmdsz)) ) { + upslogx(LOG_ERR, "blazer_ser_command() failed to allocate buffer"); return -1; } diff --git a/drivers/nutdrv_qx_masterguard.c b/drivers/nutdrv_qx_masterguard.c index ed4811d37d..508e9d5689 100644 --- a/drivers/nutdrv_qx_masterguard.c +++ b/drivers/nutdrv_qx_masterguard.c @@ -355,7 +355,7 @@ static int masterguard_output_voltages(item_t *item, char *value, const size_t v for (w = strtok(item->value, sep); w; w = strtok(NULL, sep)) { n++; upsdebugx(4, "output voltage #%" PRIuSIZE ": %s", n, w); - if ((masterguard_e_outvolts = realloc(masterguard_e_outvolts, n * sizeof(info_rw_t))) == NULL) { + if ((masterguard_e_outvolts = (info_rw_t*)realloc(masterguard_e_outvolts, n * sizeof(info_rw_t))) == NULL) { upsdebugx(1, "output voltages: allocating #%" PRIuSIZE " failed", n); return -1; } @@ -363,7 +363,7 @@ static int masterguard_output_voltages(item_t *item, char *value, const size_t v masterguard_e_outvolts[n - 1].preprocess = NULL; } /* need to do this seperately in case the loop is run zero times */ - if ((masterguard_e_outvolts = realloc(masterguard_e_outvolts, (n + 1) * sizeof(info_rw_t))) == NULL) { + if ((masterguard_e_outvolts = (info_rw_t*)realloc(masterguard_e_outvolts, (n + 1) * sizeof(info_rw_t))) == NULL) { upsdebugx(1, "output voltages: allocating terminator after #%" PRIuSIZE " failed", n); return -1; } diff --git a/drivers/rhino.c b/drivers/rhino.c index 1a8bc55360..10c7165e50 100644 --- a/drivers/rhino.c +++ b/drivers/rhino.c @@ -481,7 +481,7 @@ send_command( unsigned char cmd ) ssize_t ret = -1; unsigned char ch, *psend = NULL; - if ( !(psend = xmalloc(sizeof(char) * sizes)) ) { + if ( !(psend = (unsigned char *)xmalloc(sizeof(char) * sizes)) ) { upslogx(LOG_ERR, "send_command() failed to allocate buffer"); return -1; } diff --git a/drivers/serial.c b/drivers/serial.c index 0317493e7b..926609ec02 100644 --- a/drivers/serial.c +++ b/drivers/serial.c @@ -448,7 +448,7 @@ ssize_t ser_send_buf_pace(TYPE_FD_SER fd, useconds_t d_usec, const void *buf, { ssize_t ret = 0; ssize_t sent; - const char *data = buf; + const char *data = (const char *)buf; assert(buflen < SSIZE_MAX); for (sent = 0; sent < (ssize_t)buflen; sent += ret) { @@ -486,7 +486,7 @@ ssize_t ser_get_buf_len(TYPE_FD_SER fd, void *buf, size_t buflen, time_t d_sec, { ssize_t ret; ssize_t recv; - char *data = buf; + char *data = (char *)buf; assert(buflen < SSIZE_MAX); memset(buf, '\0', buflen); @@ -513,7 +513,7 @@ ssize_t ser_get_line_alert(TYPE_FD_SER fd, void *buf, size_t buflen, char endcha { ssize_t i, ret; char tmp[64]; - char *data = buf; + char *data = (char *)buf; ssize_t count = 0, maxcount; assert(buflen < SSIZE_MAX && buflen > 0); diff --git a/drivers/snmp-ups.c b/drivers/snmp-ups.c index 72c93f04c6..a69239af8d 100644 --- a/drivers/snmp-ups.c +++ b/drivers/snmp-ups.c @@ -259,7 +259,7 @@ static void analyze_mapping_usage(void) { return; } - unused_names = xcalloc(unused_bufsize, sizeof(char)); + unused_names = (char*)xcalloc(unused_bufsize, sizeof(char)); for (su_info_p = &snmp_info[0]; (su_info_p != NULL && su_info_p->info_type != NULL) ; su_info_p++) { @@ -312,7 +312,7 @@ static void analyze_mapping_usage(void) { if (*pBufSize < SIZE_MAX - LARGEBUF) { *pBufSize = *pBufSize + LARGEBUF; upsdebugx(1, "%s: buffer overflowed, trying to re-allocate as %" PRIuSIZE, __func__, *pBufSize); - *pNames = realloc(*pNames, *pBufSize); + *pNames = (char*)realloc(*pNames, *pBufSize); if (!*pNames) { upsdebugx(1, "%s: buffer overflowed, will not report unused descriptor names", __func__); @@ -1397,7 +1397,7 @@ static struct snmp_pdu **nut_snmp_walk(const char *OID, int max_iteration) nb_iteration++; /* +1 is for the terminating NULL */ - new_ret_array = realloc( + new_ret_array = (struct snmp_pdu**)realloc( ret_array, sizeof(struct snmp_pdu*) * ((size_t)nb_iteration+1) ); @@ -1618,7 +1618,7 @@ bool_t nut_snmp_get_int(const char *OID, long *pval) switch (pdu->variables->type) { case ASN_OCTET_STR: case ASN_OPAQUE: - buf = xmalloc(pdu->variables->val_len + 1); + buf = (char*)xmalloc(pdu->variables->val_len + 1); memcpy(buf, pdu->variables->val.string, pdu->variables->val_len); buf[pdu->variables->val_len] = '\0'; value = strtol(buf, NULL, 0); diff --git a/drivers/tripplite_usb.c b/drivers/tripplite_usb.c index e660fd97b5..2735394712 100644 --- a/drivers/tripplite_usb.c +++ b/drivers/tripplite_usb.c @@ -662,7 +662,7 @@ void upsdrv_initinfo(void); */ static void usb_comm_fail(int res, const char *msg) { - static int try = 0; + static int try_num = 0; switch(res) { case LIBUSB_ERROR_BUSY: @@ -679,18 +679,18 @@ static void usb_comm_fail(int res, const char *msg) "%s: Device detached? (error %d: %s)", msg, res, nut_usb_strerror(res)); - upslogx(LOG_NOTICE, "Reconnect attempt #%d", ++try); + upslogx(LOG_NOTICE, "Reconnect attempt #%d", ++try_num); hd = NULL; reconnect_ups(); if(hd) { upslogx(LOG_NOTICE, "Successfully reconnected"); - try = 0; + try_num = 0; dstate_setinfo("driver.state", "reconnect.updateinfo"); upsdrv_initinfo(); dstate_setinfo("driver.state", "quiet"); } else { - if(try > MAX_RECONNECT_TRIES) { + if(try_num > MAX_RECONNECT_TRIES) { fatalx(EXIT_FAILURE, "Too many unsuccessful reconnection attempts"); } } diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index f534051741..0b91bed0f5 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -232,10 +232,10 @@ void do_upsconf_args(char *arg_upsname, char *var, char *val) return; } - tmp = tmp->next; + tmp = (ups_t*)tmp->next; } - tmp = xmalloc(sizeof(ups_t)); + tmp = (ups_t*)xmalloc(sizeof(ups_t)); tmp->upsname = xstrdup(arg_upsname); tmp->driver = NULL; tmp->port = NULL; @@ -1504,7 +1504,7 @@ static void send_one_driver(void (*command_func)(const ups_t *), const char *arg return; } - ups = ups->next; + ups = (ups_t*)ups->next; } fatalx(EXIT_FAILURE, "UPS %s not found in ups.conf", arg_upsname); @@ -1525,7 +1525,7 @@ static void send_all_drivers(void (*command_func)(const ups_t *)) if (command_func == &list_driver || command_func == &status_driver) { while (ups) { command_func(ups); - ups = ups->next; + ups = (ups_t*)ups->next; } fflush(stdout); @@ -1559,7 +1559,7 @@ static void send_all_drivers(void (*command_func)(const ups_t *)) while (ups) { command_func(ups); - ups = ups->next; + ups = (ups_t*)ups->next; } return; @@ -1571,7 +1571,7 @@ static void send_all_drivers(void (*command_func)(const ups_t *)) if (ups->sdorder == i) command_func(ups); - ups = ups->next; + ups = (ups_t*)ups->next; } } } @@ -1590,7 +1590,7 @@ static void exit_cleanup(void) ) { /* First stop the drivers, if any are running */ while (tmp) { - next = tmp->next; + next = (ups_t*)tmp->next; if (tmp->pid != -1) { stop_driver(tmp); } @@ -1600,7 +1600,7 @@ static void exit_cleanup(void) tmp = upstable; while (tmp) { - next = tmp->next; + next = (ups_t*)tmp->next; free(tmp->driver); free(tmp->port); @@ -1837,7 +1837,7 @@ int main(int argc, char **argv) upscount = 0; while (tmp) { - tmp = tmp->next; + tmp = (ups_t*)tmp->next; upscount++; } @@ -1979,7 +1979,7 @@ int main(int argc, char **argv) } } - tmp = tmp->next; + tmp = (ups_t*)tmp->next; } #else /* WIN32 */ /* TOTHINK: Is there something we can do on the platform? */ @@ -2013,7 +2013,7 @@ int main(int argc, char **argv) * and exit the tool - with error if applicable. */ while (tmp) { - next = tmp->next; + next = (ups_t*)tmp->next; if (tmp->pid != -1) { int status; if (waitpid(tmp->pid, &status, WNOHANG) == tmp->pid) { @@ -2075,7 +2075,7 @@ int main(int argc, char **argv) tmp = upstable; while (tmp) { - next = tmp->next; + next = (ups_t*)tmp->next; signal_driver(tmp); tmp = next; } diff --git a/drivers/usb-common.c b/drivers/usb-common.c index 36cb74cbb4..6e50b37cf3 100644 --- a/drivers/usb-common.c +++ b/drivers/usb-common.c @@ -141,12 +141,12 @@ int USBNewExactMatcher(USBDeviceMatcher_t **matcher, USBDevice_t *hd) USBDeviceMatcher_t *m; USBDevice_t *data; - m = malloc(sizeof(*m)); + m = (USBDeviceMatcher_t*)malloc(sizeof(*m)); if (!m) { return -1; } - data = calloc(1, sizeof(*data)); + data = (USBDevice_t*)calloc(1, sizeof(*data)); if (!data) { free(m); return -1; @@ -329,12 +329,12 @@ int USBNewRegexMatcher(USBDeviceMatcher_t **matcher, char **regex, int cflags) USBDeviceMatcher_t *m; regex_matcher_data_t *data; - m = malloc(sizeof(*m)); + m = (USBDeviceMatcher_t*)malloc(sizeof(*m)); if (!m) { return -1; } - data = calloc(1, sizeof(*data)); + data = (regex_matcher_data_t*)calloc(1, sizeof(*data)); if (!data) { free(m); return -1; diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index d469a59a66..d0c443efb9 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -699,8 +699,8 @@ static void analyze_mapping_usage(void) { return; } - unused_names = xcalloc(unused_bufsize, sizeof(char)); - halfused_names = xcalloc(halfused_bufsize, sizeof(char)); + unused_names = (char *)xcalloc(unused_bufsize, sizeof(char)); + halfused_names = (char *)xcalloc(halfused_bufsize, sizeof(char)); for (d = 0; d < pDesc->nitems; d++) { HIDData_t *pData = &pDesc->item[d]; @@ -770,7 +770,7 @@ static void analyze_mapping_usage(void) { if (*pBufSize < SIZE_MAX - LARGEBUF) { *pBufSize = *pBufSize + LARGEBUF; upsdebugx(1, "%s: buffer overflowed, trying to re-allocate as %" PRIuSIZE, __func__, *pBufSize); - *pNames = realloc(*pNames, *pBufSize); + *pNames = (char *)realloc(*pNames, *pBufSize); if (!*pNames) { upsdebugx(1, "%s: buffer overflowed, will not report unused descriptor names", __func__); diff --git a/server/conf.c b/server/conf.c index 18f7bc89f2..edb05bcb26 100644 --- a/server/conf.c +++ b/server/conf.c @@ -54,7 +54,7 @@ static void ups_create(const char *fn, const char *name, const char *desc) } /* grab some memory and add the info */ - temp = xcalloc(1, sizeof(*temp)); + temp = (upstype_t*)xcalloc(1, sizeof(*temp)); temp->fn = xstrdup(fn); temp->name = xstrdup(name); @@ -475,7 +475,7 @@ void do_upsconf_args(char *upsname, char *var, char *val) /* if not listed, create a new entry and prepend it to the list */ if (temp == NULL) { - temp = xcalloc(1, sizeof(*temp)); + temp = (ups_t*)xcalloc(1, sizeof(*temp)); temp->upsname = xstrdup(upsname); temp->next = upstable; upstable = temp; diff --git a/server/desc.c b/server/desc.c index bdc9924e72..edbc01eda3 100644 --- a/server/desc.c +++ b/server/desc.c @@ -76,7 +76,7 @@ static void desc_add(dlist_t **list, const char *name, const char *desc) } if (temp == NULL) { - temp = xcalloc(1, sizeof(*temp)); + temp = (dlist_t*)xcalloc(1, sizeof(*temp)); temp->name = xstrdup(name); temp->next = *list; *list = temp; diff --git a/server/upsd.c b/server/upsd.c index 145979a7a5..5a22ff34f3 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -151,11 +151,12 @@ static tracking_t *tracking_list = NULL; #ifndef WIN32 /* pollfd */ -static struct pollfd *fds = NULL; +#define FTS_T struct pollfd #else /* WIN32 */ -static HANDLE *fds = NULL; +#define FTS_T HANDLE static HANDLE mutex = INVALID_HANDLE_VALUE; #endif /* WIN32 */ +static FTS_T *fds = NULL; static handler_t *handler = NULL; /* pid file */ @@ -230,7 +231,7 @@ void listen_add(const char *addr, const char *port) } /* grab some memory and add the info */ - server = xcalloc(1, sizeof(*server)); + server = (stype_t*)xcalloc(1, sizeof(*server)); server->addr = xstrdup(addr); server->port = xstrdup(port); server->sock_fd = ERROR_FD_SOCK; @@ -326,7 +327,7 @@ static void setuptcp(stype_t *server) /* Not constrained to IPv6 */ upsdebugx(1, "%s: handling 'LISTEN * %s' with IPv4 any-address support", __func__, server->port); - serverAnyV4 = xcalloc(1, sizeof(*serverAnyV4)); + serverAnyV4 = (stype_t*)xcalloc(1, sizeof(*serverAnyV4)); serverAnyV4->addr = xstrdup("0.0.0.0"); serverAnyV4->port = xstrdup(server->port); serverAnyV4->sock_fd = ERROR_FD_SOCK; @@ -337,7 +338,7 @@ static void setuptcp(stype_t *server) /* Not constrained to IPv4 */ upsdebugx(1, "%s: handling 'LISTEN * %s' with IPv6 any-address support", __func__, server->port); - serverAnyV6 = xcalloc(1, sizeof(*serverAnyV6)); + serverAnyV6 = (stype_t*)xcalloc(1, sizeof(*serverAnyV6)); serverAnyV6->addr = xstrdup("::0"); serverAnyV6->port = xstrdup(server->port); serverAnyV6->sock_fd = ERROR_FD_SOCK; @@ -750,7 +751,7 @@ static void check_command(int cmdnum, nut_ctype_t *client, size_t numarg, && (nut_debug_level > 9 || strcmp(arg[0], "PASSWORD")) /* Do not log credentials by default */ ) { /* Not xcalloc() here, not too fatal if we fail */ - char *s = calloc(LARGEBUF, sizeof(char)); + char *s = (char*)calloc(LARGEBUF, sizeof(char)); if (s) { size_t i; @@ -856,7 +857,7 @@ static void client_connect(stype_t *server) return; } - client = xcalloc(1, sizeof(*client)); + client = (nut_ctype_t*)xcalloc(1, sizeof(*client)); client->sock_fd = fd; @@ -1256,8 +1257,8 @@ static void poll_reload(void) upsdebugx(1, "%s: (p)re-allocate %" PRIuMAX " entries for polling FDs and handlers", __func__, (uintmax_t)maxconn); - fds = xrealloc(fds, (size_t)maxconn * sizeof(*fds)); - handler = xrealloc(handler, (size_t)maxconn * sizeof(*handler)); + fds = (FTS_T*)xrealloc(fds, (size_t)maxconn * sizeof(*fds)); + handler = (handler_t*)xrealloc(handler, (size_t)maxconn * sizeof(*handler)); } /* instant command and setvar status tracking */ @@ -1270,7 +1271,7 @@ int tracking_add(const char *id) if ((!tracking_enabled) || (!id)) return 0; - item = xcalloc(1, sizeof(*item)); + item = (tracking_t*)xcalloc(1, sizeof(*item)); item->id = xstrdup(id); item->status = STAT_PENDING; diff --git a/server/user.c b/server/user.c index 7bf29445c9..e8a76f7f97 100644 --- a/server/user.c +++ b/server/user.c @@ -45,7 +45,7 @@ static void user_add(const char *un) return; } - for (tmp = users; tmp != NULL; tmp = tmp->next) { + for (tmp = users; tmp != NULL; tmp = (ulist_t*)tmp->next) { last = tmp; @@ -55,7 +55,7 @@ static void user_add(const char *un) } } - tmp = xcalloc(1, sizeof(*tmp)); + tmp = (ulist_t*)xcalloc(1, sizeof(*tmp)); tmp->username = xstrdup(un); if (last) { @@ -105,7 +105,7 @@ static void user_add_instcmd(const char *cmd) return; } - for (tmp = curr_user->firstcmd; tmp != NULL; tmp = tmp->next) { + for (tmp = curr_user->firstcmd; tmp != NULL; tmp = (instcmdlist_t*)tmp->next) { last = tmp; @@ -118,7 +118,7 @@ static void user_add_instcmd(const char *cmd) upsdebugx(2, "user_add_instcmd: adding '%s' for %s", cmd, curr_user->username); - tmp = xcalloc(1, sizeof(*tmp)); + tmp = (instcmdlist_t*)xcalloc(1, sizeof(*tmp)); tmp->cmd = xstrdup(cmd); @@ -137,12 +137,12 @@ static actionlist_t *addaction(actionlist_t *base, const char *action) return base; } - for (tmp = base; tmp != NULL; tmp = tmp->next) { + for (tmp = base; tmp != NULL; tmp = (actionlist_t*)tmp->next) { last = tmp; } - tmp = xcalloc(1, sizeof(*tmp)); + tmp = (actionlist_t*)xcalloc(1, sizeof(*tmp)); tmp->action = xstrdup(action); if (last) { @@ -174,7 +174,7 @@ static void flushcmd(instcmdlist_t *ptr) return; } - flushcmd(ptr->next); + flushcmd((instcmdlist_t*)ptr->next); free(ptr->cmd); free(ptr); @@ -186,7 +186,7 @@ static void flushaction(actionlist_t *ptr) return; } - flushaction(ptr->next); + flushaction((actionlist_t*)ptr->next); free(ptr->action); free(ptr); @@ -198,7 +198,7 @@ static void flushuser(ulist_t *ptr) return; } - flushuser(ptr->next); + flushuser((ulist_t*)ptr->next); flushcmd(ptr->firstcmd); flushaction(ptr->firstaction); @@ -218,7 +218,7 @@ static int user_matchinstcmd(ulist_t *user, const char * cmd) { instcmdlist_t *tmp; - for (tmp = user->firstcmd; tmp != NULL; tmp = tmp->next) { + for (tmp = user->firstcmd; tmp != NULL; tmp = (instcmdlist_t*)tmp->next) { if (!strcasecmp(tmp->cmd, cmd)) { return 1; /* good */ @@ -240,7 +240,7 @@ int user_checkinstcmd(const char *un, const char *pw, const char *cmd) return 0; /* failed */ } - for (tmp = users; tmp != NULL; tmp = tmp->next) { + for (tmp = users; tmp != NULL; tmp = (ulist_t*)tmp->next) { /* let's be paranoid before we call strcmp */ @@ -274,7 +274,7 @@ static int user_matchaction(ulist_t *user, const char *action) { actionlist_t *tmp; - for (tmp = user->firstaction; tmp != NULL; tmp = tmp->next) { + for (tmp = user->firstaction; tmp != NULL; tmp = (actionlist_t*)tmp->next) { if (!strcasecmp(tmp->action, action)) { return 1; /* good */ @@ -291,7 +291,7 @@ int user_checkaction(const char *un, const char *pw, const char *action) if ((!un) || (!pw) || (!action)) return 0; /* failed */ - for (tmp = users; tmp != NULL; tmp = tmp->next) { + for (tmp = users; tmp != NULL; tmp = (ulist_t*)tmp->next) { /* let's be paranoid before we call strcmp */ diff --git a/tools/nut-scanner/nutscan-device.c b/tools/nut-scanner/nutscan-device.c index 47b1f6a7fa..7f57cf9638 100644 --- a/tools/nut-scanner/nutscan-device.c +++ b/tools/nut-scanner/nutscan-device.c @@ -60,7 +60,7 @@ nutscan_device_t * nutscan_new_device(void) { nutscan_device_t * device; - device = malloc(sizeof(nutscan_device_t)); + device = (nutscan_device_t*)malloc(sizeof(nutscan_device_t)); if (device == NULL) { return NULL; } diff --git a/tools/nut-scanner/nutscan-display.c b/tools/nut-scanner/nutscan-display.c index f486b99198..fdd537859a 100644 --- a/tools/nut-scanner/nutscan-display.c +++ b/tools/nut-scanner/nutscan-display.c @@ -261,7 +261,7 @@ void nutscan_display_sanity_check_serial(nutscan_device_t * device) */ /* Reserve enough slots for all-unique serials */ - map = calloc(listlen, sizeof(keyval_strings_t)); + map = (keyval_strings_t*)calloc(listlen, sizeof(keyval_strings_t)); if (map == NULL) { upsdebugx(0, "%s: Memory allocation error, skipped", __func__); return; diff --git a/tools/nut-scanner/nutscan-ip.c b/tools/nut-scanner/nutscan-ip.c index 6d9eff1e55..629fee13f5 100644 --- a/tools/nut-scanner/nutscan-ip.c +++ b/tools/nut-scanner/nutscan-ip.c @@ -158,7 +158,7 @@ size_t nutscan_add_ip_range(nutscan_ip_range_list_t *irl, char * start_ip, char end_ip = start_ip; } - p = xcalloc(1, sizeof(nutscan_ip_range_t)); + p = (nutscan_ip_range_t*)xcalloc(1, sizeof(nutscan_ip_range_t)); if (start_ip == end_ip || strcmp(start_ip, end_ip) <= 0) { p->start_ip = start_ip; diff --git a/tools/nut-scanner/nutscan-serial.c b/tools/nut-scanner/nutscan-serial.c index 2aa8739a08..aeadc68903 100644 --- a/tools/nut-scanner/nutscan-serial.c +++ b/tools/nut-scanner/nutscan-serial.c @@ -115,7 +115,7 @@ static char ** add_port(char ** list, char * port) /*+1 to get the number of port from the index nb_ports*/ /*+1 for the terminal NULL */ - res = realloc(list, sizeof(char*) * (count + 1 + 1)); + res = (char**)realloc(list, sizeof(char*) * (count + 1 + 1)); if (res == NULL) { upsdebugx(0, "%s: Failed to realloc port list", __func__); return list; diff --git a/tools/nut-scanner/scan_avahi.c b/tools/nut-scanner/scan_avahi.c index 0501e86744..45a060da46 100644 --- a/tools/nut-scanner/scan_avahi.c +++ b/tools/nut-scanner/scan_avahi.c @@ -236,7 +236,7 @@ int nutscan_load_avahi_library(const char *libname_path) upsdebugx(0, "Cannot load AVAHI library (%s) : %s. AVAHI search disabled.", libname_path, dl_error); - dl_handle = (void *)1; + dl_handle = (lt_dlhandle)1; lt_dlexit(); if (dl_saved_libname) { free(dl_saved_libname); @@ -312,7 +312,7 @@ static void update_device(const char * host_name, const char *ip, uint16_t port, buf_size = strlen(device) + strlen(host_name) + 5 + 1 + 1 + 1; - dev->port = malloc(buf_size); + dev->port = (char*)malloc(buf_size); if (dev->port) { snprintf(dev->port, buf_size, "%s@%s:%" PRIu16, device, host_name, port); @@ -321,7 +321,7 @@ static void update_device(const char * host_name, const char *ip, uint16_t port, else { /*+1+1 is for '@' character and terminating 0 */ buf_size = strlen(device) + strlen(host_name) + 1 + 1; - dev->port = malloc(buf_size); + dev->port = (char*)malloc(buf_size); if (dev->port) { snprintf(dev->port, buf_size, "%s@%s", device, host_name); @@ -363,7 +363,7 @@ static void update_device(const char * host_name, const char *ip, uint16_t port, /*+1+1 is for ':' character and terminating 0 */ /*buf is the string containing the port number*/ buf_size = strlen(host_name) + strlen(buf) + 1 + 1; - dev->port = malloc(buf_size); + dev->port = (char*)malloc(buf_size); if (dev->port) { snprintf(dev->port, buf_size, "%s:%s", host_name, buf); @@ -488,7 +488,7 @@ static void browse_callback( void* userdata) { - AvahiClient *c = userdata; + AvahiClient *c = (AvahiClient*)userdata; assert(b); NUT_UNUSED_VARIABLE(flags); @@ -521,7 +521,7 @@ static void browse_callback( * but lacks a value in that enum for lack of flags (unconstrained * lookup). So we have to silence a warning here... */ - if (!((*nut_avahi_service_resolver_new)(c, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, resolve_callback, c))) + if (!((*nut_avahi_service_resolver_new)(c, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, (AvahiLookupFlags)0, resolve_callback, c))) #if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_ASSIGN_ENUM) # pragma GCC diagnostic pop #endif @@ -599,7 +599,7 @@ static AvahiClient* wrap_nut_avahi_client_new(int *error) * but lacks a value in that enum for lack of flags (unconstrained * lookup). So we have to silence a warning here... */ - return (*nut_avahi_client_new)((*nut_avahi_simple_poll_get)(simple_poll), 0, client_callback, NULL, error); + return (*nut_avahi_client_new)((*nut_avahi_simple_poll_get)(simple_poll), (AvahiLookupFlags)0, client_callback, NULL, error); #if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_ASSIGN_ENUM) # pragma GCC diagnostic pop #endif @@ -646,7 +646,7 @@ nutscan_device_t * nutscan_scan_avahi(useconds_t usec_timeout) /* See comments about flags just a bit above */ if (!(sb = (*nut_avahi_service_browser_new)( client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, - "_upsd._tcp", NULL, 0, browse_callback, client)) + "_upsd._tcp", NULL, (AvahiLookupFlags)0, browse_callback, client)) ) { #if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_ASSIGN_ENUM) # pragma GCC diagnostic pop diff --git a/tools/nut-scanner/scan_eaton_serial.c b/tools/nut-scanner/scan_eaton_serial.c index 1401dd42ac..2b1db5d27c 100644 --- a/tools/nut-scanner/scan_eaton_serial.c +++ b/tools/nut-scanner/scan_eaton_serial.c @@ -135,7 +135,7 @@ unsigned char calc_checksum(const unsigned char *buf) * return 1 if OK, 0 otherwise */ static int shut_synchronise(TYPE_FD_SER arg_upsfd) { - int try; + int try_num; unsigned char reply = '\0'; /* FIXME? Should we save "arg_upsfd" into global "upsfd" variable? * This was previously shadowed by function argument named "upsfd"... @@ -143,7 +143,7 @@ static int shut_synchronise(TYPE_FD_SER arg_upsfd) /* upsfd = arg_upsfd; */ /* Sync with the UPS according to notification */ - for (try = 0; try < MAX_TRY; try++) { + for (try_num = 0; try_num < MAX_TRY; try_num++) { if ((ser_send_char(arg_upsfd, SHUT_SYNC)) == -1) { continue; } @@ -477,7 +477,7 @@ nutscan_device_t * nutscan_scan_eaton_serial(const char* ports_range) sem_wait(semaphore); pass = TRUE; } else { - pass = (sem_trywait(semaphore) == 0); + pass = (sem_trywait(semaphore) == 0) ? TRUE : FALSE; } # else # ifdef HAVE_PTHREAD_TRYJOIN @@ -562,7 +562,7 @@ nutscan_device_t * nutscan_scan_eaton_serial(const char* ports_range) # endif /* HAVE_PTHREAD_TRYJOIN */ thread_count++; - new_thread_array = realloc(thread_array, + new_thread_array = (nutscan_thread_t*)realloc(thread_array, thread_count * sizeof(nutscan_thread_t)); if (new_thread_array == NULL) { upsdebugx(1, "%s: Failed to realloc thread array", __func__); diff --git a/tools/nut-scanner/scan_ipmi.c b/tools/nut-scanner/scan_ipmi.c index 9aa1e12e54..e3b7403074 100644 --- a/tools/nut-scanner/scan_ipmi.c +++ b/tools/nut-scanner/scan_ipmi.c @@ -283,7 +283,7 @@ int nutscan_load_ipmi_library(const char *libname_path) upsdebugx(0, "Cannot load IPMI library (%s) : %s. IPMI search disabled.", libname_path, dl_error); - dl_handle = (void *)1; + dl_handle = (lt_dlhandle)1; lt_dlexit(); if (dl_saved_libname) { free(dl_saved_libname); @@ -846,7 +846,7 @@ nutscan_device_t * nutscan_scan_ip_range_ipmi(nutscan_ip_range_list_t * irl, nut */ int stwST = sem_trywait(semaphore_scantype); int stwS = sem_trywait(semaphore); - pass = ((max_threads_scantype == 0 || stwST == 0) && stwS == 0); + pass = ((max_threads_scantype == 0 || stwST == 0) && stwS == 0) ? TRUE : FALSE; upsdebugx(4, "%s: max_threads_scantype=%" PRIuSIZE " curr_threads=%" PRIuSIZE " thread_count=%" PRIuSIZE @@ -934,7 +934,7 @@ nutscan_device_t * nutscan_scan_ip_range_ipmi(nutscan_ip_range_list_t * irl, nut #endif /* HAVE_PTHREAD */ if (pass) { - tmp_sec = malloc(sizeof(nutscan_ipmi_t)); + tmp_sec = (nutscan_ipmi_t*)malloc(sizeof(nutscan_ipmi_t)); if (tmp_sec == NULL) { upsdebugx(0, "%s: Memory allocation error", __func__); break; @@ -952,7 +952,7 @@ nutscan_device_t * nutscan_scan_ip_range_ipmi(nutscan_ip_range_list_t * irl, nut # endif /* HAVE_PTHREAD_TRYJOIN */ thread_count++; - new_thread_array = realloc(thread_array, + new_thread_array = (nutscan_thread_t*)realloc(thread_array, thread_count * sizeof(nutscan_thread_t)); if (new_thread_array == NULL) { upsdebugx(1, "%s: Failed to realloc thread array", __func__); diff --git a/tools/nut-scanner/scan_nut.c b/tools/nut-scanner/scan_nut.c index 9321d96a62..bad82d6ba5 100644 --- a/tools/nut-scanner/scan_nut.c +++ b/tools/nut-scanner/scan_nut.c @@ -154,7 +154,7 @@ int nutscan_load_upsclient_library(const char *libname_path) upsdebugx(0, "Cannot load NUT library (%s) : %s. NUT search disabled.", libname_path, dl_error); - dl_handle = (void *)1; + dl_handle = (lt_dlhandle)1; lt_dlexit(); if (dl_saved_libname) { free(dl_saved_libname); @@ -179,7 +179,7 @@ static void * list_nut_devices_thready(void * arg) const char *query[4]; char **answer = NULL; char *hostname = NULL; - UPSCONN_t *ups = xcalloc(1, sizeof(*ups)); + UPSCONN_t *ups = (UPSCONN_t*)xcalloc(1, sizeof(*ups)); nutscan_device_t * dev = NULL; size_t buf_size; @@ -243,7 +243,7 @@ static void * list_nut_devices_thready(void * arg) buf_size += 6; } - dev->port = malloc(buf_size); + dev->port = (char*)malloc(buf_size); if (dev->port) { /* Check if IPv6 and needs brackets */ @@ -463,7 +463,7 @@ nutscan_device_t * nutscan_scan_ip_range_nut(nutscan_ip_range_list_t * irl, cons */ int stwST = sem_trywait(semaphore_scantype); int stwS = sem_trywait(semaphore); - pass = ((max_threads_scantype == 0 || stwST == 0) && stwS == 0); + pass = (((max_threads_scantype == 0) || (stwST == 0)) && (stwS == 0)) ? TRUE : FALSE; upsdebugx(4, "%s: max_threads_scantype=%" PRIuSIZE " curr_threads=%" PRIuSIZE " thread_count=%" PRIuSIZE @@ -565,7 +565,7 @@ nutscan_device_t * nutscan_scan_ip_range_nut(nutscan_ip_range_list_t * irl, cons ip_dest = strdup(ip_str); } - if ((nut_arg = malloc(sizeof(struct scan_nut_arg))) == NULL) { + if ((nut_arg = (struct scan_nut_arg*)malloc(sizeof(struct scan_nut_arg))) == NULL) { upsdebugx(0, "%s: Memory allocation error", __func__); free(ip_dest); break; @@ -583,7 +583,7 @@ nutscan_device_t * nutscan_scan_ip_range_nut(nutscan_ip_range_list_t * irl, cons # endif /* HAVE_PTHREAD_TRYJOIN */ thread_count++; - new_thread_array = realloc(thread_array, + new_thread_array = (nutscan_thread_t*)realloc(thread_array, thread_count * sizeof(nutscan_thread_t)); if (new_thread_array == NULL) { upsdebugx(1, "%s: Failed to realloc thread array", __func__); diff --git a/tools/nut-scanner/scan_snmp.c b/tools/nut-scanner/scan_snmp.c index a5ad7158c4..bad7233596 100644 --- a/tools/nut-scanner/scan_snmp.c +++ b/tools/nut-scanner/scan_snmp.c @@ -493,7 +493,7 @@ int nutscan_load_snmp_library(const char *libname_path) upsdebugx(0, "Cannot load SNMP library (%s) : %s. SNMP search disabled.", libname_path, dl_error); - dl_handle = (void *)1; + dl_handle = (lt_dlhandle)1; lt_dlexit(); if (dl_saved_libname) { free(dl_saved_libname); @@ -522,7 +522,7 @@ static void scan_snmp_add_device(nutscan_snmp_t * sec, struct snmp_pdu *response * Does our driver support the notation? */ dev->port = strdup(session->peername); if (response != NULL) { - buf = malloc (response->variables->val_len + 1); + buf = (char*)malloc (response->variables->val_len + 1); if (buf) { memcpy(buf, response->variables->val.string, response->variables->val_len); @@ -562,7 +562,7 @@ static void scan_snmp_add_device(nutscan_snmp_t * sec, struct snmp_pdu *response } } else { - buf = malloc (session->community_len + 1); + buf = (char*)malloc(session->community_len + 1); if (buf) { memcpy(buf, session->community, session->community_len); @@ -1323,7 +1323,7 @@ nutscan_device_t * nutscan_scan_ip_range_snmp(nutscan_ip_range_list_t * irl, #endif /* HAVE_PTHREAD */ if (pass) { - tmp_sec = malloc(sizeof(nutscan_snmp_t)); + tmp_sec = (nutscan_snmp_t*)malloc(sizeof(nutscan_snmp_t)); if (tmp_sec == NULL) { upsdebugx(0, "%s: Memory allocation error", __func__); break; @@ -1341,7 +1341,7 @@ nutscan_device_t * nutscan_scan_ip_range_snmp(nutscan_ip_range_list_t * irl, # endif /* HAVE_PTHREAD_TRYJOIN */ thread_count++; - new_thread_array = realloc(thread_array, + new_thread_array = (nutscan_thread_t*)realloc(thread_array, thread_count * sizeof(nutscan_thread_t)); if (new_thread_array == NULL) { upsdebugx(1, "%s: Failed to realloc thread array", __func__); diff --git a/tools/nut-scanner/scan_usb.c b/tools/nut-scanner/scan_usb.c index 0f5ae6d43c..77050c8267 100644 --- a/tools/nut-scanner/scan_usb.c +++ b/tools/nut-scanner/scan_usb.c @@ -274,7 +274,7 @@ int nutscan_load_usb_library(const char *libname_path) upsdebugx(0, "Cannot load USB library (%s) : %s. USB search disabled.", libname_path, dl_error); - dl_handle = (void *)1; + dl_handle = (lt_dlhandle)1; lt_dlexit(); if (dl_saved_libname) { free(dl_saved_libname); @@ -594,7 +594,7 @@ nutscan_device_t * nutscan_scan_usb(nutscan_usb_t * scanopts) "bus/port '%s', skipping: %s", __func__, busname, device_port, bus_port, - (*nut_usb_strerror)(ret)); + (*nut_usb_strerror)((enum libusb_error)ret)); /* Note: closing is not applicable * it seems, and can even segfault diff --git a/tools/nut-scanner/scan_xml_http.c b/tools/nut-scanner/scan_xml_http.c index 699a8cab16..c4cc8f2326 100644 --- a/tools/nut-scanner/scan_xml_http.c +++ b/tools/nut-scanner/scan_xml_http.c @@ -165,7 +165,7 @@ int nutscan_load_neon_library(const char *libname_path) upsdebugx(0, "Cannot load XML library (%s) : %s. XML search disabled.", libname_path, dl_error); - dl_handle = (void *)1; + dl_handle = (lt_dlhandle)1; lt_dlexit(); if (dl_saved_libname) { free(dl_saved_libname); @@ -610,7 +610,7 @@ nutscan_device_t * nutscan_scan_ip_range_xml_http(nutscan_ip_range_list_t * irl, */ int stwST = sem_trywait(semaphore_scantype); int stwS = sem_trywait(semaphore); - pass = ((max_threads_scantype == 0 || stwST == 0) && stwS == 0); + pass = ((max_threads_scantype == 0 || stwST == 0) && stwS == 0) ? TRUE : FALSE; upsdebugx(4, "%s: max_threads_scantype=%" PRIuSIZE " curr_threads=%" PRIuSIZE " thread_count=%" PRIuSIZE @@ -698,7 +698,7 @@ nutscan_device_t * nutscan_scan_ip_range_xml_http(nutscan_ip_range_list_t * irl, #endif /* HAVE_PTHREAD */ if (pass) { - tmp_sec = malloc(sizeof(nutscan_xml_t)); + tmp_sec = (nutscan_xml_t*)malloc(sizeof(nutscan_xml_t)); if (tmp_sec == NULL) { upsdebugx(0, "%s: Memory allocation error", __func__); break; @@ -719,7 +719,7 @@ nutscan_device_t * nutscan_scan_ip_range_xml_http(nutscan_ip_range_list_t * irl, # endif /* HAVE_PTHREAD_TRYJOIN */ thread_count++; - new_thread_array = realloc(thread_array, + new_thread_array = (nutscan_thread_t*)realloc(thread_array, thread_count * sizeof(nutscan_thread_t)); if (new_thread_array == NULL) { upsdebugx(1, "%s: Failed to realloc thread array", __func__); @@ -849,7 +849,7 @@ nutscan_device_t * nutscan_scan_ip_range_xml_http(nutscan_ip_range_list_t * irl, } /* end of: scan range of 1+ IP address(es), maybe in parallel */ /* both start_ip == end_ip == NULL, scan broadcast */ - tmp_sec = malloc(sizeof(nutscan_xml_t)); + tmp_sec = (nutscan_xml_t*)malloc(sizeof(nutscan_xml_t)); if (tmp_sec == NULL) { upsdebugx(0, "%s: Memory allocation error", __func__); return NULL; From f95f3dd96b72aca6b5608a24e3620c5b01303328 Mon Sep 17 00:00:00 2001 From: Tim Niemueller Date: Sun, 1 Feb 2026 14:31:02 +0100 Subject: [PATCH 070/198] Add nullptr checks and wrong enum cast Signed-off-by: Jim Klimov --- clients/cgilib.c | 3 +++ clients/upslog.c | 6 ++++++ clients/upsset.c | 5 +++++ tools/nut-scanner/scan_avahi.c | 2 +- 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/clients/cgilib.c b/clients/cgilib.c index 1817d582f6..b196271a43 100644 --- a/clients/cgilib.c +++ b/clients/cgilib.c @@ -32,6 +32,9 @@ static char *unescape(char *buf) buflen = strlen(buf) + 2; newbuf = (char *)xmalloc(buflen); + if (newbuf == NULL) { + return NULL; + } *newbuf = '\0'; fflush(stdout); diff --git a/clients/upslog.c b/clients/upslog.c index 52820c126b..87c37e1a6b 100644 --- a/clients/upslog.c +++ b/clients/upslog.c @@ -812,6 +812,12 @@ int main(int argc, char **argv) upsdebugx(1, "FOUND: %s: %s", answer[1], answer[2]); mu = (struct monhost_ups_t *)xmalloc(sizeof(struct monhost_ups_t)); + if (mu == NULL) { + upslogx(LOG_ERR, "Failed to get memory for monitoring host structure. Not adding %s@%s:%" PRIu16, + answer[1], monhost_ups_current->hostname, monhost_ups_current->port); + continue; + } + snprintf(buf, sizeof(buf), "%s@%s:%" PRIu16, answer[1], monhost_ups_current->hostname, diff --git a/clients/upsset.c b/clients/upsset.c index f952846973..969f091395 100644 --- a/clients/upsset.c +++ b/clients/upsset.c @@ -70,6 +70,11 @@ void parsearg(char *var, char *value) uvtype_t *last, *tmp = NULL; static int upsvc = 0; + if (var == NULL || value == NULL) { + upslogx(LOG_ERR, "parsearg() called with var null or value null"); + return; + } + /* store variables from a SET command for the later commit */ if (!strncmp(var, "UPSVAR_", 7)) { diff --git a/tools/nut-scanner/scan_avahi.c b/tools/nut-scanner/scan_avahi.c index 45a060da46..9f3469f82c 100644 --- a/tools/nut-scanner/scan_avahi.c +++ b/tools/nut-scanner/scan_avahi.c @@ -599,7 +599,7 @@ static AvahiClient* wrap_nut_avahi_client_new(int *error) * but lacks a value in that enum for lack of flags (unconstrained * lookup). So we have to silence a warning here... */ - return (*nut_avahi_client_new)((*nut_avahi_simple_poll_get)(simple_poll), (AvahiLookupFlags)0, client_callback, NULL, error); + return (*nut_avahi_client_new)((*nut_avahi_simple_poll_get)(simple_poll), (AvahiClientFlags)0, client_callback, NULL, error); #if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_ASSIGN_ENUM) # pragma GCC diagnostic pop #endif From d03b3007d86466042cf2ff172f078863c706d6ab Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 09:58:22 +0100 Subject: [PATCH 071/198] NEWS.adoc: note the pointer-casting refinement [#3293] Kudos to Tim Niemueller, Gemini, and clang-21 extended warnings. Signed-off-by: Jim Klimov --- NEWS.adoc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/NEWS.adoc b/NEWS.adoc index 5d08172d8e..2fb1339723 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -89,6 +89,14 @@ https://github.com/networkupstools/nut/milestone/12 Separated an `upsdrvquery_ping()` operation from earlier code, so it can be directly used by consumers (in-tree this is drivers and `upsdrvctl`). [issue #3276, PR #3277] + * Revised `void*` pointer casting into specific types for values returned + by `xmalloc()` and friends, or iterated in loops via `something->next`, + as `clang-21` now warns about not-casting void pointers (formally valid, + practically uncertain if that code matches the developer's intention), + and (better safe than sorry) added `NULL`-return checks although we should + not normally get into those code paths with the `x*()` methods which + should bail out and abort the program with a common error message when + an allocation fails. [#3293] - NUT for Windows specific updates: * Revised detection of (relative) paths to program and configuration files From 3d3522e5c78b468e79610f5ff5e54e3fa94b231b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 10:44:14 +0100 Subject: [PATCH 072/198] drivers/apc_modbus.c: bump DRIVER_VERSION due to refined setting of mapping table entry types etc. via enum values [#3293] Signed-off-by: Jim Klimov --- drivers/apc_modbus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/apc_modbus.c b/drivers/apc_modbus.c index d5198426b7..178aa65e7a 100644 --- a/drivers/apc_modbus.c +++ b/drivers/apc_modbus.c @@ -44,7 +44,7 @@ #endif #define DRIVER_NAME "NUT APC Modbus driver " DRIVER_NAME_NUT_MODBUS_HAS_USB_WITH_STR " USB support (libmodbus link type: " NUT_MODBUS_LINKTYPE_STR ")" -#define DRIVER_VERSION "0.17" +#define DRIVER_VERSION "0.18" #if defined NUT_MODBUS_HAS_USB From e6b85694f749859068b5489fc63276694bb23825 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 13:29:39 +0100 Subject: [PATCH 073/198] *.{c,h}: rectify indentations and line-wrapping in general code structure and method arguments Signed-off-by: Jim Klimov --- clients/cgilib.c | 2 +- clients/upsc.c | 2 +- clients/upsclient.c | 2 +- clients/upscmd.c | 2 +- clients/upslog.c | 8 +- clients/upsmon.c | 4 +- clients/upsrw.c | 2 +- clients/upsset.c | 4 +- common/common.c | 9 +- common/strptime.c | 6 +- common/wincompat.c | 12 +- drivers/adelsystem_cbi.c | 2 +- drivers/adelsystem_cbi.h | 14 +- drivers/al175.c | 16 +- drivers/apc-hid.c | 296 +++++++++++++++--------------- drivers/apcsmart-old.c | 11 +- drivers/apcsmart.c | 8 +- drivers/bcmxcp.c | 147 ++++++++------- drivers/bcmxcp_usb.c | 2 +- drivers/belkinunv.c | 2 +- drivers/bestfortress.c | 21 ++- drivers/bicker_ser.c | 16 +- drivers/clone-outlet.c | 2 +- drivers/dstate.c | 18 +- drivers/eaton-pdu-marlin-mib.c | 2 +- drivers/everups.c | 4 +- drivers/generic_gpio_libgpiod.c | 5 +- drivers/generic_modbus.c | 4 +- drivers/genericups.c | 8 +- drivers/hpe-pdu-mib.c | 2 +- drivers/huawei-ups2000.c | 31 ++-- drivers/libshut.c | 21 ++- drivers/macosx-ups.c | 2 +- drivers/mge-utalk.c | 61 +++--- drivers/microdowell.c | 2 +- drivers/microsol-apc.h | 160 ++++++++-------- drivers/nut-ipmipsu.c | 2 +- drivers/nut-libfreeipmi.c | 9 +- drivers/nut-upower.c | 12 +- drivers/nutdrv_hashx.c | 79 ++++---- drivers/nutdrv_qx.c | 4 +- drivers/optiups.c | 4 +- drivers/pijuice.c | 45 +++-- drivers/powercom.c | 179 +++++++++--------- drivers/richcomm_usb.c | 6 +- drivers/riello_ser.c | 2 +- drivers/skel.c | 2 +- drivers/snmp-ups.c | 20 +- drivers/snmp-ups.h | 7 +- drivers/socomec_jbus.c | 14 +- drivers/solis.c | 8 +- drivers/tripplite-hid.c | 4 +- drivers/tripplite_usb.c | 114 +++++++----- drivers/tripplitesu.c | 32 ++-- drivers/upsdrvctl.c | 2 +- drivers/upshandler.h | 6 +- drivers/usb-common.c | 48 ++--- drivers/usb-common.h | 20 +- drivers/ydn23.h | 5 +- include/common.h | 9 +- server/conf.c | 2 +- server/netlist.c | 2 +- server/upsd.c | 2 +- tests/generic_gpio_liblocal.c | 131 ++++++++----- tools/nut-scanner/nut-scanner.c | 8 +- tools/nut-scanner/nutscan-ip.c | 4 +- tools/nut-scanner/scan_avahi.c | 7 +- tools/nut-scanner/scan_ipmi.c | 14 +- tools/nut-scanner/scan_snmp.c | 10 +- tools/nut-scanner/scan_usb.c | 2 +- tools/nut-scanner/scan_xml_http.c | 2 +- 71 files changed, 937 insertions(+), 790 deletions(-) diff --git a/clients/cgilib.c b/clients/cgilib.c index b196271a43..36bc0395b8 100644 --- a/clients/cgilib.c +++ b/clients/cgilib.c @@ -33,7 +33,7 @@ static char *unescape(char *buf) buflen = strlen(buf) + 2; newbuf = (char *)xmalloc(buflen); if (newbuf == NULL) { - return NULL; + return NULL; } *newbuf = '\0'; diff --git a/clients/upsc.c b/clients/upsc.c index 6912e70f01..f3736b8a4f 100644 --- a/clients/upsc.c +++ b/clients/upsc.c @@ -87,7 +87,7 @@ static void usage(const char *prog) printf("\nCommon arguments:\n"); printf(" -V - display the version of this software\n"); printf(" -W - network timeout for initial connections (default: %s)\n", - UPSCLI_DEFAULT_CONNECT_TIMEOUT); + UPSCLI_DEFAULT_CONNECT_TIMEOUT); printf(" -h - display this help text\n"); nut_report_config_flags(); diff --git a/clients/upsclient.c b/clients/upsclient.c index baaeae6fdf..1d4851f18e 100644 --- a/clients/upsclient.c +++ b/clients/upsclient.c @@ -1972,7 +1972,7 @@ int upscli_init_default_connect_timeout(const char *cli_secs, const char *config } upsdebugx(1, "%s: upscli_default_connect_timeout=%" PRIiMAX - ".%06" PRIiMAX " sec assigned from: %s", + ".%06" PRIiMAX " sec assigned from: %s", __func__, (intmax_t)upscli_default_connect_timeout.tv_sec, (intmax_t)upscli_default_connect_timeout.tv_usec, cause); diff --git a/clients/upscmd.c b/clients/upscmd.c index 963153cdc8..561d7d5bb6 100644 --- a/clients/upscmd.c +++ b/clients/upscmd.c @@ -70,7 +70,7 @@ static void usage(const char *prog) printf("\nCommon arguments:\n"); printf(" -V - display the version of this software\n"); printf(" -W - network timeout for initial connections (default: %s)\n", - UPSCLI_DEFAULT_CONNECT_TIMEOUT); + UPSCLI_DEFAULT_CONNECT_TIMEOUT); printf(" -h - display this help text\n"); nut_report_config_flags(); diff --git a/clients/upslog.c b/clients/upslog.c index 87c37e1a6b..c5c6a9a038 100644 --- a/clients/upslog.c +++ b/clients/upslog.c @@ -129,8 +129,8 @@ static void reopen_log(void) } if ((p->logfile = freopen( - p->logfn, "a", - p->logfile)) == NULL + p->logfn, "a", + p->logfile)) == NULL ) { fatal_with_errno(EXIT_FAILURE, "could not reopen logfile %s", p->logfn); @@ -225,7 +225,7 @@ static void help(const char *prog) printf("\nCommon arguments:\n"); printf(" -V - display the version of this software\n"); printf(" -W - network timeout for initial connections (default: %s)\n", - UPSCLI_DEFAULT_CONNECT_TIMEOUT); + UPSCLI_DEFAULT_CONNECT_TIMEOUT); printf(" -h - display this help text\n"); printf("\n"); printf("Some valid format string escapes:\n"); @@ -814,7 +814,7 @@ int main(int argc, char **argv) mu = (struct monhost_ups_t *)xmalloc(sizeof(struct monhost_ups_t)); if (mu == NULL) { upslogx(LOG_ERR, "Failed to get memory for monitoring host structure. Not adding %s@%s:%" PRIu16, - answer[1], monhost_ups_current->hostname, monhost_ups_current->port); + answer[1], monhost_ups_current->hostname, monhost_ups_current->port); continue; } diff --git a/clients/upsmon.c b/clients/upsmon.c index 70f7a2c030..dc1a41ce38 100644 --- a/clients/upsmon.c +++ b/clients/upsmon.c @@ -1594,7 +1594,7 @@ static int is_ups_critical(utype_t *ups) if (flag_isset(ups->status, ST_CAL)) { upslogx(LOG_WARNING, "%s: seems that UPS [%s] is OB+LB now, but " "it is also calibrating - not declaring a critical state", - __func__, ups->upsname); + __func__, ups->upsname); return 0; } @@ -3442,7 +3442,7 @@ static void help(const char *arg_progname) printf("\nCommon arguments:\n"); printf(" -V - display the version of this software\n"); printf(" -W - network timeout for initial connections (default: %s)\n", - UPSCLI_DEFAULT_CONNECT_TIMEOUT); + UPSCLI_DEFAULT_CONNECT_TIMEOUT); printf(" -h - display this help text\n"); nut_report_config_flags(); diff --git a/clients/upsrw.c b/clients/upsrw.c index 97ca368b57..797445eeee 100644 --- a/clients/upsrw.c +++ b/clients/upsrw.c @@ -69,7 +69,7 @@ static void usage(const char *prog) printf("\nCommon arguments:\n"); printf(" -V - display the version of this software\n"); printf(" -W - network timeout for initial connections (default: %s)\n", - UPSCLI_DEFAULT_CONNECT_TIMEOUT); + UPSCLI_DEFAULT_CONNECT_TIMEOUT); printf(" -h - display this help text\n"); printf("\n"); printf("Call without -s to show all possible read/write variables (same as -l).\n"); diff --git a/clients/upsset.c b/clients/upsset.c index 969f091395..898acd4dba 100644 --- a/clients/upsset.c +++ b/clients/upsset.c @@ -71,8 +71,8 @@ void parsearg(char *var, char *value) static int upsvc = 0; if (var == NULL || value == NULL) { - upslogx(LOG_ERR, "parsearg() called with var null or value null"); - return; + upslogx(LOG_ERR, "parsearg() called with var null or value null"); + return; } /* store variables from a SET command for the later commit */ diff --git a/common/common.c b/common/common.c index 903b77880a..8d230a790a 100644 --- a/common/common.c +++ b/common/common.c @@ -2465,9 +2465,12 @@ int str_contains_token(const char *string, const char *token) * checking for uniqueness and going to add a newly seen token. * If such callback returns 0, abort the addition of token. */ -int str_add_unique_token(char *tgt, size_t tgtsize, const char *token, - int (*callback_always)(char *, size_t, const char *), - int (*callback_unique)(char *, size_t, const char *) +int str_add_unique_token( + char *tgt, + size_t tgtsize, + const char *token, + int (*callback_always)(char *, size_t, const char *), + int (*callback_unique)(char *, size_t, const char *) ) { size_t toklen = 0, tgtlen = 0; diff --git a/common/strptime.c b/common/strptime.c index 3480aa42b3..90b6627019 100644 --- a/common/strptime.c +++ b/common/strptime.c @@ -338,9 +338,9 @@ again: switch (c = *fmt++) { * point to calculate a real value, so just check the * range for now. */ - bp = conv_num(bp, &i, 0, 53); - LEGAL_ALT(ALT_O); - continue; + bp = conv_num(bp, &i, 0, 53); + LEGAL_ALT(ALT_O); + continue; case 'w': /* The day of week, beginning on sunday. */ bp = conv_num(bp, &tm->tm_wday, 0, 6); diff --git a/common/wincompat.c b/common/wincompat.c index 59a5a5aa2a..9045ba4624 100644 --- a/common/wincompat.c +++ b/common/wincompat.c @@ -1301,9 +1301,9 @@ TCSAFLUSH: flush output and discard input, then change attributes. } /* - if (t->c_cflag & CRTSXOFF) - state.fRtsControl = RTS_CONTROL_HANDSHAKE; - */ + if (t->c_cflag & CRTSXOFF) + state.fRtsControl = RTS_CONTROL_HANDSHAKE; + */ /* -------------- DTR ------------------ */ /* Assert DTR on device open */ @@ -1578,9 +1578,9 @@ int tcgetattr (serial_handler_t * sh, struct termios *t) (state.fOutxCtsFlow == TRUE)) t->c_cflag |= CRTSCTS; /* - if (state.fRtsControl == RTS_CONTROL_HANDSHAKE) - t->c_cflag |= CRTSXOFF; - */ + if (state.fRtsControl == RTS_CONTROL_HANDSHAKE) + t->c_cflag |= CRTSXOFF; + */ /* -------------- CLOCAL --------------- */ /* DSR is only lead toggled only by CLOCAL. Check it to see if diff --git a/drivers/adelsystem_cbi.c b/drivers/adelsystem_cbi.c index 48e7d0f355..3df478a90a 100644 --- a/drivers/adelsystem_cbi.c +++ b/drivers/adelsystem_cbi.c @@ -1336,7 +1336,7 @@ modbus_t *modbus_new(const char *port) upslogx(LOG_ERR, "modbus_new_rtu: Unable to open serial port context"); } } else if ((sp = strchr(port, ':')) != NULL) { - char *tcp_port = (char*)xmalloc(sizeof(sp)); + char *tcp_port = (char*)xmalloc(sizeof(sp)); strncpy(tcp_port, sp + 1, sizeof(sp)); *sp = '\0'; mb = modbus_new_tcp(port, (int)strtoul(tcp_port, NULL, 10)); diff --git a/drivers/adelsystem_cbi.h b/drivers/adelsystem_cbi.h index 1fd2139494..275c44b3b0 100644 --- a/drivers/adelsystem_cbi.h +++ b/drivers/adelsystem_cbi.h @@ -257,14 +257,14 @@ typedef struct alrm_ar alrm_ar_t; static inline alrm_ar_t *alloc_alrm_ar(int as, size_t extra) { - alrm_ar_t *ret = (alrm_ar_t*)xcalloc(1, sizeof(alrm_t) + extra); + alrm_ar_t *ret = (alrm_ar_t*)xcalloc(1, sizeof(alrm_t) + extra); if (ret) { - memcpy(ret, - &(alrm_ar_t const) { - .alrm_c = as - }, - sizeof(alrm_ar_t) - ); + memcpy(ret, + &(alrm_ar_t const) { + .alrm_c = as + }, + sizeof(alrm_ar_t) + ); } return ret; } diff --git a/drivers/al175.c b/drivers/al175.c index 66c2cb9a92..77f8e8e2ea 100644 --- a/drivers/al175.c +++ b/drivers/al175.c @@ -253,14 +253,14 @@ static void reverse_bits(byte_t *buf, size_t count) while (count!=0) { x = *buf; - x = (byte_t)( (x & 0x80) >> 7 ) | - (byte_t)( (x & 0x40) >> 5 ) | - (byte_t)( (x & 0x20) >> 3 ) | - (byte_t)( (x & 0x10) >> 1 ) | - (byte_t)( (x & 0x08) << 1 ) | - (byte_t)( (x & 0x04) << 3 ) | - (byte_t)( (x & 0x02) << 5 ) | - (byte_t)( (x & 0x01) << 7 ); + x = (byte_t)( (x & 0x80) >> 7 ) + | (byte_t)( (x & 0x40) >> 5 ) + | (byte_t)( (x & 0x20) >> 3 ) + | (byte_t)( (x & 0x10) >> 1 ) + | (byte_t)( (x & 0x08) << 1 ) + | (byte_t)( (x & 0x04) << 3 ) + | (byte_t)( (x & 0x02) << 5 ) + | (byte_t)( (x & 0x01) << 7 ); *buf = x; ++buf; diff --git a/drivers/apc-hid.c b/drivers/apc-hid.c index de0ae5a924..da34dba7eb 100644 --- a/drivers/apc-hid.c +++ b/drivers/apc-hid.c @@ -330,144 +330,144 @@ static usage_tables_t apc_utab[] = { /* HID2NUT lookup table */ static hid_info_t apc_hid2nut[] = { - /* Battery page */ - { "battery.charge", 0, 0, "UPS.PowerSummary.RemainingCapacity", NULL, "%.0f", 0, NULL }, - { "battery.charge.low", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.PowerSummary.RemainingCapacityLimit", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL }, - { "battery.charge.warning", 0, 0, "UPS.PowerSummary.WarningCapacityLimit", NULL, "%.0f", 0, NULL }, - { "battery.runtime", 0, 0, "UPS.Battery.RunTimeToEmpty", NULL, "%.0f", 0, NULL }, - { "battery.runtime", 0, 0, "UPS.PowerSummary.RunTimeToEmpty", NULL, "%.0f", 0, NULL }, - { "battery.runtime.low", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.Battery.RemainingTimeLimit", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL }, - { "battery.runtime.low", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.PowerSummary.RemainingTimeLimit", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL }, - { "battery.voltage", 0, 0, "UPS.Battery.Voltage", NULL, "%.1f", 0, NULL }, - { "battery.voltage", 0, 0, "UPS.PowerSummary.Voltage", NULL, "%.1f", 0, NULL }, - { "battery.voltage.nominal", 0, 0, "UPS.Battery.ConfigVoltage", NULL, "%.1f", 0, NULL }, - { "battery.voltage.nominal", 0, 0, "UPS.PowerSummary.ConfigVoltage", NULL, "%.1f", 0, NULL }, /* Back-UPS 500 */ - { "battery.temperature", 0, 0, "UPS.Battery.Temperature", NULL, "%s", 0, kelvin_celsius_conversion }, - { "battery.type", 0, 0, "UPS.PowerSummary.iDeviceChemistry", NULL, "%s", 0, stringid_conversion }, - { "battery.mfr.date", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.Battery.ManufacturerDate", NULL, "%s", HU_FLAG_SEMI_STATIC, date_conversion }, - { "battery.mfr.date", 0, 0, "UPS.PowerSummary.APCBattReplaceDate", NULL, "%s", 0, apc_date_conversion }, /* Back-UPS 500, Back-UPS ES/CyberFort 500 */ - { "battery.date", 0, 0, "UPS.Battery.APCBattReplaceDate", NULL, "%s", 0, apc_date_conversion }, /* Observed values: 0x0 on Back-UPS ES 650, 0x92501 on Back-UPS BF500 whose manufacture date was 2005/01/20 - this makes little sense but at least it's a valid date. */ - - /* UPS page */ - { "ups.load", 0, 0, "UPS.Output.PercentLoad", NULL, "%.1f", 0, NULL }, - { "ups.load", 0, 0, "UPS.PowerConverter.PercentLoad", NULL, "%.0f", 0, NULL }, - /* USB HID PDC defaults */ - { "ups.delay.start", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.PowerSummary.DelayBeforeStartup", NULL, DEFAULT_ONDELAY, HU_FLAG_ABSENT, NULL}, - { "ups.delay.shutdown", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.PowerSummary.DelayBeforeShutdown", NULL, DEFAULT_OFFDELAY, HU_FLAG_ABSENT, NULL}, - { "ups.timer.start", 0, 0, "UPS.PowerSummary.DelayBeforeStartup", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL}, - { "ups.timer.shutdown", 0, 0, "UPS.PowerSummary.DelayBeforeShutdown", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL}, - { "ups.timer.reboot", 0, 0, "UPS.PowerSummary.DelayBeforeReboot", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL}, - /* used by APC SmartUPS RM */ - { "ups.delay.start", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.Output.DelayBeforeStartup", NULL, DEFAULT_ONDELAY, HU_FLAG_ABSENT, NULL}, - { "ups.delay.shutdown", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.Output.DelayBeforeShutdown", NULL, DEFAULT_OFFDELAY, HU_FLAG_ABSENT, NULL}, - { "ups.timer.start", 0, 0, "UPS.Output.DelayBeforeStartup", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL}, - { "ups.timer.shutdown", 0, 0, "UPS.Output.DelayBeforeShutdown", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL}, - { "ups.timer.reboot", 0, 0, "UPS.Output.DelayBeforeReboot", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL}, - /* used by APC BackUPS ES */ - { "ups.delay.start", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.APCGeneralCollection.APCDelayBeforeStartup", NULL, DEFAULT_ONDELAY, HU_FLAG_ABSENT, NULL}, - { "ups.delay.shutdown", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.APCGeneralCollection.APCDelayBeforeShutdown", NULL, DEFAULT_OFFDELAY, HU_FLAG_ABSENT, NULL}, - { "ups.timer.start", 0, 0, "UPS.APCGeneralCollection.APCDelayBeforeStartup", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL}, - { "ups.timer.shutdown", 0, 0, "UPS.APCGeneralCollection.APCDelayBeforeShutdown", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL}, - { "ups.timer.reboot", 0, 0, "UPS.APCGeneralCollection.APCDelayBeforeReboot", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL}, - { "ups.test.result", 0, 0, "UPS.Battery.Test", NULL, "%s", 0, test_read_info }, - { "ups.beeper.status", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "%s", 0, beeper_info }, - { "ups.mfr.date", 0, 0, "UPS.ManufacturerDate", NULL, "%s", 0, date_conversion }, - { "ups.mfr.date", 0, 0, "UPS.PowerSummary.ManufacturerDate", NULL, "%s", 0, date_conversion }, /* Back-UPS 500 */ - { "ups.realpower.nominal", 0, 0, "UPS.PowerConverter.ConfigActivePower", NULL, "%.0f", 0, NULL }, - { "ups.realpower.nominal", 0, 0, "UPS.Output.ConfigActivePower", NULL, "%.0f", 0, NULL }, - - /* the below one need to be discussed as we might need to complete - * the ups.test sub collection - * { "ups.test.panel", 0, 0, "UPS.APCPanelTest", NULL, "%.0f", 0, NULL }, */ - - /* Special case: ups.status & ups.alarm */ - { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.ACPresent", NULL, NULL, HU_FLAG_QUICK_POLL, online_info }, - { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Discharging", NULL, NULL, HU_FLAG_QUICK_POLL, discharging_info }, - { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Charging", NULL, NULL, HU_FLAG_QUICK_POLL, charging_info }, - { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.ShutdownImminent", NULL, NULL, 0, shutdownimm_info }, - { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.BelowRemainingCapacityLimit", NULL, NULL, HU_FLAG_QUICK_POLL, lowbatt_info }, - { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Overload", NULL, NULL, 0, overload_info }, - { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.NeedReplacement", NULL, NULL, 0, replacebatt_info }, - { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.RemainingTimeLimitExpired", NULL, NULL, 0, timelimitexpired_info }, - { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.BatteryPresent", NULL, NULL, 0, nobattery_info }, - - { "BOOL", 0, 0, "UPS.PowerSummary.Charging", NULL, NULL, HU_FLAG_QUICK_POLL, charging_info }, /* Back-UPS 500 */ - { "BOOL", 0, 0, "UPS.PowerSummary.Discharging", NULL, NULL, HU_FLAG_QUICK_POLL, discharging_info }, /* Back-UPS 500 */ - { "BOOL", 0, 0, "UPS.PowerSummary.ACPresent", NULL, NULL, HU_FLAG_QUICK_POLL, online_info }, /* Back-UPS 500 */ - { "BOOL", 0, 0, "UPS.PowerSummary.BelowRemainingCapacityLimit", NULL, NULL, HU_FLAG_QUICK_POLL, lowbatt_info }, /* Back-UPS 500 */ - { "BOOL", 0, 0, "UPS.PowerSummary.ShutdownImminent", NULL, NULL, 0, shutdownimm_info }, - { "BOOL", 0, 0, "UPS.PowerSummary.APCStatusFlag", NULL, NULL, HU_FLAG_QUICK_POLL, apcstatusflag_info }, /* APC Back-UPS LS 500 */ - - /* we map 2 times "input.transfer.reason" to be able to clear - * both vrange (voltage) and frange (frequency) */ - { "BOOL", 0, 0, "UPS.Input.APCLineFailCause", NULL, NULL, 0, apc_linefailcause_vrange_info }, - { "BOOL", 0, 0, "UPS.Input.APCLineFailCause", NULL, NULL, 0, apc_linefailcause_frange_info }, - - /* Input page */ - { "input.voltage", 0, 0, "UPS.Input.Voltage", NULL, "%.1f", 0, NULL }, - { "input.voltage.nominal", 0, 0, "UPS.Input.ConfigVoltage", NULL, "%.0f", 0, NULL }, - { "input.transfer.low", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.Output.LowVoltageTransfer", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL }, - { "input.transfer.high", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.Output.HighVoltageTransfer", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL }, - /* used by APC BackUPS RS */ - { "input.transfer.low", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.Input.LowVoltageTransfer", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL }, - { "input.transfer.high", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.Input.HighVoltageTransfer", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL }, - { "input.sensitivity", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.Input.APCSensitivity", NULL, "%s", HU_FLAG_SEMI_STATIC, apc_sensitivity_info }, - - /* Output page */ - { "output.voltage", 0, 0, "UPS.Output.Voltage", NULL, "%.1f", 0, NULL }, - { "output.voltage.nominal", 0, 0, "UPS.Output.ConfigVoltage", NULL, "%.1f", 0, NULL }, - { "output.current", 0, 0, "UPS.Output.Current", NULL, "%.2f", 0, NULL }, - { "output.frequency", 0, 0, "UPS.Output.Frequency", NULL, "%.1f", 0, NULL }, - - /* Environmental page */ - { "ambient.temperature", 0, 0, "UPS.APCEnvironment.APCProbe1.Temperature", NULL, "%s", 0, kelvin_celsius_conversion }, - { "ambient.humidity", 0, 0, "UPS.APCEnvironment.APCProbe1.Humidity", NULL, "%.1f", 0, NULL }, + /* Battery page */ + { "battery.charge", 0, 0, "UPS.PowerSummary.RemainingCapacity", NULL, "%.0f", 0, NULL }, + { "battery.charge.low", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.PowerSummary.RemainingCapacityLimit", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL }, + { "battery.charge.warning", 0, 0, "UPS.PowerSummary.WarningCapacityLimit", NULL, "%.0f", 0, NULL }, + { "battery.runtime", 0, 0, "UPS.Battery.RunTimeToEmpty", NULL, "%.0f", 0, NULL }, + { "battery.runtime", 0, 0, "UPS.PowerSummary.RunTimeToEmpty", NULL, "%.0f", 0, NULL }, + { "battery.runtime.low", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.Battery.RemainingTimeLimit", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL }, + { "battery.runtime.low", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.PowerSummary.RemainingTimeLimit", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL }, + { "battery.voltage", 0, 0, "UPS.Battery.Voltage", NULL, "%.1f", 0, NULL }, + { "battery.voltage", 0, 0, "UPS.PowerSummary.Voltage", NULL, "%.1f", 0, NULL }, + { "battery.voltage.nominal", 0, 0, "UPS.Battery.ConfigVoltage", NULL, "%.1f", 0, NULL }, + { "battery.voltage.nominal", 0, 0, "UPS.PowerSummary.ConfigVoltage", NULL, "%.1f", 0, NULL }, /* Back-UPS 500 */ + { "battery.temperature", 0, 0, "UPS.Battery.Temperature", NULL, "%s", 0, kelvin_celsius_conversion }, + { "battery.type", 0, 0, "UPS.PowerSummary.iDeviceChemistry", NULL, "%s", 0, stringid_conversion }, + { "battery.mfr.date", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.Battery.ManufacturerDate", NULL, "%s", HU_FLAG_SEMI_STATIC, date_conversion }, + { "battery.mfr.date", 0, 0, "UPS.PowerSummary.APCBattReplaceDate", NULL, "%s", 0, apc_date_conversion }, /* Back-UPS 500, Back-UPS ES/CyberFort 500 */ + { "battery.date", 0, 0, "UPS.Battery.APCBattReplaceDate", NULL, "%s", 0, apc_date_conversion }, /* Observed values: 0x0 on Back-UPS ES 650, 0x92501 on Back-UPS BF500 whose manufacture date was 2005/01/20 - this makes little sense but at least it's a valid date. */ + + /* UPS page */ + { "ups.load", 0, 0, "UPS.Output.PercentLoad", NULL, "%.1f", 0, NULL }, + { "ups.load", 0, 0, "UPS.PowerConverter.PercentLoad", NULL, "%.0f", 0, NULL }, + /* USB HID PDC defaults */ + { "ups.delay.start", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.PowerSummary.DelayBeforeStartup", NULL, DEFAULT_ONDELAY, HU_FLAG_ABSENT, NULL}, + { "ups.delay.shutdown", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.PowerSummary.DelayBeforeShutdown", NULL, DEFAULT_OFFDELAY, HU_FLAG_ABSENT, NULL}, + { "ups.timer.start", 0, 0, "UPS.PowerSummary.DelayBeforeStartup", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL}, + { "ups.timer.shutdown", 0, 0, "UPS.PowerSummary.DelayBeforeShutdown", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL}, + { "ups.timer.reboot", 0, 0, "UPS.PowerSummary.DelayBeforeReboot", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL}, + /* used by APC SmartUPS RM */ + { "ups.delay.start", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.Output.DelayBeforeStartup", NULL, DEFAULT_ONDELAY, HU_FLAG_ABSENT, NULL}, + { "ups.delay.shutdown", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.Output.DelayBeforeShutdown", NULL, DEFAULT_OFFDELAY, HU_FLAG_ABSENT, NULL}, + { "ups.timer.start", 0, 0, "UPS.Output.DelayBeforeStartup", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL}, + { "ups.timer.shutdown", 0, 0, "UPS.Output.DelayBeforeShutdown", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL}, + { "ups.timer.reboot", 0, 0, "UPS.Output.DelayBeforeReboot", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL}, + /* used by APC BackUPS ES */ + { "ups.delay.start", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.APCGeneralCollection.APCDelayBeforeStartup", NULL, DEFAULT_ONDELAY, HU_FLAG_ABSENT, NULL}, + { "ups.delay.shutdown", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.APCGeneralCollection.APCDelayBeforeShutdown", NULL, DEFAULT_OFFDELAY, HU_FLAG_ABSENT, NULL}, + { "ups.timer.start", 0, 0, "UPS.APCGeneralCollection.APCDelayBeforeStartup", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL}, + { "ups.timer.shutdown", 0, 0, "UPS.APCGeneralCollection.APCDelayBeforeShutdown", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL}, + { "ups.timer.reboot", 0, 0, "UPS.APCGeneralCollection.APCDelayBeforeReboot", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL}, + { "ups.test.result", 0, 0, "UPS.Battery.Test", NULL, "%s", 0, test_read_info }, + { "ups.beeper.status", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "%s", 0, beeper_info }, + { "ups.mfr.date", 0, 0, "UPS.ManufacturerDate", NULL, "%s", 0, date_conversion }, + { "ups.mfr.date", 0, 0, "UPS.PowerSummary.ManufacturerDate", NULL, "%s", 0, date_conversion }, /* Back-UPS 500 */ + { "ups.realpower.nominal", 0, 0, "UPS.PowerConverter.ConfigActivePower", NULL, "%.0f", 0, NULL }, + { "ups.realpower.nominal", 0, 0, "UPS.Output.ConfigActivePower", NULL, "%.0f", 0, NULL }, + + /* the below one need to be discussed as we might need to complete + * the ups.test sub collection + * { "ups.test.panel", 0, 0, "UPS.APCPanelTest", NULL, "%.0f", 0, NULL }, */ + + /* Special case: ups.status & ups.alarm */ + { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.ACPresent", NULL, NULL, HU_FLAG_QUICK_POLL, online_info }, + { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Discharging", NULL, NULL, HU_FLAG_QUICK_POLL, discharging_info }, + { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Charging", NULL, NULL, HU_FLAG_QUICK_POLL, charging_info }, + { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.ShutdownImminent", NULL, NULL, 0, shutdownimm_info }, + { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.BelowRemainingCapacityLimit", NULL, NULL, HU_FLAG_QUICK_POLL, lowbatt_info }, + { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Overload", NULL, NULL, 0, overload_info }, + { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.NeedReplacement", NULL, NULL, 0, replacebatt_info }, + { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.RemainingTimeLimitExpired", NULL, NULL, 0, timelimitexpired_info }, + { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.BatteryPresent", NULL, NULL, 0, nobattery_info }, + + { "BOOL", 0, 0, "UPS.PowerSummary.Charging", NULL, NULL, HU_FLAG_QUICK_POLL, charging_info }, /* Back-UPS 500 */ + { "BOOL", 0, 0, "UPS.PowerSummary.Discharging", NULL, NULL, HU_FLAG_QUICK_POLL, discharging_info }, /* Back-UPS 500 */ + { "BOOL", 0, 0, "UPS.PowerSummary.ACPresent", NULL, NULL, HU_FLAG_QUICK_POLL, online_info }, /* Back-UPS 500 */ + { "BOOL", 0, 0, "UPS.PowerSummary.BelowRemainingCapacityLimit", NULL, NULL, HU_FLAG_QUICK_POLL, lowbatt_info }, /* Back-UPS 500 */ + { "BOOL", 0, 0, "UPS.PowerSummary.ShutdownImminent", NULL, NULL, 0, shutdownimm_info }, + { "BOOL", 0, 0, "UPS.PowerSummary.APCStatusFlag", NULL, NULL, HU_FLAG_QUICK_POLL, apcstatusflag_info }, /* APC Back-UPS LS 500 */ + + /* we map 2 times "input.transfer.reason" to be able to clear + * both vrange (voltage) and frange (frequency) */ + { "BOOL", 0, 0, "UPS.Input.APCLineFailCause", NULL, NULL, 0, apc_linefailcause_vrange_info }, + { "BOOL", 0, 0, "UPS.Input.APCLineFailCause", NULL, NULL, 0, apc_linefailcause_frange_info }, + + /* Input page */ + { "input.voltage", 0, 0, "UPS.Input.Voltage", NULL, "%.1f", 0, NULL }, + { "input.voltage.nominal", 0, 0, "UPS.Input.ConfigVoltage", NULL, "%.0f", 0, NULL }, + { "input.transfer.low", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.Output.LowVoltageTransfer", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL }, + { "input.transfer.high", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.Output.HighVoltageTransfer", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL }, + /* used by APC BackUPS RS */ + { "input.transfer.low", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.Input.LowVoltageTransfer", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL }, + { "input.transfer.high", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.Input.HighVoltageTransfer", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL }, + { "input.sensitivity", ST_FLAG_RW | ST_FLAG_STRING, 10, "UPS.Input.APCSensitivity", NULL, "%s", HU_FLAG_SEMI_STATIC, apc_sensitivity_info }, + + /* Output page */ + { "output.voltage", 0, 0, "UPS.Output.Voltage", NULL, "%.1f", 0, NULL }, + { "output.voltage.nominal", 0, 0, "UPS.Output.ConfigVoltage", NULL, "%.1f", 0, NULL }, + { "output.current", 0, 0, "UPS.Output.Current", NULL, "%.2f", 0, NULL }, + { "output.frequency", 0, 0, "UPS.Output.Frequency", NULL, "%.1f", 0, NULL }, + + /* Environmental page */ + { "ambient.temperature", 0, 0, "UPS.APCEnvironment.APCProbe1.Temperature", NULL, "%s", 0, kelvin_celsius_conversion }, + { "ambient.humidity", 0, 0, "UPS.APCEnvironment.APCProbe1.Humidity", NULL, "%.1f", 0, NULL }, /* - { "ambient.temperature", 0, 0, "UPS.APCEnvironment.APCProbe2.Temperature", NULL, "%.1f", 0, kelvin_celsius_conversion }, - { "ambient.humidity", 0, 0, "UPS.APCEnvironment.APCProbe2.Humidity", NULL, "%.1f", 0, NULL }, + { "ambient.temperature", 0, 0, "UPS.APCEnvironment.APCProbe2.Temperature", NULL, "%.1f", 0, kelvin_celsius_conversion }, + { "ambient.humidity", 0, 0, "UPS.APCEnvironment.APCProbe2.Humidity", NULL, "%.1f", 0, NULL }, */ - /* instant commands. */ - /* test.* split into subset while waiting for extradata support - * ie: test.battery.start quick - */ - { "test.battery.start.quick", 0, 0, "UPS.BatterySystem.Battery.Test", NULL, "1", HU_TYPE_CMD, NULL }, - { "test.battery.start.quick", 0, 0, "UPS.Battery.Test", NULL, "1", HU_TYPE_CMD, NULL }, /* Back-UPS RS (experimental) */ - { "test.battery.start.deep", 0, 0, "UPS.BatterySystem.Battery.Test", NULL, "2", HU_TYPE_CMD, NULL }, - { "test.battery.start.deep", 0, 0, "UPS.Battery.Test", NULL, "2", HU_TYPE_CMD, NULL }, /* Back-UPS RS (experimental) */ - { "test.battery.stop", 0, 0, "UPS.BatterySystem.Battery.Test", NULL, "3", HU_TYPE_CMD, NULL }, - { "test.battery.stop", 0, 0, "UPS.Battery.Test", NULL, "3", HU_TYPE_CMD, NULL }, /* Back-UPS RS (experimental) */ - { "test.panel.start", 0, 0, "UPS.APCPanelTest", NULL, "1", HU_TYPE_CMD, NULL }, - { "test.panel.stop", 0, 0, "UPS.APCPanelTest", NULL, "0", HU_TYPE_CMD, NULL }, - { "test.panel.start", 0, 0, "UPS.PowerSummary.APCPanelTest", NULL, "1", HU_TYPE_CMD, NULL }, /* Back-UPS 500 */ - { "test.panel.stop", 0, 0, "UPS.PowerSummary.APCPanelTest", NULL, "0", HU_TYPE_CMD, NULL }, /* Back-UPS 500 */ - - /* USB HID PDC defaults */ - { "load.off.delay", 0, 0, "UPS.PowerSummary.DelayBeforeShutdown", NULL, DEFAULT_OFFDELAY, HU_TYPE_CMD, NULL }, - { "load.on.delay", 0, 0, "UPS.PowerSummary.DelayBeforeStartup", NULL, DEFAULT_ONDELAY, HU_TYPE_CMD, NULL }, - { "shutdown.stop", 0, 0, "UPS.PowerSummary.DelayBeforeShutdown", NULL, "-1", HU_TYPE_CMD, NULL }, - { "shutdown.reboot", 0, 0, "UPS.PowerSummary.DelayBeforeReboot", NULL, "10", HU_TYPE_CMD, NULL }, - /* used by APC SmartUPS RM */ - { "load.off.delay", 0, 0, "UPS.Output.DelayBeforeShutdown", NULL, DEFAULT_OFFDELAY, HU_TYPE_CMD, NULL }, - { "load.on.delay", 0, 0, "UPS.Output.DelayBeforeStartup", NULL, DEFAULT_ONDELAY, HU_TYPE_CMD, NULL }, - { "shutdown.stop", 0, 0, "UPS.Output.DelayBeforeShutdown", NULL, "-1", HU_TYPE_CMD, NULL }, - { "shutdown.reboot", 0, 0, "UPS.Output.DelayBeforeReboot", NULL, "10", HU_TYPE_CMD, NULL }, - /* used by APC BackUPS ES */ - { "load.off.delay", 0, 0, "UPS.APCGeneralCollection.APCDelayBeforeShutdown", NULL, DEFAULT_OFFDELAY, HU_TYPE_CMD, NULL }, - { "load.on.delay", 0, 0, "UPS.APCGeneralCollection.APCDelayBeforeStartup", NULL, DEFAULT_ONDELAY, HU_TYPE_CMD, NULL }, - { "shutdown.stop", 0, 0, "UPS.APCGeneralCollection.APCDelayBeforeShutdown", NULL, "-1", HU_TYPE_CMD, NULL }, - { "shutdown.reboot", 0, 0, "UPS.APCGeneralCollection.APCDelayBeforeReboot", NULL, "10", HU_TYPE_CMD, NULL }, - /* used by APC BackUPS CS */ - { "shutdown.return", 0, 0, "UPS.Output.APCDelayBeforeReboot", NULL, "1", HU_TYPE_CMD, NULL }, - - { "beeper.on", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "2", HU_TYPE_CMD, NULL }, - { "beeper.off", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "3", HU_TYPE_CMD, NULL }, - { "beeper.enable", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "2", HU_TYPE_CMD, NULL }, - { "beeper.disable", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "1", HU_TYPE_CMD, NULL }, - { "beeper.mute", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "3", HU_TYPE_CMD, NULL }, - - /* end of structure. */ - { NULL, 0, 0, NULL, NULL, NULL, 0, NULL } + /* instant commands. */ + /* test.* split into subset while waiting for extradata support + * ie: test.battery.start quick + */ + { "test.battery.start.quick", 0, 0, "UPS.BatterySystem.Battery.Test", NULL, "1", HU_TYPE_CMD, NULL }, + { "test.battery.start.quick", 0, 0, "UPS.Battery.Test", NULL, "1", HU_TYPE_CMD, NULL }, /* Back-UPS RS (experimental) */ + { "test.battery.start.deep", 0, 0, "UPS.BatterySystem.Battery.Test", NULL, "2", HU_TYPE_CMD, NULL }, + { "test.battery.start.deep", 0, 0, "UPS.Battery.Test", NULL, "2", HU_TYPE_CMD, NULL }, /* Back-UPS RS (experimental) */ + { "test.battery.stop", 0, 0, "UPS.BatterySystem.Battery.Test", NULL, "3", HU_TYPE_CMD, NULL }, + { "test.battery.stop", 0, 0, "UPS.Battery.Test", NULL, "3", HU_TYPE_CMD, NULL }, /* Back-UPS RS (experimental) */ + { "test.panel.start", 0, 0, "UPS.APCPanelTest", NULL, "1", HU_TYPE_CMD, NULL }, + { "test.panel.stop", 0, 0, "UPS.APCPanelTest", NULL, "0", HU_TYPE_CMD, NULL }, + { "test.panel.start", 0, 0, "UPS.PowerSummary.APCPanelTest", NULL, "1", HU_TYPE_CMD, NULL }, /* Back-UPS 500 */ + { "test.panel.stop", 0, 0, "UPS.PowerSummary.APCPanelTest", NULL, "0", HU_TYPE_CMD, NULL }, /* Back-UPS 500 */ + + /* USB HID PDC defaults */ + { "load.off.delay", 0, 0, "UPS.PowerSummary.DelayBeforeShutdown", NULL, DEFAULT_OFFDELAY, HU_TYPE_CMD, NULL }, + { "load.on.delay", 0, 0, "UPS.PowerSummary.DelayBeforeStartup", NULL, DEFAULT_ONDELAY, HU_TYPE_CMD, NULL }, + { "shutdown.stop", 0, 0, "UPS.PowerSummary.DelayBeforeShutdown", NULL, "-1", HU_TYPE_CMD, NULL }, + { "shutdown.reboot", 0, 0, "UPS.PowerSummary.DelayBeforeReboot", NULL, "10", HU_TYPE_CMD, NULL }, + /* used by APC SmartUPS RM */ + { "load.off.delay", 0, 0, "UPS.Output.DelayBeforeShutdown", NULL, DEFAULT_OFFDELAY, HU_TYPE_CMD, NULL }, + { "load.on.delay", 0, 0, "UPS.Output.DelayBeforeStartup", NULL, DEFAULT_ONDELAY, HU_TYPE_CMD, NULL }, + { "shutdown.stop", 0, 0, "UPS.Output.DelayBeforeShutdown", NULL, "-1", HU_TYPE_CMD, NULL }, + { "shutdown.reboot", 0, 0, "UPS.Output.DelayBeforeReboot", NULL, "10", HU_TYPE_CMD, NULL }, + /* used by APC BackUPS ES */ + { "load.off.delay", 0, 0, "UPS.APCGeneralCollection.APCDelayBeforeShutdown", NULL, DEFAULT_OFFDELAY, HU_TYPE_CMD, NULL }, + { "load.on.delay", 0, 0, "UPS.APCGeneralCollection.APCDelayBeforeStartup", NULL, DEFAULT_ONDELAY, HU_TYPE_CMD, NULL }, + { "shutdown.stop", 0, 0, "UPS.APCGeneralCollection.APCDelayBeforeShutdown", NULL, "-1", HU_TYPE_CMD, NULL }, + { "shutdown.reboot", 0, 0, "UPS.APCGeneralCollection.APCDelayBeforeReboot", NULL, "10", HU_TYPE_CMD, NULL }, + /* used by APC BackUPS CS */ + { "shutdown.return", 0, 0, "UPS.Output.APCDelayBeforeReboot", NULL, "1", HU_TYPE_CMD, NULL }, + + { "beeper.on", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "2", HU_TYPE_CMD, NULL }, + { "beeper.off", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "3", HU_TYPE_CMD, NULL }, + { "beeper.enable", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "2", HU_TYPE_CMD, NULL }, + { "beeper.disable", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "1", HU_TYPE_CMD, NULL }, + { "beeper.mute", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "3", HU_TYPE_CMD, NULL }, + + /* end of structure. */ + { NULL, 0, 0, NULL, NULL, NULL, 0, NULL } }; static const char *apc_format_model(HIDDevice_t *hd) { @@ -535,11 +535,11 @@ static int apc_claim(HIDDevice_t *hd) { * the report IDs may be different. */ static int apc_fix_report_desc(HIDDevice_t *pDev, HIDDesc_t *pDesc_arg) { - HIDData_t *pData; - int res = 0; + HIDData_t *pData; + int res = 0; - int vendorID = pDev->VendorID; - int productID = pDev->ProductID; + int vendorID = pDev->VendorID; + int productID = pDev->ProductID; if (vendorID != APC_VENDORID || productID != 0x0002) { return 0; } @@ -570,34 +570,34 @@ static int apc_fix_report_desc(HIDDevice_t *pDev, HIDDesc_t *pDesc_arg) { */ if ((pData=FindObject_with_ID_Node(pDesc_arg, 0x33, USAGE_POW_HIGH_VOLTAGE_TRANSFER))) { - long hvt_logmin = pData->LogMin; - long hvt_logmax = pData->LogMax; + long hvt_logmin = pData->LogMin; + long hvt_logmax = pData->LogMax; upsdebugx(4, "Report Descriptor: highVoltageTransfer LogMin: %ld LogMax: %ld", hvt_logmin, hvt_logmax); if ((pData=FindObject_with_ID_Node(pDesc_arg, 0x31, USAGE_POW_VOLTAGE))) { - long voltage_logmin = pData->LogMin; - long voltage_logmax = pData->LogMax; + long voltage_logmin = pData->LogMin; + long voltage_logmax = pData->LogMax; upsdebugx(4, "Report Descriptor: voltage LogMin: %ld LogMax: %ld", - voltage_logmin, voltage_logmax); + voltage_logmin, voltage_logmax); if (hvt_logmax > voltage_logmax) { pData->LogMin = 0; /* a reasonable lower limit for voltage */ pData->LogMax = hvt_logmax * 2; /* it may be smoking at this point */ upsdebugx(3, "Fixing Report Descriptor. Set voltage LogMin = %ld, LogMax = %ld", - pData->LogMin , pData->LogMax); + pData->LogMin , pData->LogMax); res = 1; } } if ((pData=FindObject_with_ID_Node(pDesc_arg, 0x30, USAGE_POW_CONFIG_VOLTAGE))) { - long cvoltage_logmin = pData->LogMin; - long cvoltage_logmax = pData->LogMax; + long cvoltage_logmin = pData->LogMin; + long cvoltage_logmax = pData->LogMax; upsdebugx(4, "Report Descriptor: configVoltage LogMin: %ld LogMax: %ld", cvoltage_logmin, cvoltage_logmax); if (hvt_logmax > cvoltage_logmax) { pData->LogMax = 255; upsdebugx(3, "Fixing Report Descriptor. Set configVoltage LogMin = %ld, LogMax = %ld", - pData->LogMin , pData->LogMax); + pData->LogMin , pData->LogMax); res = 1; } } diff --git a/drivers/apcsmart-old.c b/drivers/apcsmart-old.c index 94b0365684..dcae58d357 100644 --- a/drivers/apcsmart-old.c +++ b/drivers/apcsmart-old.c @@ -1016,11 +1016,12 @@ static void upsdrv_shutdown_simple(long status) static void upsdrv_shutdown_advanced(long status) { const char *strval; - const char deforder[] = {48 + SDIDX_S, - 48 + SDIDX_AT3N, - 48 + SDIDX_K, - 48 + SDIDX_Z, - 0}; + const char deforder[] = { + 48 + SDIDX_S, + 48 + SDIDX_AT3N, + 48 + SDIDX_K, + 48 + SDIDX_Z, + 0}; size_t i; long n; diff --git a/drivers/apcsmart.c b/drivers/apcsmart.c index 5d96dd052c..7cf11bd5d3 100644 --- a/drivers/apcsmart.c +++ b/drivers/apcsmart.c @@ -2083,9 +2083,11 @@ static int instcmd(const char *cmd, const char *ext) } if (!(ct->flags & APC_PRESENT)) { - upslogx(LOG_INSTCMD_INVALID, "%s: command [%s %s] recognized, but" - " not supported by your UPS model", __func__, cmd, - ext ? ext : "\b"); + upslogx(LOG_INSTCMD_INVALID, + "%s: command [%s %s] recognized, but" + " not supported by your UPS model", + __func__, cmd, + ext ? ext : "\b"); return STAT_INSTCMD_INVALID; } diff --git a/drivers/bcmxcp.c b/drivers/bcmxcp.c index d4695ed6ee..dd00e00b88 100644 --- a/drivers/bcmxcp.c +++ b/drivers/bcmxcp.c @@ -1087,67 +1087,79 @@ void init_ext_vars(void) length = command_write_sequence(cbuf, 4, answer); if (length <= 0) fatal_with_errno(EXIT_FAILURE, "Could not communicate with the ups"); - if (length < 4) /* UPS doesn't have configurable vars */ + if (length < 4) /* UPS doesn't have configurable vars */ return; + for (index=3; index < length; index++) { switch(answer[index]) { - case PW_CONF_LOW_DEV_LIMIT: dstate_setinfo("input.transfer.boost.high", "%d", 0); - dstate_setflags("input.transfer.boost.high", ST_FLAG_RW | ST_FLAG_STRING); - dstate_setaux("input.transfer.boost.high", 3); - break; - - case PW_CONF_HIGH_DEV_LIMIT: dstate_setinfo("input.transfer.trim.low", "%d", 0); - dstate_setflags("input.transfer.trim.low", ST_FLAG_RW | ST_FLAG_STRING); - dstate_setaux("input.transfer.trim.low", 3); - break; - - case PW_CONF_LOW_BATT: dstate_setinfo("battery.runtime.low", "%d", 0); - dstate_setflags("battery.runtime.low", ST_FLAG_RW | ST_FLAG_STRING); - dstate_setaux("battery.runtime.low", 2); - break; - - case PW_CONF_BEEPER: dstate_addcmd("beeper.disable"); - dstate_addcmd("beeper.enable"); - dstate_addcmd("beeper.mute"); - break; - - case PW_CONF_RETURN_DELAY: dstate_setinfo("input.transfer.delay", "%d", 0); - dstate_setflags("input.transfer.delay", ST_FLAG_RW | ST_FLAG_STRING); - dstate_setaux("input.transfer.delay", 5); - break; - - case PW_CONF_RETURN_CAP: dstate_setinfo("battery.charge.restart", "%d", 0); - dstate_setflags("battery.charge.restart", ST_FLAG_RW | ST_FLAG_STRING); - dstate_setaux("battery.charge.restart", 3); - break; - - case PW_CONF_MAX_TEMP: dstate_setinfo("ambient.temperature.high", "%d", 0); - dstate_setflags("ambient.temperature.high", ST_FLAG_RW | ST_FLAG_STRING); - dstate_setaux("ambient.temperature.high", 3); - break; - - case PW_CONF_NOMINAL_OUT_VOLTAGE: dstate_setinfo("output.voltage.nominal", "%d", 0); - dstate_setflags("output.voltage.nominal", ST_FLAG_RW | ST_FLAG_STRING); - dstate_setaux("output.voltage.nominal", 3); - break; - - case PW_CONF_SLEEP_TH_LOAD: dstate_setinfo("battery.energysave.load", "%d", 0); - dstate_setflags("battery.energysave.load", ST_FLAG_RW | ST_FLAG_STRING); - dstate_setaux("battery.energysave.load", 3); - break; - - case PW_CONF_SLEEP_DELAY: dstate_setinfo("battery.energysave.delay", "%d", 0); - dstate_setflags("battery.energysave.delay", ST_FLAG_RW | ST_FLAG_STRING); - dstate_setaux("battery.energysave.delay", 3); - break; - - case PW_CONF_BATT_STRINGS: dstate_setinfo("battery.packs", "%d", 0); - dstate_setflags("battery.packs", ST_FLAG_RW | ST_FLAG_STRING); - dstate_setaux("battery.packs", 1); - break; + case PW_CONF_LOW_DEV_LIMIT: + dstate_setinfo("input.transfer.boost.high", "%d", 0); + dstate_setflags("input.transfer.boost.high", ST_FLAG_RW | ST_FLAG_STRING); + dstate_setaux("input.transfer.boost.high", 3); + break; + + case PW_CONF_HIGH_DEV_LIMIT: + dstate_setinfo("input.transfer.trim.low", "%d", 0); + dstate_setflags("input.transfer.trim.low", ST_FLAG_RW | ST_FLAG_STRING); + dstate_setaux("input.transfer.trim.low", 3); + break; + + case PW_CONF_LOW_BATT: + dstate_setinfo("battery.runtime.low", "%d", 0); + dstate_setflags("battery.runtime.low", ST_FLAG_RW | ST_FLAG_STRING); + dstate_setaux("battery.runtime.low", 2); + break; + + case PW_CONF_BEEPER: + dstate_addcmd("beeper.disable"); + dstate_addcmd("beeper.enable"); + dstate_addcmd("beeper.mute"); + break; + + case PW_CONF_RETURN_DELAY: + dstate_setinfo("input.transfer.delay", "%d", 0); + dstate_setflags("input.transfer.delay", ST_FLAG_RW | ST_FLAG_STRING); + dstate_setaux("input.transfer.delay", 5); + break; + + case PW_CONF_RETURN_CAP: + dstate_setinfo("battery.charge.restart", "%d", 0); + dstate_setflags("battery.charge.restart", ST_FLAG_RW | ST_FLAG_STRING); + dstate_setaux("battery.charge.restart", 3); + break; + + case PW_CONF_MAX_TEMP: + dstate_setinfo("ambient.temperature.high", "%d", 0); + dstate_setflags("ambient.temperature.high", ST_FLAG_RW | ST_FLAG_STRING); + dstate_setaux("ambient.temperature.high", 3); + break; + + case PW_CONF_NOMINAL_OUT_VOLTAGE: + dstate_setinfo("output.voltage.nominal", "%d", 0); + dstate_setflags("output.voltage.nominal", ST_FLAG_RW | ST_FLAG_STRING); + dstate_setaux("output.voltage.nominal", 3); + break; + + case PW_CONF_SLEEP_TH_LOAD: + dstate_setinfo("battery.energysave.load", "%d", 0); + dstate_setflags("battery.energysave.load", ST_FLAG_RW | ST_FLAG_STRING); + dstate_setaux("battery.energysave.load", 3); + break; + + case PW_CONF_SLEEP_DELAY: + dstate_setinfo("battery.energysave.delay", "%d", 0); + dstate_setflags("battery.energysave.delay", ST_FLAG_RW | ST_FLAG_STRING); + dstate_setaux("battery.energysave.delay", 3); + break; + + case PW_CONF_BATT_STRINGS: + dstate_setinfo("battery.packs", "%d", 0); + dstate_setflags("battery.packs", ST_FLAG_RW | ST_FLAG_STRING); + dstate_setaux("battery.packs", 1); + break; default: - break; + break; } } } @@ -1583,7 +1595,8 @@ void upsdrv_initinfo(void) if (bcmxcp_command_map[PW_INIT_SYS_TEST].command_byte > 0) { init_system_test_capabilities(); } - /* Get information about configurable external variables*/ + + /* Get information about configurable external variables*/ init_ext_vars(); upsh.instcmd = instcmd; @@ -1615,8 +1628,10 @@ void upsdrv_updateinfo(void) /* Loop thru meter map, get all data UPS is willing to offer */ for (iIndex = 0; iIndex < BCMXCP_METER_MAP_MAX; iIndex++) { if (bcmxcp_meter_map[iIndex].format != 0 && bcmxcp_meter_map[iIndex].nut_entity != NULL) { - decode_meter_map_entry(answer + bcmxcp_meter_map[iIndex].meter_block_index, - bcmxcp_meter_map[iIndex].format, sValue); + decode_meter_map_entry( + answer + bcmxcp_meter_map[iIndex].meter_block_index, + bcmxcp_meter_map[iIndex].format, + sValue); /* Set result */ dstate_setinfo(bcmxcp_meter_map[iIndex].nut_entity, "%s", sValue); @@ -1913,20 +1928,20 @@ float calculate_ups_load(const unsigned char *answer) bcmxcp_meter_map[BCMXCP_METER_MAP_OUTPUT_VA_BAR_CHART].format != 0) /* Max output VA */ { decode_meter_map_entry(answer + bcmxcp_meter_map[BCMXCP_METER_MAP_OUTPUT_VA].meter_block_index, - bcmxcp_meter_map[BCMXCP_METER_MAP_OUTPUT_VA].format, sValue); + bcmxcp_meter_map[BCMXCP_METER_MAP_OUTPUT_VA].format, sValue); output = atof(sValue); decode_meter_map_entry(answer + bcmxcp_meter_map[BCMXCP_METER_MAP_OUTPUT_VA_BAR_CHART].meter_block_index, - bcmxcp_meter_map[BCMXCP_METER_MAP_OUTPUT_VA_BAR_CHART].format, sValue); + bcmxcp_meter_map[BCMXCP_METER_MAP_OUTPUT_VA_BAR_CHART].format, sValue); max_output = atof(sValue); } else if (bcmxcp_meter_map[BCMXCP_METER_MAP_LOAD_CURRENT_PHASE_A].format != 0 && /* Output A */ - bcmxcp_meter_map[BCMXCP_METER_MAP_LOAD_CURRENT_PHASE_A_BAR_CHART].format != 0) /* Max output A */ + bcmxcp_meter_map[BCMXCP_METER_MAP_LOAD_CURRENT_PHASE_A_BAR_CHART].format != 0) /* Max output A */ { decode_meter_map_entry(answer + bcmxcp_meter_map[BCMXCP_METER_MAP_LOAD_CURRENT_PHASE_A].meter_block_index, - bcmxcp_meter_map[BCMXCP_METER_MAP_LOAD_CURRENT_PHASE_A].format, sValue); + bcmxcp_meter_map[BCMXCP_METER_MAP_LOAD_CURRENT_PHASE_A].format, sValue); output = atof(sValue); decode_meter_map_entry(answer + bcmxcp_meter_map[BCMXCP_METER_MAP_LOAD_CURRENT_PHASE_A_BAR_CHART].meter_block_index, - bcmxcp_meter_map[BCMXCP_METER_MAP_LOAD_CURRENT_PHASE_A_BAR_CHART].format, sValue); + bcmxcp_meter_map[BCMXCP_METER_MAP_LOAD_CURRENT_PHASE_A_BAR_CHART].format, sValue); max_output = atof(sValue); } if (max_output > 0.0) @@ -2073,7 +2088,7 @@ static int instcmd(const char *cmdname, const char *extra) return decode_instcmd_exec(res, (unsigned char)answer[0], cmdname, "Testing panel now"); } - if (!strcasecmp(cmdname, "beeper.disable") || !strcasecmp(cmdname, "beeper.enable") || !strcasecmp(cmdname, "beeper.mute")) { + if (!strcasecmp(cmdname, "beeper.disable") || !strcasecmp(cmdname, "beeper.enable") || !strcasecmp(cmdname, "beeper.mute")) { send_write_command(AUTHOR, 4); sleep(PW_SLEEP); /* Need to. Have to wait at least 0,25 sec max 16 sec */ @@ -2387,7 +2402,7 @@ int setvar (const char *varname, const char *val) } - if (!strcasecmp(varname, "output.voltage.nominal")) { + if (!strcasecmp(varname, "output.voltage.nominal")) { send_write_command(AUTHOR, 4); sleep(PW_SLEEP); /* Need to. Have to wait at least 0,25 sec max 16 sec */ diff --git a/drivers/bcmxcp_usb.c b/drivers/bcmxcp_usb.c index 6a726bc263..8ab3c32d38 100644 --- a/drivers/bcmxcp_usb.c +++ b/drivers/bcmxcp_usb.c @@ -302,7 +302,7 @@ ssize_t get_answer(unsigned char *data, unsigned char command) tail = (ssize_t)bytes_read; tail -= (ssize_t)(length + PW_HEADER_SIZE); if (tail > 0) - my_buf = (unsigned char*)memmove(&buf[0], my_buf + length + PW_HEADER_SIZE, (size_t)tail); + my_buf = (unsigned char*)memmove(&buf[0], my_buf + length + PW_HEADER_SIZE, (size_t)tail); else if (tail == 0) my_buf = &buf[0]; else { /* if (tail < 0) */ diff --git a/drivers/belkinunv.c b/drivers/belkinunv.c index f0bbed41cf..5c4b0d3d05 100644 --- a/drivers/belkinunv.c +++ b/drivers/belkinunv.c @@ -1390,7 +1390,7 @@ void upsdrv_initups(void) /* If '-x wait' or '-x wait=' option given, branch into * standalone behavior. */ if (getval("wait") || dstate_getinfo("driver.flag.wait")) { - exit(belkin_wait()); + exit(belkin_wait()); } belkin_nut_open_tty(); diff --git a/drivers/bestfortress.c b/drivers/bestfortress.c index 9795487287..713e99e672 100644 --- a/drivers/bestfortress.c +++ b/drivers/bestfortress.c @@ -264,8 +264,9 @@ static ssize_t upsrecv(char *buf,size_t bufsize,char ec,const char *ic) { ssize_t nread; - nread = ser_get_line(upsfd, buf, bufsize - 1, ec, ic, - SER_WAIT_SEC, SER_WAIT_USEC); + nread = ser_get_line( + upsfd, buf, bufsize - 1, ec, ic, + SER_WAIT_SEC, SER_WAIT_USEC); /* \todo is buf null terminated? */ upsdebugx(4, "%s: read %" PRIiSIZE " <%s>", __func__, nread, buf); @@ -302,7 +303,7 @@ void upsdrv_updateinfo(void) do { if ((recv = upsrecv (temp+2, sizeof temp - 2, ENDCHAR, IGNCHARS)) <= 0) { upsdebugx(1, "%s: upsrecv failed, " - "retrying without counting", __func__); + "retrying without counting", __func__); upsflushin (0, 0, "\r "); upssend ("f\r"); while (ser_get_char(upsfd, &ch, 0, UPSDELAY) > 0 && ch != '\n'); /* response starts with \r\n */ @@ -310,7 +311,7 @@ void upsdrv_updateinfo(void) } while (temp[2] == 0); upsdebugx(3, "%s: received %" PRIiSIZE " bytes (try %i)", - __func__, recv, retry); + __func__, recv, retry); /* syslog (LOG_DAEMON | LOG_NOTICE,"ups: got %d chars '%s'\n", recv, temp + 2); */ /* status example: @@ -330,11 +331,11 @@ void upsdrv_updateinfo(void) if (!checksum_ok) { upsdebug_hex(5, "upsdrv_updateinfo: " - "checksum failure buffer hex", - temp, (size_t)recv); + "checksum failure buffer hex", + temp, (size_t)recv); upsdebug_ascii(5, "upsdrv_updateinfo: " - "checksum failure buffer ascii", - temp, (size_t)recv); + "checksum failure buffer ascii", + temp, (size_t)recv); } @@ -352,7 +353,7 @@ void upsdrv_updateinfo(void) if (checksum_ok) break; upsdebugx(1, "%s: failed to read status try %d", - __func__, retry); + __func__, retry); sleep(SER_WAIT_SEC); } @@ -633,7 +634,7 @@ void upsdrv_initups(void) ser_set_speed(upsfd, device_path, speed); upsdebugx(1, "%s: opened %s speed %s upsfd %d", - __func__, device_path, speed_val ? speed_val : "DEFAULT", upsfd); + __func__, device_path, speed_val ? speed_val : "DEFAULT", upsfd); upsdebugx(1, "%s: end", __func__); } diff --git a/drivers/bicker_ser.c b/drivers/bicker_ser.c index d9a14cf760..218b943825 100644 --- a/drivers/bicker_ser.c +++ b/drivers/bicker_ser.c @@ -390,10 +390,10 @@ static ssize_t bicker_receive_parameter(uint8_t id, BickerParameter *dst) parameter.value = WORDLH(data[8], data[9]); upsdebugx(3, "Parameter %u = %u (%s, min = %u, max = %u, std = %u)", - (unsigned)parameter.id, (unsigned)parameter.value, - parameter.enabled ? "enabled" : "disabled", - (unsigned)parameter.min, (unsigned)parameter.max, - (unsigned)parameter.std); + (unsigned)parameter.id, (unsigned)parameter.value, + parameter.enabled ? "enabled" : "disabled", + (unsigned)parameter.min, (unsigned)parameter.max, + (unsigned)parameter.std); if (dst != NULL) { memcpy(dst, ¶meter, sizeof(parameter)); @@ -715,7 +715,7 @@ static int bicker_setvar(const char *varname, const char *val) if (parameter.enabled) { dstate_setinfo(varname, "%u", - (unsigned)parameter.value); + (unsigned)parameter.value); } else { /* Disabled parameters are removed from NUT */ dstate_delinfo(varname); @@ -879,9 +879,9 @@ void upsdrv_updateinfo(void) status_set("DISCHRG"); } dstate_setinfo("battery.charger.status", - (u8 & 0x01) > 0 ? "charging" : - (u8 & 0x02) > 0 ? "discharging" : - "resting"); + (u8 & 0x01) > 0 ? "charging" + : (u8 & 0x02) > 0 ? "discharging" + : "resting"); status_set((u8 & 0x04) > 0 ? "OL" : "OB"); if ((u8 & 0x20) > 0) { diff --git a/drivers/clone-outlet.c b/drivers/clone-outlet.c index d57aa9efdd..e95b89bdbe 100644 --- a/drivers/clone-outlet.c +++ b/drivers/clone-outlet.c @@ -455,7 +455,7 @@ static int sstate_dead(int maxage) if (elapsed > maxage) { upsdebugx(3, "sstate_dead: didn't hear from driver for UPS [%s] for %g seconds (max %d)", - device_path, elapsed, maxage); + device_path, elapsed, maxage); return -1; /* dead */ } diff --git a/drivers/dstate.c b/drivers/dstate.c index d368ce006f..d1cf9ba1bc 100644 --- a/drivers/dstate.c +++ b/drivers/dstate.c @@ -121,10 +121,11 @@ static void sock_fail(const char *fn) case EADDRINUSE: case EADDRNOTAVAIL: printf("\nThings to try:\n\n"); + /* NOTE: Do not reformat indentation with TABs, to keep lines aligned for consistent editing */ printf(" - ps -ef | grep '%s'\t(Linux, GNU userland)\n" " - ps -xawwu | grep '%s'\t(BSD, Solaris, embedded)\n" " To check if another copy of the driver is running; if not:\n\n", - progname, progname); + progname, progname); printf(" - ls -la %s\n To check if a (non-socket) filesystem object already exists there\n\n", fn); printf(" - rm -rf %s\n To remove any offending files (a new driver instance creates its own)\n", fn); break; @@ -2229,13 +2230,14 @@ int dstate_detect_phasecount( * tables should take care of this with converion routine and numeric * data type flags. */ #define dstate_getinfo_nonzero(var, suffix) \ - do { strncpy(bufrw_ptr, suffix, bufrw_max); \ - if ( (var = dstate_getinfo(buf)) ) { \ - if ( (var[0] == '0' && var[1] == '\0') || \ - (var[0] == '\0') ) { \ - var = NULL; \ - } \ - } \ + do { \ + strncpy(bufrw_ptr, suffix, bufrw_max); \ + if ( (var = dstate_getinfo(buf)) ) { \ + if ( (var[0] == '0' && var[1] == '\0') \ + || (var[0] == '\0') ) { \ + var = NULL; \ + } \ + } \ } while(0) dstate_getinfo_nonzero(v1, "L1.voltage"); diff --git a/drivers/eaton-pdu-marlin-mib.c b/drivers/eaton-pdu-marlin-mib.c index a8fca038cb..1129467605 100644 --- a/drivers/eaton-pdu-marlin-mib.c +++ b/drivers/eaton-pdu-marlin-mib.c @@ -1058,7 +1058,7 @@ static snmp_info_t eaton_marlin_mib[] = { ".1.3.6.1.4.1.534.6.6.7.6.2.1.3.%i.%i.2", NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET | SU_TYPE_DAISY_1, NULL), snmp_info_default("outlet.%i.groupid", ST_FLAG_STRING, SU_INFOSIZE, - ".1.3.6.1.4.1.534.6.6.7.6.2.1.3.%i.%i.3", + ".1.3.6.1.4.1.534.6.6.7.6.2.1.3.%i.%i.3", NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET | SU_TYPE_DAISY_1, NULL), snmp_info_default("outlet.%i.groupid", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.6.2.1.3.%i.%i.4", diff --git a/drivers/everups.c b/drivers/everups.c index 1401e82067..b7987790fa 100644 --- a/drivers/everups.c +++ b/drivers/everups.c @@ -162,9 +162,9 @@ void upsdrv_updateinfo(void) fVal=((double)acuV-95.0)*100.0; if (standby) - fVal/=(135.5-95.0); + fVal/=(135.5-95.0); else - fVal/=(124.5-95.0); + fVal/=(124.5-95.0); if (fVal>100) fVal=100; else if (fVal<0) diff --git a/drivers/generic_gpio_libgpiod.c b/drivers/generic_gpio_libgpiod.c index 9fe7891618..30c2dd806f 100644 --- a/drivers/generic_gpio_libgpiod.c +++ b/drivers/generic_gpio_libgpiod.c @@ -197,8 +197,9 @@ void gpio_open(struct gpioups_t *gpioupsfdlocal) { if(gpioRc) { fatal_with_errno(LOG_ERR, "Failed to set lines to GPIOD_LINE_EDGE_BOTH"); } - gpioRc = gpiod_line_config_add_line_settings(libgpiod_data->lineConfig, (unsigned int *)gpioupsfdlocal->upsLines, - gpioupsfdlocal->upsLinesCount, lineSettings); + gpioRc = gpiod_line_config_add_line_settings( + libgpiod_data->lineConfig, (unsigned int *)gpioupsfdlocal->upsLines, + gpioupsfdlocal->upsLinesCount, lineSettings); if(gpioRc) { fatalx(LOG_ERR, "Failed to attach line settings to line configuration"); } diff --git a/drivers/generic_modbus.c b/drivers/generic_modbus.c index 2f80f45695..0c7877d39a 100644 --- a/drivers/generic_modbus.c +++ b/drivers/generic_modbus.c @@ -855,7 +855,7 @@ void get_config_vars(void) /* check if OL register type is set and get the value otherwise set to INPUT_B */ if (testvar("OL_regtype")) { - sigar[OL_T].type = (regtype_t)(unsigned int)strtol(getval("OL_regtype"), NULL, 10); + sigar[OL_T].type = (regtype_t)(unsigned int)strtol(getval("OL_regtype"), NULL, 10); if (sigar[OL_T].type < COIL || sigar[OL_T].type > HOLDING) { sigar[OL_T].type = INPUT_B; } @@ -1068,7 +1068,7 @@ modbus_t *modbus_new(const char *port) upslogx(LOG_ERR, "modbus_new_rtu: Unable to open serial port context\n"); } } else if ((sp = strchr(port, ':')) != NULL) { - char *tcp_port = (char*)xmalloc(sizeof(sp)); + char *tcp_port = (char*)xmalloc(sizeof(sp)); strncpy(tcp_port, sp + 1, sizeof(sp)); *sp = '\0'; mb = modbus_new_tcp(port, (int)strtoul(tcp_port, NULL, 10)); diff --git a/drivers/genericups.c b/drivers/genericups.c index ea08728b0e..dfeb17d420 100644 --- a/drivers/genericups.c +++ b/drivers/genericups.c @@ -319,7 +319,7 @@ void upsdrv_shutdown(void) upslogx(LOG_ERR, "No upstype set - see help text / man page!"); if (handling_upsdrv_shutdown > 0) set_exit_flag(EF_EXIT_FAILURE); - return; + return; } flags = upstab[upstype].line_sd; @@ -328,7 +328,7 @@ void upsdrv_shutdown(void) upslogx(LOG_ERR, "No shutdown command defined for this model!"); if (handling_upsdrv_shutdown > 0) set_exit_flag(EF_EXIT_FAILURE); - return; + return; } if (flags == TIOCM_ST) { @@ -338,7 +338,7 @@ void upsdrv_shutdown(void) upslogx(LOG_ERR, "Need to send a BREAK, but don't have tcsendbreak!"); if (handling_upsdrv_shutdown > 0) set_exit_flag(EF_EXIT_FAILURE); - return; + return; # endif #else /* WIN32 */ NUT_WIN32_INCOMPLETE_DETAILED("Need to send a BREAK at this point, but not addressed for WIN32 yet"); @@ -365,7 +365,7 @@ void upsdrv_shutdown(void) upslog_with_errno(LOG_ERR, "ioctl TIOCMSET"); if (handling_upsdrv_shutdown > 0) set_exit_flag(EF_EXIT_FAILURE); - return; + return; } if (getval("sdtime")) { diff --git a/drivers/hpe-pdu-mib.c b/drivers/hpe-pdu-mib.c index ad2960f735..3c32676d5f 100644 --- a/drivers/hpe-pdu-mib.c +++ b/drivers/hpe-pdu-mib.c @@ -678,7 +678,7 @@ static snmp_info_t hpe_pdu_mib[] = { ".1.3.6.1.4.1.534.6.6.7.6.2.1.3.%i.%i.2", NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET | SU_TYPE_DAISY_1, NULL), snmp_info_default("outlet.%i.groupid", ST_FLAG_STRING, SU_INFOSIZE, - ".1.3.6.1.4.1.534.6.6.7.6.2.1.3.%i.%i.3", + ".1.3.6.1.4.1.534.6.6.7.6.2.1.3.%i.%i.3", NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET | SU_TYPE_DAISY_1, NULL), snmp_info_default("outlet.%i.groupid", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.6.2.1.3.%i.%i.4", diff --git a/drivers/huawei-ups2000.c b/drivers/huawei-ups2000.c index f51c8acdd5..48291ebf6e 100644 --- a/drivers/huawei-ups2000.c +++ b/drivers/huawei-ups2000.c @@ -1365,11 +1365,12 @@ static void ups2000_delay_get(void) if (cmdline) { r = ups2000_delay_set(delay->name, cmdline); if (r != STAT_SET_HANDLED) { - upslogx(LOG_ERR, "servar: %s is invalid. " - "Reverting to default %s %d seconds", - delay->varname_cmdline, - delay->varname_cmdline, - delay->dfault); + upslogx(LOG_ERR, + "servar: %s is invalid. " + "Reverting to default %s %d seconds", + delay->varname_cmdline, + delay->varname_cmdline, + delay->dfault); *delay->global_var = delay->dfault; } } @@ -1591,15 +1592,17 @@ static int ups2000_instcmd_load_on(const uint16_t reg) * normal/bypass status. Also log an error and suggest "bypass.stop". */ /* FIXME: ..._INVALID ? */ - upslogx(LOG_INSTCMD_FAILED, "load.on error: UPS is already on, and is in bypass mode. " - "To enter normal mode, use bypass.stop"); + upslogx(LOG_INSTCMD_FAILED, + "load.on error: UPS is already on, and is in bypass mode. " + "To enter normal mode, use bypass.stop"); return STAT_INSTCMD_FAILED; } else { /* unreachable, see comments for r != 0 at the beginning */ /* FIXME: ..._INVALID ? */ - upslogx(LOG_INSTCMD_FAILED, "load.on error: invalid ups.status (%s) detected. " - "Please file a bug report!", status); + upslogx(LOG_INSTCMD_FAILED, + "load.on error: invalid ups.status (%s) detected. " + "Please file a bug report!", status); return STAT_INSTCMD_FAILED; } @@ -1987,8 +1990,9 @@ static int ups2000_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *des int r = -1; if (addr < 10000) - upslogx(LOG_ERR, "Invalid register read from %04d detected. " - "Please file a bug report!", addr); + upslogx(LOG_ERR, + "Invalid register read from %04d detected. " + "Please file a bug report!", addr); for (i = 0; i < 3; i++) { /* @@ -2048,8 +2052,9 @@ static int ups2000_write_registers(modbus_t *ctx, int addr, int nb, uint16_t *sr int r = -1; if (addr < 10000) - upslogx(LOG_ERR, "Invalid register write to %04d detected. " - "Please file a bug report!", addr); + upslogx(LOG_ERR, + "Invalid register write to %04d detected. " + "Please file a bug report!", addr); for (i = 0; i < 3; i++) { r = modbus_write_registers(ctx, addr, nb, src); diff --git a/drivers/libshut.c b/drivers/libshut.c index 803727308e..84341407ed 100644 --- a/drivers/libshut.c +++ b/drivers/libshut.c @@ -373,7 +373,7 @@ static int libshut_open( SHUTDevice_t *curDevice, char *arg_device_path, int (*callback)(usb_dev_handle arg_upsfd, SHUTDevice_t *hd, - usb_ctrl_charbuf rdbuf, usb_ctrl_charbufsize rdlen)) + usb_ctrl_charbuf rdbuf, usb_ctrl_charbufsize rdlen)) { int ret, res; usb_ctrl_char buf[20] __attribute__((aligned(4))); @@ -478,7 +478,7 @@ static int libshut_open( if (res < 9) { upsdebugx(2, "DEVICE descriptor too short (expected %d, got %d)", - USB_DT_DEVICE_SIZE, res); + USB_DT_DEVICE_SIZE, res); return -1; } @@ -725,9 +725,9 @@ static int libshut_get_report( return shut_control_msg(arg_upsfd, REQUEST_TYPE_GET_REPORT, /* == USB_ENDPOINT_IN + USB_TYPE_CLASS + USB_RECIP_INTERFACE, */ - 0x01, - ReportId+(0x03<<8), /* HID_REPORT_TYPE_FEATURE */ - 0, raw_buf, ReportSize, SHUT_TIMEOUT); + 0x01, + ReportId+(0x03<<8), /* HID_REPORT_TYPE_FEATURE */ + 0, raw_buf, ReportSize, SHUT_TIMEOUT); } /* return ReportSize upon success ; -1 otherwise */ @@ -1156,8 +1156,15 @@ static int shut_get_descriptor( "entering shut_get_descriptor(n %02x, %" PRI_NUT_USB_CTRL_CHARBUFSIZE ")", type, size); - return shut_control_msg(arg_upsfd, USB_ENDPOINT_IN+(type>=USB_DT_HID?1:0), - USB_REQ_GET_DESCRIPTOR, (type << 8) + index, 0, (usb_ctrl_charbuf)buf, size, SHUT_TIMEOUT); + return shut_control_msg( + arg_upsfd, + USB_ENDPOINT_IN+(type>=USB_DT_HID?1:0), + USB_REQ_GET_DESCRIPTOR, + (type << 8) + index, + 0, + (usb_ctrl_charbuf)buf, + size, + SHUT_TIMEOUT); } /* Take care of a SHUT transfer (sending and receiving data) */ diff --git a/drivers/macosx-ups.c b/drivers/macosx-ups.c index 0f03fd0b82..db994a933a 100644 --- a/drivers/macosx-ups.c +++ b/drivers/macosx-ups.c @@ -327,7 +327,7 @@ static int setvar(const char *varname, const char *val) { upsdebug_SET_STARTING(varname, val); - if (!strcasecmp(varname, "ups.test.interval")) { + if (!strcasecmp(varname, "ups.test.interval")) { ser_send_buf(upsfd, ...); return STAT_SET_HANDLED; } diff --git a/drivers/mge-utalk.c b/drivers/mge-utalk.c index d192cff8d4..a69c260e20 100644 --- a/drivers/mge-utalk.c +++ b/drivers/mge-utalk.c @@ -129,8 +129,9 @@ static int instcmd(const char *cmdname, const char *extra); static int setvar(const char *varname, const char *val); static void enable_ups_comm(void); static void disable_ups_comm(void); -static void extract_info(const char *buf, const mge_info_item_t *mge, - char *infostr, size_t infolen); +static void extract_info( + const char *buf, const mge_info_item_t *mge, + char *infostr, size_t infolen); static const char *info_variable_cmd(const char *type); static bool_t info_variable_ok(const char *type); static int get_ups_status(void); @@ -259,7 +260,7 @@ void upsdrv_initinfo(void) /* loop until we have at status */ tries = 0; do { - printf("."); + printf("."); /* get model information in ASCII string form: */ bytes_rcvd = mge_command(buf, sizeof(buf), "Si 1"); @@ -289,45 +290,44 @@ void upsdrv_initinfo(void) } } else - { + { upsdebugx(1, "initinfo: 'Si 1' unavailable, switching to 'Si' command"); /* get model information, numbered form, : */ bytes_rcvd = mge_command(buf, sizeof(buf), "Si"); - if(bytes_rcvd > 0 && buf[0] != '?') { - upsdebugx(1, "initinfo: Si == >%s<", buf); + if (bytes_rcvd > 0 && buf[0] != '?') { + upsdebugx(1, "initinfo: Si == >%s<", buf); - printf("\nCAUTION : This is an older model. It may not support too much polling.\nPlease read man mge-utalk and use pollinterval\n"); + printf("\nCAUTION : This is an older model. It may not support too much polling.\nPlease read man mge-utalk and use pollinterval\n"); - p = strchr(buf, ' '); + p = strchr(buf, ' '); - if ( p != NULL ) { - *p = '\0'; - si_data1 = atoi(buf); - v = p+1; - p = strchr(v, ' '); - } + if ( p != NULL ) { + *p = '\0'; + si_data1 = atoi(buf); + v = p+1; + p = strchr(v, ' '); + } - if ( p != NULL ) { - *p = '\0'; - si_data2 = atoi(v); - } + if ( p != NULL ) { + *p = '\0'; + si_data2 = atoi(v); + } /* Parsing legacy model table in order to find it */ for ( legacy_model = mge_model ; legacy_model->name != NULL ; legacy_model++ ) { - if(legacy_model->Data1 == si_data1 && legacy_model->Data2 == si_data2){ + if (legacy_model->Data1 == si_data1 && legacy_model->Data2 == si_data2) { model = legacy_model->name; upsdebugx(1, "initinfo: UPS model == >%s<", model); break; + } } - } - - if( model == NULL ) - printf("No model found by that model and version ID\nPlease contact us with UPS model, name and reminder info\nReminder info : Data1=%i , Data2=%i\n", si_data1, si_data2); + if (model == NULL) + printf("No model found by that model and version ID\nPlease contact us with UPS model, name and reminder info\nReminder info : Data1=%i , Data2=%i\n", si_data1, si_data2); } - } + } if ( model ) { upsdebugx(2, "Got model name: %s", model); @@ -465,10 +465,10 @@ void upsdrv_updateinfo(void) dstate_dataok(); } else { - upslogx(LOG_NOTICE, "updateinfo: Cannot update %s", item->type); - /* try to re enable communication */ - disable_ups_comm(); - enable_ups_comm(); + upslogx(LOG_NOTICE, "updateinfo: Cannot update %s", item->type); + /* try to re-enable communication */ + disable_ups_comm(); + enable_ups_comm(); } } /* if item->ok */ } @@ -750,8 +750,9 @@ static void enable_ups_comm(void) NOTE: buf="?" must be handled before calling extract_info buf is changed inspite of const !!!!! */ -static void extract_info(const char *buf, const mge_info_item_t *item, - char *infostr, size_t infolen) +static void extract_info( + const char *buf, const mge_info_item_t *item, + char *infostr, size_t infolen) { /* initialize info string */ infostr[0] = '\0'; diff --git a/drivers/microdowell.c b/drivers/microdowell.c index 62d020ca7d..efb092368f 100644 --- a/drivers/microdowell.c +++ b/drivers/microdowell.c @@ -908,7 +908,7 @@ void upsdrv_initinfo(void) if (detect_hardware() == -1) { fatalx(EXIT_FAILURE, - "Unable to detect a Microdowell's Enterprise UPS on port %s\nCheck the cable, port name and try again", device_path); + "Unable to detect a Microdowell's Enterprise UPS on port %s\nCheck the cable, port name and try again", device_path); } /* I set the corresponding UPS variables diff --git a/drivers/microsol-apc.h b/drivers/microsol-apc.h index 6f38d28b77..9390a773d7 100644 --- a/drivers/microsol-apc.h +++ b/drivers/microsol-apc.h @@ -29,18 +29,18 @@ /* Supported UPS models */ static const unsigned int MODELS[MODEL_COUNT] = { - 183 /* APC Back-UPS BZ2200I-BR */ , - 190 /* APC Back-UPS BZ1500-BR */ , - 191 /* APC Back-UPS BZ2200BI-BR */ + 183 /* APC Back-UPS BZ2200I-BR */ , + 190 /* APC Back-UPS BZ1500-BR */ , + 191 /* APC Back-UPS BZ2200BI-BR */ }; /* Note: int type here is aligned with the "nominal_power" * variable in microsol-common.h and many related drivers. */ static const int NOMINAL_POWER[MODEL_COUNT] = { - 2200 /* Model 183 */ , - 1500 /* Model 190 */ , - 2200 /* Model 191 */ + 2200 /* Model 183 */ , + 1500 /* Model 190 */ , + 2200 /* Model 191 */ }; /* Curves for output voltage (depends on relay state and battery state) @@ -50,32 +50,32 @@ static const int NOMINAL_POWER[MODEL_COUNT] = { /* For on-line UPS */ static const float OUTPUT_VOLTAGE_MULTIPLIER_A[MODEL_COUNT][2][8] = { { - { 1.831, 1.831, 1.831, 1.831, 1.831, 1.831, 1.831, 1.831}, - { 0.1566, 0.1566, 0.1566, 0.1566, 0.1566, 0.1566, 0.1566, 0.1566} - } /* Model 183 */ , + { 1.831, 1.831, 1.831, 1.831, 1.831, 1.831, 1.831, 1.831}, + { 0.1566, 0.1566, 0.1566, 0.1566, 0.1566, 0.1566, 0.1566, 0.1566} + } /* Model 183 */ , { - { 0.9266, 0.9266, 0.9266, 0.9266, 0.9266, 0.9266, 0.9266, 0.9266}, - { 5.59, 9.47, 13.7, 0.0, 0.0, 0.0, 0.0, 0.0} - } /* Model 190 */ , + { 0.9266, 0.9266, 0.9266, 0.9266, 0.9266, 0.9266, 0.9266, 0.9266}, + { 5.59, 9.47, 13.7, 0.0, 0.0, 0.0, 0.0, 0.0} + } /* Model 190 */ , { - { 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00}, - { 1.26, 1.26, 1.26, 1.26, 1.26, 1.26, 1.26, 1.26} - } /* Model 191 */ + { 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00}, + { 1.26, 1.26, 1.26, 1.26, 1.26, 1.26, 1.26, 1.26} + } /* Model 191 */ }; static const float OUTPUT_VOLTAGE_MULTIPLIER_B[MODEL_COUNT][2][8] = { { - { -2.1374, -2.1374, -2.1374, -2.1374, -2.1374, -2.1374, -2.1374, -2.1374}, - { 204.93, 204.93, 204.93, 204.93, 204.93, 204.93, 204.93, 204.93} - } /* Model 183 */ , + { -2.1374, -2.1374, -2.1374, -2.1374, -2.1374, -2.1374, -2.1374, -2.1374}, + { 204.93, 204.93, 204.93, 204.93, 204.93, 204.93, 204.93, 204.93} + } /* Model 183 */ , { - { 5.0694, 5.0694, 5.0694, 5.0694, 5.0694, 5.0694, 5.0694, 5.0694}, - { 5.4, 6.5, 17.6, 0.0, 0.0, 0.0, 0.0, 0.0} - } /* Model 190 */ , + { 5.0694, 5.0694, 5.0694, 5.0694, 5.0694, 5.0694, 5.0694, 5.0694}, + { 5.4, 6.5, 17.6, 0.0, 0.0, 0.0, 0.0, 0.0} + } /* Model 190 */ , { - { 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0}, - { -5.91, -5.91, -5.91, -5.91, -5.91, -5.91, -5.91, -5.91} - } /* Model 191 */ + { 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0}, + { -5.91, -5.91, -5.91, -5.91, -5.91, -5.91, -5.91, -5.91} + } /* Model 191 */ }; /* Curves for output current @@ -83,130 +83,136 @@ static const float OUTPUT_VOLTAGE_MULTIPLIER_B[MODEL_COUNT][2][8] = { */ static const float OUTPUT_CURRENT_MULTIPLIER_A[MODEL_COUNT][2] = { { - 0.0892999991774559, - 0.09070000052452087 } /* Model 183 */ , + 0.0892999991774559, + 0.09070000052452087 + } /* Model 183 */ , { - 0.1264, - 0.1303 } /* Model 190 */ , + 0.1264, + 0.1303 + } /* Model 190 */ , { - 0.13819999992847443, - 0.08959999680519104 } /* Model 191 */ , + 0.13819999992847443, + 0.08959999680519104 + } /* Model 191 */ , }; static const float OUTPUT_CURRENT_MULTIPLIER_B[MODEL_COUNT][2] = { { - 0.09350000321865082, - 0.14550000429153442 } /* Model 183 */ , + 0.09350000321865082, + 0.14550000429153442 + } /* Model 183 */ , { - 0.522, - 0.468 } /* Model 190 */ , + 0.522, + 0.468 + } /* Model 190 */ , { - 0.12999999523162842, - 0.1881999969482422 } /* Model 191 */ + 0.12999999523162842, + 0.1881999969482422 + } /* Model 191 */ }; /* Curves for input voltage (depends on nominal output voltage) * Second index: Nominal output voltage = 220V (1) or 115V (0). */ static const float INPUT_VOLTAGE_MULTIPLIER_A[MODEL_COUNT][2] = { - { 1.7937, 1.7937 } /* Model 183 */ , - { 1.8, 1.8 } /* Model 190 */ , + { 1.7937, 1.7937 } /* Model 183 */ , + { 1.8, 1.8 } /* Model 190 */ , { 1.4825, 1.4952 } /* Model 191 */ }; static const float INPUT_VOLTAGE_MULTIPLIER_B[MODEL_COUNT][2] = { - { 1.854, 1.854 } /* Model 183 */ , - { 2.224, 2.224 } /* Model 190 */ , + { 1.854, 1.854 } /* Model 183 */ , + { 2.224, 2.224 } /* Model 190 */ , { 0.0853, -2.4241 } /* Model 191 */ }; /* Curves for battery voltage */ static const float BATTERY_VOLTAGE_MULTIPLIER_A[MODEL_COUNT] = { - 0.1551 /* Model 183 */ , - 0.1513 /* Model 190 */ , - 0.1543 /* Model 191 */ + 0.1551 /* Model 183 */ , + 0.1513 /* Model 190 */ , + 0.1543 /* Model 191 */ }; static const float BATTERY_VOLTAGE_MULTIPLIER_B[MODEL_COUNT] = { - 0.0654 /* Model 183 */ , - 0.7153 /* Model 190 */ , - 0.1414 /* Model 191 */ + 0.0654 /* Model 183 */ , + 0.7153 /* Model 190 */ , + 0.1414 /* Model 191 */ }; /* Real power estimation curves (depends on relay state) */ /* * Remarks: - * - Model 190 use a direct real power determination (no need for curve selectors) + * - Model 190 uses a direct real power determination (no need for curve selectors) */ static const float REAL_POWER_CURVE_SELECTOR_A1[MODEL_COUNT][8] = { - { 0.24, 0.26, 0.0, 0.0, 0.24, 0.26, 0.0, 0.28 } /* Model 183 */ , - { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 } /* Model 190 */ , + { 0.24, 0.26, 0.0, 0.0, 0.24, 0.26, 0.0, 0.28 } /* Model 183 */ , + { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 } /* Model 190 */ , { 0.24, 0.26, 0.0, 0.0, 0.24, 0.26, 0.0, 0.28 } /* Model 191 */ }; static const float REAL_POWER_CURVE_SELECTOR_B1[MODEL_COUNT][8] = { - { 83.15, 81.23, 0.0, 0.0, 83.49, 79.05, 0.0, 85.67 } /* Model 183 */ , - { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 } /* Model 190 */ , + { 83.15, 81.23, 0.0, 0.0, 83.49, 79.05, 0.0, 85.67 } /* Model 183 */ , + { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 } /* Model 190 */ , { 83.15, 81.23, 0.0, 0.0, 83.49, 79.05, 0.0, 85.67 } /* Model 191 */ }; static const float REAL_POWER_CURVE_SELECTOR_A2[MODEL_COUNT][8] = { - { 0.0763, 0.081, 0.0919, 0.0, 0.0741, 0.0828, 0.0, 0.0938 } /* Model 183 */ , - { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 } /* Model 190 */ , + { 0.0763, 0.081, 0.0919, 0.0, 0.0741, 0.0828, 0.0, 0.0938 } /* Model 183 */ , + { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 } /* Model 190 */ , { 0.0763, 0.081, 0.0919, 0.0, 0.0741, 0.0828, 0.0, 0.0938 } /* Model 191 */ }; static const float REAL_POWER_CURVE_SELECTOR_B2[MODEL_COUNT][8] = { - { 81.732, 94.459, 86.686, 0.0, 84.657, 84.999, 0.0, 78.097 } /* Model 183 */ , - { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 } /* Model 190 */ , + { 81.732, 94.459, 86.686, 0.0, 84.657, 84.999, 0.0, 78.097 } /* Model 183 */ , + { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 } /* Model 190 */ , { 81.732, 94.459, 86.686, 0.0, 84.657, 84.999, 0.0, 78.097 } /* Model 191 */ }; static const float REAL_POWER_CURVE_SELECTOR_A3[MODEL_COUNT][8] = { - { 0.0744, 0.0808, 0.0885, 0.0, 0.0732, 0.084, 0.0, 0.0955 } /* Model 183 */ , - { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 } /* Model 190 */ , + { 0.0744, 0.0808, 0.0885, 0.0, 0.0732, 0.084, 0.0, 0.0955 } /* Model 183 */ , + { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 } /* Model 190 */ , { 0.0744, 0.0808, 0.0885, 0.0, 0.0732, 0.084, 0.0, 0.0955 } /* Model 191 */ }; static const float REAL_POWER_CURVE_SELECTOR_B3[MODEL_COUNT][8] = { - { 122.06, 122.9, 125.75, 0.0, 120.39, 108.52, 0.0, 92.239 } /* Model 183 */ , - { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 } /* Model 190 */ , + { 122.06, 122.9, 125.75, 0.0, 120.39, 108.52, 0.0, 92.239 } /* Model 183 */ , + { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 } /* Model 190 */ , { 122.06, 122.9, 125.75, 0.0, 120.39, 108.52, 0.0, 92.239 } /* Model 191 */ }; static const float REAL_POWER_MULTIPLIER_A1[MODEL_COUNT][8] = { - { 0.08040007075206226, 0.0894, 0.0999, 0.0, 0.0813, 0.0905, 0.0, 0.1005 } /* Model 183 */ , - { 0.1127, 0.1127, 0.1127, 0.1127, 0.1127, 0.1127, 0.1127, 0.1127 } /* Model 190 */ , + { 0.08040007075206226, 0.0894, 0.0999, 0.0, 0.0813, 0.0905, 0.0, 0.1005 } /* Model 183 */ , + { 0.1127, 0.1127, 0.1127, 0.1127, 0.1127, 0.1127, 0.1127, 0.1127 } /* Model 190 */ , { 0.08040007075206226, 0.0894, 0.0999, 0.0, 0.0813, 0.0905, 0.0, 0.1005 } /* Model 191 */ }; static const float REAL_POWER_MULTIPLIER_B1[MODEL_COUNT][8] = { - { 45.292, 41.928, 41.727, 0.0, 40.269, 41.81, 0.0, 43.458 } /* Model 183 */ , - { 50.031, 50.031, 50.031, 50.031, 50.031, 50.031, 50.031, 50.031 } /* Model 190 */ , + { 45.292, 41.928, 41.727, 0.0, 40.269, 41.81, 0.0, 43.458 } /* Model 183 */ , + { 50.031, 50.031, 50.031, 50.031, 50.031, 50.031, 50.031, 50.031 } /* Model 190 */ , { 45.292, 41.928, 41.727, 0.0, 40.269, 41.81, 0.0, 43.458 } /* Model 191 */ }; static const float REAL_POWER_MULTIPLIER_A2[MODEL_COUNT][8] = { - { 0.08630063689870031, 0.0946, 0.1068, 0.0, 0.086, 0.0967, 0.0, 0.1088 } /* Model 183 */ , - { 0.1127, 0.1127, 0.1127, 0.1127, 0.1127, 0.1127, 0.1127, 0.1127 } /* Model 190 */ , + { 0.08630063689870031, 0.0946, 0.1068, 0.0, 0.086, 0.0967, 0.0, 0.1088 } /* Model 183 */ , + { 0.1127, 0.1127, 0.1127, 0.1127, 0.1127, 0.1127, 0.1127, 0.1127 } /* Model 190 */ , { 0.08630063689870031, 0.0946, 0.1068, 0.0, 0.086, 0.0967, 0.0, 0.1088 } /* Model 191 */ }; static const float REAL_POWER_MULTIPLIER_B2[MODEL_COUNT][8] = { - { 8.3927, 9.2393, 8.2852, 0.0, 8.301, 6.7636, 0.0, 8.2842 } /* Model 183 */ , - { 50.031, 50.031, 50.031, 50.031, 50.031, 50.031, 50.031, 50.031 } /* Model 190 */ , + { 8.3927, 9.2393, 8.2852, 0.0, 8.301, 6.7636, 0.0, 8.2842 } /* Model 183 */ , + { 50.031, 50.031, 50.031, 50.031, 50.031, 50.031, 50.031, 50.031 } /* Model 190 */ , { 8.3927, 9.2393, 8.2852, 0.0, 8.301, 6.7636, 0.0, 8.2842 } /* Model 191 */ }; static const float REAL_POWER_MULTIPLIER_A3[MODEL_COUNT][8] = { - { 0.0896001146881468, 0.0991, 0.1116, 0.0, 0.0967, 0.1068, 0.0, 0.1169 } /* Model 183 */ , - { 0.1127, 0.1127, 0.1127, 0.1127, 0.1127, 0.1127, 0.1127, 0.1127 } /* Model 190 */ , + { 0.0896001146881468, 0.0991, 0.1116, 0.0, 0.0967, 0.1068, 0.0, 0.1169 } /* Model 183 */ , + { 0.1127, 0.1127, 0.1127, 0.1127, 0.1127, 0.1127, 0.1127, 0.1127 } /* Model 190 */ , { 0.0896001146881468, 0.0991, 0.1116, 0.0, 0.0967, 0.1068, 0.0, 0.1169 } /* Model 191 */ }; static const float REAL_POWER_MULTIPLIER_B3[MODEL_COUNT][8] = { - { -31.115, -33.777, -33.826, 0.0, -59.513, -57.729, 0.0, -41.333 } /* Model 183 */ , - { 50.031, 50.031, 50.031, 50.031, 50.031, 50.031, 50.031, 50.031 } /* Model 190 */ , + { -31.115, -33.777, -33.826, 0.0, -59.513, -57.729, 0.0, -41.333 } /* Model 183 */ , + { 50.031, 50.031, 50.031, 50.031, 50.031, 50.031, 50.031, 50.031 } /* Model 190 */ , { -31.115, -33.777, -33.826, 0.0, -59.513, -57.729, 0.0, -41.333 } /* Model 191 */ }; @@ -215,16 +221,16 @@ static const float REAL_POWER_MULTIPLIER_B3[MODEL_COUNT][8] = { * Second index: Recharging battery flag: charging (1) or charged/discharging (0) */ static const float MAX_BATTERY_VOLTAGE[MODEL_COUNT][2] = { - { 27.0, 29.5 } /* Model 183 */ , - { 27.0, 29.5 } /* Model 190 */ , + { 27.0, 29.5 } /* Model 183 */ , + { 27.0, 29.5 } /* Model 190 */ , { 27.0, 29.5 } /* Model 191 */ }; /** Minimum battery voltage, used to estimate battery charge */ static const float MIN_BATTERY_VOLTAGE[MODEL_COUNT] = { - 20 /* Model 183 */ , - 20 /* Model 190 */ , - 20 /* Model 191 */ + 20 /* Model 183 */ , + 20 /* Model 190 */ , + 20 /* Model 191 */ }; -#endif /* INCLUDED_MICROSOL_APC_H */ +#endif /* INCLUDED_MICROSOL_APC_H */ diff --git a/drivers/nut-ipmipsu.c b/drivers/nut-ipmipsu.c index 6906c7ed02..477c6271f4 100644 --- a/drivers/nut-ipmipsu.c +++ b/drivers/nut-ipmipsu.c @@ -190,7 +190,7 @@ static int setvar(const char *varname, const char *val) { upsdebug_SET_STARTING(varname, val); - if (!strcasecmp(varname, "ups.test.interval")) { + if (!strcasecmp(varname, "ups.test.interval")) { ser_send_buf(upsfd, ...); return STAT_SET_HANDLED; } diff --git a/drivers/nut-libfreeipmi.c b/drivers/nut-libfreeipmi.c index 53eebf86a7..e136d026fb 100644 --- a/drivers/nut-libfreeipmi.c +++ b/drivers/nut-libfreeipmi.c @@ -637,15 +637,16 @@ static int libfreeipmi_get_sensors_info (IPMIDevice_t *ipmi_dev) if (ipmi_sdr_ctx_errnum (sdr_ctx) == IPMI_SDR_ERR_CACHE_READ_CACHE_DOES_NOT_EXIST) { - if (ipmi_sdr_cache_create (sdr_ctx, - ipmi_ctx, CACHE_LOCATION, - NUT_IPMI_SDR_CACHE_DEFAULTS, - NULL, NULL) < 0) + if (ipmi_sdr_cache_create ( + sdr_ctx, ipmi_ctx, CACHE_LOCATION, + NUT_IPMI_SDR_CACHE_DEFAULTS, + NULL, NULL) < 0) { libfreeipmi_cleanup(); fatal_with_errno(EXIT_FAILURE, "ipmi_sdr_cache_create: %s", ipmi_sdr_ctx_errormsg (sdr_ctx)); } + if (ipmi_sdr_cache_open (sdr_ctx, ipmi_ctx, CACHE_LOCATION) < 0) { if (ipmi_sdr_ctx_errnum (sdr_ctx) != IPMI_SDR_ERR_CACHE_READ_CACHE_DOES_NOT_EXIST) diff --git a/drivers/nut-upower.c b/drivers/nut-upower.c index 7ac799338f..84a1ac0a0e 100644 --- a/drivers/nut-upower.c +++ b/drivers/nut-upower.c @@ -117,12 +117,12 @@ static int find_ups_device(void) /* Check if we are looking for a specific path */ if (device_path && strcmp(device_path, "auto") != 0 && *device_path != '\0') { - if (strstr(obj_path, device_path)) { - upsdebugx(1, "Match found for specific path '%s': %s", device_path, obj_path); - ups_object_path = strdup(obj_path); - found = 1; - break; - } + if (strstr(obj_path, device_path)) { + upsdebugx(1, "Match found for specific path '%s': %s", device_path, obj_path); + ups_object_path = strdup(obj_path); + found = 1; + break; + } } else { /* Auto-detection: Check for substring "ups_" */ if (strstr(obj_path, "ups_")) { diff --git a/drivers/nutdrv_hashx.c b/drivers/nutdrv_hashx.c index 41a4fd68bb..ff6f7f81b5 100644 --- a/drivers/nutdrv_hashx.c +++ b/drivers/nutdrv_hashx.c @@ -139,8 +139,9 @@ static ssize_t hashx_recv(char *buf, size_t bufsize) { ssize_t nread; - nread = ser_get_line(upsfd, buf, bufsize - 1, ENDCHAR, IGNCHAR, - SER_WAIT_SEC, SER_WAIT_USEC); + nread = ser_get_line( + upsfd, buf, bufsize - 1, ENDCHAR, IGNCHAR, + SER_WAIT_SEC, SER_WAIT_USEC); assert(nread < (ssize_t) bufsize); buf[nread] = '\0'; @@ -149,8 +150,10 @@ static ssize_t hashx_recv(char *buf, size_t bufsize) char base_msg[128]; int n; - n = snprintf(base_msg, sizeof(base_msg), - "%s: read %" PRIiSIZE ": ", __func__, nread); + n = snprintf( + base_msg, sizeof(base_msg), + "%s: read %" PRIiSIZE ": ", + __func__, nread); assert(n > 0); upsdebug_ascii(4, base_msg, buf, nread); } @@ -188,14 +191,16 @@ static int hashx_send_command(const char *command) int status; if ((transferred = ser_send(upsfd, "%s%c", command, ENDCHAR)) != strlen (command) + 1) { - upslogx(LOG_ERR, "%s: Failed to send command: %s", - __func__, command); + upslogx(LOG_ERR, + "%s: Failed to send command: %s", + __func__, command); return STATUS_UNKNOWN_FAILURE; } if ((status = hashx_status_value(buf, sizeof(buf))) != STATUS_SUCCESS) { - upslogx(LOG_ERR, "%s: unexpected hash protocol response: %s (status %d)", - __func__, buf, status); + upslogx(LOG_ERR, + "%s: unexpected hash protocol response: %s (status %d)", + __func__, buf, status); } return status; @@ -256,8 +261,9 @@ void upsdrv_initinfo(void) for (i = 0; ; ++i) { upsdebugx(4, "Checking if device supports the #-protocol... [%" PRIuSIZE "]", i+1); if ((transferred = ser_send_char(upsfd, ENDCHAR)) != 1) { - fatalx(EXIT_FAILURE, "%s: Initialization failure %s", - __func__, device_path); + fatalx(EXIT_FAILURE, + "%s: Initialization failure %s", + __func__, device_path); } if ((status = hashx_status_value(buf, sizeof(buf))) == -1) { break; @@ -267,8 +273,9 @@ void upsdrv_initinfo(void) continue; } - fatalx(EXIT_FAILURE, "%s: unexpected hash protocol response: %s (status %d)", - __func__, buf, status); + fatalx(EXIT_FAILURE, + "%s: unexpected hash protocol response: %s (status %d)", + __func__, buf, status); } /* The K19 function needs a 16 bytes value and the device should reply @@ -277,8 +284,9 @@ void upsdrv_initinfo(void) * send one value we know about, to verify the protocol. */ if ((status = hashx_send_command(COMMAND_SET_SESSION_ID":"SESSION_ID)) != STATUS_SUCCESS) { - fatalx(EXIT_FAILURE, "%s: Failed to set session ID: %s", - __func__, SESSION_ID); + fatalx(EXIT_FAILURE, + "%s: Failed to set session ID: %s", + __func__, SESSION_ID); } if ((transferred = ser_send(upsfd, COMMAND_GET_SESSION_HASH"%c", ENDCHAR)) != 4) { @@ -316,8 +324,9 @@ void upsdrv_initinfo(void) fatalx(EXIT_FAILURE, "%s: Failed to get UPS info", __func__); } if ((transferred = hashx_recv(buf, sizeof(buf))) < 3) { - fatalx(EXIT_FAILURE, "%s: unexpected UPS info response: %s", - __func__, buf); + fatalx(EXIT_FAILURE, + "%s: unexpected UPS info response: %s", + __func__, buf); } /* This is in the format: * #1200,PE02022.002,000000000000,000000000000000000 @@ -364,8 +373,9 @@ void upsdrv_initinfo(void) upslogx(LOG_ERR, "%s: Failed to get UPS power info", __func__); } if ((transferred = hashx_recv(buf, sizeof(buf))) < 3) { - upslogx(LOG_ERR, "%s: unexpected UPS power info response: %s", - __func__, buf); + upslogx(LOG_ERR, + "%s: unexpected UPS power info response: %s", + __func__, buf); } /* This is in the format: * #1200,0720,230,40,70,05.20 @@ -398,9 +408,10 @@ void upsdrv_initinfo(void) } if (strsep(&reply, ",") != NULL) { - upslogx(LOG_WARNING, "This UPS returns unexpected power info fields (%s), " - "previously decoded values may have not been correctly assigned!", - buf + 1); + upslogx(LOG_WARNING, + "This UPS returns unexpected power info fields (%s), " + "previously decoded values may have not been correctly assigned!", + buf + 1); } upsh.instcmd = hashx_instcmd; @@ -452,22 +463,24 @@ void upsdrv_updateinfo(void) * S) UPS Status bytes (see below) */ status = buf + 1; - if ((ret = sscanf(status, "I%fO%fL%dB%dV%fF%fH%fR%dS", - &input_voltage, &output_voltage, &output_load, - &battery_charge, &battery_voltage, &input_frequency, - &output_frequency, &remaining_runtime)) == EOF || - ret < 1) { + if ((ret = sscanf( + status, "I%fO%fL%dB%dV%fF%fH%fR%dS", + &input_voltage, &output_voltage, &output_load, + &battery_charge, &battery_voltage, &input_frequency, + &output_frequency, &remaining_runtime)) == EOF || + ret < 1 + ) { upslogx(LOG_ERR, "%s: Impossible to parse: %s", __func__, status); dstate_datastale(); return; } upsdebugx(6, "Poll: input voltage %.1f, output voltage %.1f, load balance %d%%, " - "battery level: %d%%, battery voltage: %.1f, input frequency: %.1f, " - "output frequency %.1f, remaining runtime: %d minutes", - input_voltage, output_voltage, output_load, - battery_charge, battery_voltage, input_frequency, - output_frequency, remaining_runtime); + "battery level: %d%%, battery voltage: %.1f, input frequency: %.1f, " + "output frequency %.1f, remaining runtime: %d minutes", + input_voltage, output_voltage, output_load, + battery_charge, battery_voltage, input_frequency, + output_frequency, remaining_runtime); if (input_voltage >= 0) { dstate_setinfo("input.voltage", "%.1f", input_voltage); @@ -512,7 +525,7 @@ void upsdrv_updateinfo(void) if (!status_bytes || status_bytes_size < 5) { upslogx(LOG_ERR, "Status bytes are not enough: %" PRIuSIZE, - status_bytes_size); + status_bytes_size); dstate_dataok(); return; } @@ -623,7 +636,7 @@ static int hashx_instcmd(const char *cmd_name, const char *extra) return STAT_INSTCMD_HANDLED; upslogx(LOG_INSTCMD_FAILED, "Failed to execute command [%s] [%s]: %d", - NUT_STRARG(cmd_name), NUT_STRARG(extra), status); + NUT_STRARG(cmd_name), NUT_STRARG(extra), status); return STAT_INSTCMD_FAILED; } diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index 06588bb08f..66e521e6d0 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -3326,7 +3326,7 @@ void upsdrv_makevartable(void) snprintf(temp, sizeof(temp), "Set polling frequency, in seconds, to reduce data flow (default=%d)", - DEFAULT_POLLFREQ); + DEFAULT_POLLFREQ); addvar(VAR_VALUE, QX_VAR_POLLFREQ, temp); addvar(VAR_VALUE, "protocol", @@ -3733,7 +3733,7 @@ void upsdrv_initups(void) default: fatalx(EXIT_FAILURE, "Invalid regular expression: %s", - regex_array[ret]); + regex_array[ret]); } /* Link the matchers */ diff --git a/drivers/optiups.c b/drivers/optiups.c index 6a57ad04c8..4625b8aa6b 100644 --- a/drivers/optiups.c +++ b/drivers/optiups.c @@ -134,8 +134,8 @@ static ezfill_t opti_pollv_zinto[] = { * test with a PS-1440RM at 230V the change is only applied to PowerSeries models. */ static ezfill_t opti_pollv_ps[] = { - { "OL", "ups.load", 1.0 }, - { "FF", "input.frequency", 0.1 }, + { "OL", "ups.load", 1.0 }, + { "FF", "input.frequency", 0.1 }, { "BT", "ups.temperature", 0 }, }; diff --git a/drivers/pijuice.c b/drivers/pijuice.c index 21af182b1d..e44f58fa81 100644 --- a/drivers/pijuice.c +++ b/drivers/pijuice.c @@ -84,11 +84,14 @@ static inline __s32 i2c_smbus_read_byte_data(int file, __u8 command) union i2c_smbus_data data; int err; - if ((err = i2c_smbus_access(file, I2C_SMBUS_READ, command, - I2C_SMBUS_BYTE_DATA, &data)) < 0) + if ((err = i2c_smbus_access( + file, I2C_SMBUS_READ, command, + I2C_SMBUS_BYTE_DATA, &data)) < 0 + ) { return err; - else + } else { return 0x0FF & data.byte; + } } # endif @@ -99,11 +102,14 @@ static inline __s32 i2c_smbus_write_byte_data(int file, __u8 command, __u8 value int err; data.byte = value; - if ((err = i2c_smbus_access(file, I2C_SMBUS_WRITE, command, - I2C_SMBUS_BYTE_DATA, &data)) < 0) + if ((err = i2c_smbus_access( + file, I2C_SMBUS_WRITE, command, + I2C_SMBUS_BYTE_DATA, &data)) < 0 + ) { return err; - else + } else { return 0x0FF & data.byte; + } } # endif @@ -113,11 +119,14 @@ static inline __s32 i2c_smbus_read_word_data(int file, __u8 command) union i2c_smbus_data data; int err; - if ((err = i2c_smbus_access(file, I2C_SMBUS_READ, command, - I2C_SMBUS_WORD_DATA, &data)) < 0) + if ((err = i2c_smbus_access( + file, I2C_SMBUS_READ, command, + I2C_SMBUS_WORD_DATA, &data)) < 0 + ) { return err; - else + } else { return 0x0FFFF & data.word; + } } # endif @@ -128,11 +137,14 @@ static inline __s32 i2c_smbus_write_word_data(int file, __u8 command, __u16 valu int err; data.word = value; - if ((err = i2c_smbus_access(file, I2C_SMBUS_WRITE, command, - I2C_SMBUS_WORD_DATA, &data)) < 0) + if ((err = i2c_smbus_access( + file, I2C_SMBUS_WRITE, command, + I2C_SMBUS_WORD_DATA, &data)) < 0 + ) { return err; - else + } else { return 0x0FFFF & data.word; + } } # endif @@ -150,11 +162,14 @@ static inline __u8* i2c_smbus_read_i2c_block_data(int file, __u8 command, __u8 l data.block[0] = length; memcpy(data.block + 1, values, length); - if ((err = i2c_smbus_access(file, I2C_SMBUS_READ, command, - I2C_SMBUS_I2C_BLOCK_DATA, &data)) < 0) + if ((err = i2c_smbus_access( + file, I2C_SMBUS_READ, command, + I2C_SMBUS_I2C_BLOCK_DATA, &data)) < 0 + ) { return NULL; - else + } else { memcpy(values, &data.block[1], data.block[0]); + } return values; } diff --git a/drivers/powercom.c b/drivers/powercom.c index 671ca2d630..11743dbf47 100644 --- a/drivers/powercom.c +++ b/drivers/powercom.c @@ -595,13 +595,13 @@ static float output_voltage(void) /* FIXME: may miss a last processing with ErrorVal = 5 | 10 */ } } else if ( !strcmp(types[type].name, "IMP") || !strcmp(types[type].name, "OPTI")) { - tmp=raw_data[OUTPUT_VOLTAGE]*2.0; + tmp = raw_data[OUTPUT_VOLTAGE]*2.0; } else { - tmp= linevoltage >= 220 ? - types[type].voltage[0] * raw_data[OUTPUT_VOLTAGE] + - types[type].voltage[1] : - types[type].voltage[2] * raw_data[OUTPUT_VOLTAGE] + - types[type].voltage[3]; + tmp = linevoltage >= 220 + ? types[type].voltage[0] * raw_data[OUTPUT_VOLTAGE] + + types[type].voltage[1] + : types[type].voltage[2] * raw_data[OUTPUT_VOLTAGE] + + types[type].voltage[3]; } if (tmp<0) tmp=0.0; return tmp; @@ -781,37 +781,37 @@ void upsdrv_updateinfo(void) /* input.frequency */ upsdebugx(3, "input.frequency (raw data): [raw: %u]", - raw_data[INPUT_FREQUENCY]); + raw_data[INPUT_FREQUENCY]); dstate_setinfo("input.frequency", "%02.2f", input_freq()); upsdebugx(2, "input.frequency: %s", dstate_getinfo("input.frequency")); /* output.frequency */ upsdebugx(3, "output.frequency (raw data): [raw: %u]", - raw_data[OUTPUT_FREQUENCY]); + raw_data[OUTPUT_FREQUENCY]); dstate_setinfo("output.frequency", "%02.2f", output_freq()); upsdebugx(2, "output.frequency: %s", dstate_getinfo("output.frequency")); /* ups.load */ upsdebugx(3, "ups.load (raw data): [raw: %u]", - raw_data[UPS_LOAD]); + raw_data[UPS_LOAD]); dstate_setinfo("ups.load", "%03.1f", load_level()); upsdebugx(2, "ups.load: %s", dstate_getinfo("ups.load")); /* battery.charge */ upsdebugx(3, "battery.charge (raw data): [raw: %u]", - raw_data[BATTERY_CHARGE]); + raw_data[BATTERY_CHARGE]); dstate_setinfo("battery.charge", "%03.1f", batt_level()); upsdebugx(2, "battery.charge: %s", dstate_getinfo("battery.charge")); /* input.voltage */ upsdebugx(3, "input.voltage (raw data): [raw: %u]", - raw_data[INPUT_VOLTAGE]); + raw_data[INPUT_VOLTAGE]); dstate_setinfo("input.voltage", "%03.1f",input_voltage()); upsdebugx(2, "input.voltage: %s", dstate_getinfo("input.voltage")); /* output.voltage */ upsdebugx(3, "output.voltage (raw data): [raw: %u]", - raw_data[OUTPUT_VOLTAGE]); + raw_data[OUTPUT_VOLTAGE]); dstate_setinfo("output.voltage", "%03.1f",output_voltage()); upsdebugx(2, "output.voltage: %s", dstate_getinfo("output.voltage")); @@ -907,95 +907,100 @@ void upsdrv_initups(void) tmp = atoi(getval("numOfBytesFromUPS")); if (! (tmp > 0 && tmp <= MAX_NUM_OF_BYTES_FROM_UPS) ) { printf("Given numOfBytesFromUPS '%d' is out of range (1 to %d)\n", - tmp, MAX_NUM_OF_BYTES_FROM_UPS); + tmp, MAX_NUM_OF_BYTES_FROM_UPS); exit (1); } types[type].num_of_bytes_from_ups = (unsigned char) tmp; } if (testvar("methodOfFlowControl")) { - for (i = 0; - i < NUM_OF_SUBTYPES && - strcmp(types[i].flowControl.name, - getval("methodOfFlowControl")); - i++) ; + for ( + i = 0; + i < NUM_OF_SUBTYPES + && strcmp(types[i].flowControl.name, getval("methodOfFlowControl")); + i++) ; if (i >= NUM_OF_SUBTYPES) { printf("Given methodOfFlowControl '%s' isn't valid!\n", - getval("methodOfFlowControl")); + getval("methodOfFlowControl")); exit (1); } types[type].flowControl = types[i].flowControl; } - if (testvar("validationSequence") && - sscanf(getval("validationSequence"), - "{{%u,%x},{%u,%x},{%u,%x}}", - &types[type].validation[0].index_of_byte, - &types[type].validation[0].required_value, - &types[type].validation[1].index_of_byte, - &types[type].validation[1].required_value, - &types[type].validation[2].index_of_byte, - &types[type].validation[2].required_value - ) < 6 - ) { + if (testvar("validationSequence") + && sscanf(getval("validationSequence"), + "{{%u,%x},{%u,%x},{%u,%x}}", + &types[type].validation[0].index_of_byte, + &types[type].validation[0].required_value, + &types[type].validation[1].index_of_byte, + &types[type].validation[1].required_value, + &types[type].validation[2].index_of_byte, + &types[type].validation[2].required_value + ) < 6 + ) { printf("Given validationSequence '%s' isn't valid!\n", - getval("validationSequence")); + getval("validationSequence")); exit (1); } /* NOTE: %hhu is not supported before C99; that would need reading * arguments into an uint as %u, checking range and casting */ - if (testvar("shutdownArguments") && - sscanf(getval("shutdownArguments"), "{{%hhu,%hhu},%c}", - &types[type].shutdown_arguments.delay[0], - &types[type].shutdown_arguments.delay[1], - &types[type].shutdown_arguments.minutesShouldBeUsed - ) < 3 - ) { - printf("Given shutdownArguments '%s' isn't valid!\n", - getval("shutdownArguments")); + if (testvar("shutdownArguments") + && sscanf(getval("shutdownArguments"), + "{{%hhu,%hhu},%c}", + &types[type].shutdown_arguments.delay[0], + &types[type].shutdown_arguments.delay[1], + &types[type].shutdown_arguments.minutesShouldBeUsed + ) < 3 + ) { + printf("Given shutdownArguments '%s' isn't valid!\n", + getval("shutdownArguments")); exit (1); } - if (testvar("frequency") && - sscanf(getval("frequency"), "{%f,%f}", - &types[type].freq[0], &types[type].freq[1] - ) < 2 - ) { + if (testvar("frequency") + && sscanf(getval("frequency"), + "{%f,%f}", + &types[type].freq[0], &types[type].freq[1] + ) < 2 + ) { printf("Given frequency '%s' isn't valid!\n", - getval("frequency")); + getval("frequency")); exit (1); } - if (testvar("loadPercentage") && - sscanf(getval("loadPercentage"), "{%f,%f,%f,%f}", - &types[type].loadpct[0], &types[type].loadpct[1], - &types[type].loadpct[2], &types[type].loadpct[3] - ) < 4 - ) { + if (testvar("loadPercentage") + && sscanf(getval("loadPercentage"), + "{%f,%f,%f,%f}", + &types[type].loadpct[0], &types[type].loadpct[1], + &types[type].loadpct[2], &types[type].loadpct[3] + ) < 4 + ) { printf("Given loadPercentage '%s' isn't valid!\n", - getval("loadPercentage")); + getval("loadPercentage")); exit (1); } - if (testvar("batteryPercentage") && - sscanf(getval("batteryPercentage"), "{%f,%f,%f,%f,%f}", - &types[type].battpct[0], &types[type].battpct[1], - &types[type].battpct[2], &types[type].battpct[3], - &types[type].battpct[4] - ) < 5 - ) { + if (testvar("batteryPercentage") + && sscanf(getval("batteryPercentage"), + "{%f,%f,%f,%f,%f}", + &types[type].battpct[0], &types[type].battpct[1], + &types[type].battpct[2], &types[type].battpct[3], + &types[type].battpct[4] + ) < 5 + ) { printf("Given batteryPercentage '%s' isn't valid!\n", - getval("batteryPercentage")); + getval("batteryPercentage")); exit (1); } - if (testvar("voltage") && - sscanf(getval("voltage"), "{%f,%f,%f,%f}", - &types[type].voltage[0], &types[type].voltage[1], - &types[type].voltage[2], &types[type].voltage[3] - ) < 4 - ) { + if (testvar("voltage") + && sscanf(getval("voltage"), + "{%f,%f,%f,%f}", + &types[type].voltage[0], &types[type].voltage[1], + &types[type].voltage[2], &types[type].voltage[3] + ) < 4 + ) { printf("Given voltage '%s' isn't valid!\n", getval("voltage")); exit (1); } @@ -1144,34 +1149,34 @@ void upsdrv_initinfo(void) upsdebugx(1, " line voltage : '%u'", linevoltage); upsdebugx(1, " type : '%s'", types[type].name); upsdebugx(1, " number of bytes from UPS: '%u'", - types[type].num_of_bytes_from_ups); + types[type].num_of_bytes_from_ups); upsdebugx(1, " method of flow control : '%s'", - types[type].flowControl.name); + types[type].flowControl.name); upsdebugx(1, " validation sequence: '{{%u,%#x},{%u,%#x},{%u,%#x}}'", - types[type].validation[0].index_of_byte, - types[type].validation[0].required_value, - types[type].validation[1].index_of_byte, - types[type].validation[1].required_value, - types[type].validation[2].index_of_byte, - types[type].validation[2].required_value); + types[type].validation[0].index_of_byte, + types[type].validation[0].required_value, + types[type].validation[1].index_of_byte, + types[type].validation[1].required_value, + types[type].validation[2].index_of_byte, + types[type].validation[2].required_value); upsdebugx(1, " shutdown arguments: '{{%u,%u},%c}'", - types[type].shutdown_arguments.delay[0], - types[type].shutdown_arguments.delay[1], - types[type].shutdown_arguments.minutesShouldBeUsed); + types[type].shutdown_arguments.delay[0], + types[type].shutdown_arguments.delay[1], + types[type].shutdown_arguments.minutesShouldBeUsed); if ( strcmp(types[type].name, "KIN") && strcmp(types[type].name, "BNT") && strcmp(types[type].name, "IMP")) { upsdebugx(1, " frequency calculation coefficients: '{%f,%f}'", - types[type].freq[0], types[type].freq[1]); + types[type].freq[0], types[type].freq[1]); upsdebugx(1, " load percentage calculation coefficients: " - "'{%f,%f,%f,%f}'", - types[type].loadpct[0], types[type].loadpct[1], - types[type].loadpct[2], types[type].loadpct[3]); + "'{%f,%f,%f,%f}'", + types[type].loadpct[0], types[type].loadpct[1], + types[type].loadpct[2], types[type].loadpct[3]); upsdebugx(1, " battery percentage calculation coefficients: " - "'{%f,%f,%f,%f,%f}'", - types[type].battpct[0], types[type].battpct[1], - types[type].battpct[2], types[type].battpct[3], - types[type].battpct[4]); + "'{%f,%f,%f,%f,%f}'", + types[type].battpct[0], types[type].battpct[1], + types[type].battpct[2], types[type].battpct[3], + types[type].battpct[4]); upsdebugx(1, " voltage calculation coefficients: '{%f,%f}'", - types[type].voltage[2], types[type].voltage[3]); + types[type].voltage[2], types[type].voltage[3]); } /* write constant data for this model */ diff --git a/drivers/richcomm_usb.c b/drivers/richcomm_usb.c index 42578d82d2..c20e1b6ea2 100644 --- a/drivers/richcomm_usb.c +++ b/drivers/richcomm_usb.c @@ -703,13 +703,13 @@ void upsdrv_updateinfo(void) status_init(); if (online) { - status_set("OL"); + status_set("OL"); } else { - status_set("OB"); + status_set("OB"); } if (!battery_normal) { - status_set("LB"); + status_set("LB"); } status_commit(); diff --git a/drivers/riello_ser.c b/drivers/riello_ser.c index f553362071..d2844a20bf 100644 --- a/drivers/riello_ser.c +++ b/drivers/riello_ser.c @@ -1333,7 +1333,7 @@ static int setvar(const char *varname, const char *val) { upsdebug_SET_STARTING(varname, val); - if (!strcasecmp(varname, "ups.test.interval")) { + if (!strcasecmp(varname, "ups.test.interval")) { ser_send_buf(upsfd, ...); return STAT_SET_HANDLED; } diff --git a/drivers/skel.c b/drivers/skel.c index 2f1e0c2199..c98d462304 100644 --- a/drivers/skel.c +++ b/drivers/skel.c @@ -153,7 +153,7 @@ static int setvar(const char *varname, const char *val) { upsdebug_SET_STARTING(varname, val); - if (!strcasecmp(varname, "ups.test.interval")) { + if (!strcasecmp(varname, "ups.test.interval")) { ser_send_buf(upsfd, ...); return STAT_SET_HANDLED; } diff --git a/drivers/snmp-ups.c b/drivers/snmp-ups.c index a69239af8d..391bac1ee8 100644 --- a/drivers/snmp-ups.c +++ b/drivers/snmp-ups.c @@ -790,9 +790,10 @@ void upsdrv_initups(void) if (!strcmp(mibs, "--list")) { int i; - printf("The 'mibs' argument is '%s', so just listing the mappings this driver knows,\n" - "and for 'mibs=auto' these mappings will be tried in the following order until\n" - "the first one matches your device\n\n", mibs); + printf( + "The 'mibs' argument is '%s', so just listing the mappings this driver knows,\n" + "and for 'mibs=auto' these mappings will be tried in the following order until\n" + "the first one matches your device\n\n", mibs); printf("%7s\t%-23s\t%-7s\t%-31s\t%-s\n", "NUMBER", "MAPPING NAME", "VERSION", "ENTRY POINT OID", "AUTO CHECK OID"); @@ -882,7 +883,7 @@ void upsdrv_initups(void) if (status == TRUE) upslogx(LOG_INFO, "Detected %s on host %s (mib: %s %s)", - model, device_path, mibname, mibvers); + model, device_path, mibname, mibvers); else fatalx(EXIT_FAILURE, "%s MIB wasn't found on %s", mibs, g_snmp_sess.peername); /* FIXME: "No supported device detected" */ @@ -1926,13 +1927,13 @@ void su_setinfo(snmp_info_t *su_info_p, const char *value) info_lkp != NULL && info_lkp->info_value != NULL; info_lkp++ ) { - dstate_addenum(info_type, "%s", info_lkp->info_value); + dstate_addenum(info_type, "%s", info_lkp->info_value); } } /* Commit the current value, to avoid staleness with huge * data collections on slow devices */ - dstate_dataok(); + dstate_dataok(); } } @@ -2346,7 +2347,7 @@ long su_find_valinfo(info_lkp_t *oid2info, const char* value) if (!(strcmp(info_lkp->info_value, value))) { upsdebugx(1, "%s: found %s (value: %s)", - __func__, info_lkp->info_value, value); + __func__, info_lkp->info_value, value); errno = 0; return info_lkp->oid_value; @@ -2421,7 +2422,7 @@ const char *su_find_infoval(info_lkp_t *oid2info, void *raw_value) ) { if (info_lkp->oid_value == value) { upsdebugx(1, "%s: found %s (value: %ld)", - __func__, info_lkp->info_value, value); + __func__, info_lkp->info_value, value); errno = 0; return info_lkp->info_value; @@ -3432,7 +3433,8 @@ bool_t snmp_ups_walk(int mode) /* skip instcmd, not linked to outlets */ if ((SU_TYPE(su_info_p) == SU_TYPE_CMD) && !(su_info_p->flags & SU_OUTLET) - && !(su_info_p->flags & SU_OUTLET_GROUP)) { + && !(su_info_p->flags & SU_OUTLET_GROUP) + ) { upsdebugx(1, "SU_CMD_MASK => %s", su_info_p->OID); continue; } diff --git a/drivers/snmp-ups.h b/drivers/snmp-ups.h index 3775ad78da..91e1c16dca 100644 --- a/drivers/snmp-ups.h +++ b/drivers/snmp-ups.h @@ -290,9 +290,10 @@ typedef struct { #define SU_FLAG_NAINVALID (1UL << 7) /* Invalid if "N/A" value */ #define SU_CMD_OFFSET (1UL << 8) /* Add +1 to the OID index */ -#define SU_FLAG_SEMI_STATIC (1UL << 9) /* Refresh this entry once in several walks - * (for R/W values user can set on device, - * like descriptions or contacts) */ +#define SU_FLAG_SEMI_STATIC (1UL << 9) + /* Refresh this entry once in several walks + * (for R/W values user can set on device, + * like descriptions or contacts) */ /* Notes on outlet templates usage: * - outlet.count MUST exist and MUST be declared before any outlet template diff --git a/drivers/socomec_jbus.c b/drivers/socomec_jbus.c index d4b14ec2c8..6affbdbbdd 100644 --- a/drivers/socomec_jbus.c +++ b/drivers/socomec_jbus.c @@ -106,13 +106,13 @@ void upsdrv_initinfo(void) } if (tab_reg[3] && tab_reg[4] && tab_reg[5] && tab_reg[6] && tab_reg[7]) { - dstate_setinfo("ups.serial", "%c%c%c%c%c%c%c%c%c%c", - (tab_reg[3]&0xFF), (tab_reg[3]>>8), - (tab_reg[4]&0xFF), (tab_reg[4]>>8), - (tab_reg[5]&0xFF), (tab_reg[5]>>8), - (tab_reg[6]&0xFF), (tab_reg[6]>>8), - (tab_reg[7]&0xFF), (tab_reg[7]>>8) - ); + dstate_setinfo("ups.serial", "%c%c%c%c%c%c%c%c%c%c", + (tab_reg[3]&0xFF), (tab_reg[3]>>8), + (tab_reg[4]&0xFF), (tab_reg[4]>>8), + (tab_reg[5]&0xFF), (tab_reg[5]>>8), + (tab_reg[6]&0xFF), (tab_reg[6]>>8), + (tab_reg[7]&0xFF), (tab_reg[7]>>8) + ); } /* upsh.instcmd = instcmd; */ diff --git a/drivers/solis.c b/drivers/solis.c index bc3472a52b..d11a7fed05 100644 --- a/drivers/solis.c +++ b/drivers/solis.c @@ -194,10 +194,10 @@ static void send_shutdown( void ) { int i; for (i = 0; i < 10; i++) - ser_send_char(upsfd, CMD_SHUT ); + ser_send_char(upsfd, CMD_SHUT); - upslogx(LOG_NOTICE, "Ups shutdown command sent"); - printf("Ups shutdown command sent\n"); + upslogx(LOG_NOTICE, "UPS shutdown command sent"); + printf("UPS shutdown command sent\n"); } /* save config ups */ @@ -447,7 +447,7 @@ static void scan_received_pack(void) { /* Specific for STAY1200_USB */ if (SolisModel == 16) { - InFreq = ((float)(0.37 * (257 - (aux >> 8)))); + InFreq = ((float)(0.37 * (257 - (aux >> 8)))); } else InFreq = 0; diff --git a/drivers/tripplite-hid.c b/drivers/tripplite-hid.c index 4a463846f3..ee5f41f8b2 100644 --- a/drivers/tripplite-hid.c +++ b/drivers/tripplite-hid.c @@ -529,8 +529,8 @@ static int tripplite_claim(HIDDevice_t *hd) { if (hd->ProductID == 0x0001) { /* e.g. SMART550USB, SMART3000RM2U */ upsdebugx(0, "This Tripp Lite device (%04x/%04x) is not supported by usbhid-ups.\n" - "Please use the tripplite_usb driver instead.\n", - hd->VendorID, hd->ProductID); + "Please use the tripplite_usb driver instead.\n", + hd->VendorID, hd->ProductID); return 0; } diff --git a/drivers/tripplite_usb.c b/drivers/tripplite_usb.c index 2735394712..8802813c6e 100644 --- a/drivers/tripplite_usb.c +++ b/drivers/tripplite_usb.c @@ -309,13 +309,16 @@ static usb_communication_subdriver_t *comm_driver = &usb_subdriver; /* Interval notation for Q% = 10% <= [minV, maxV] <= 100% */ static double V_interval[2] = {MIN_VOLT, MAX_VOLT}; -static long battery_voltage_nominal = 12, - input_voltage_nominal = 120, - input_voltage_scaled = 120, - /* input_voltage_maximum = -1, - input_voltage_minimum = -1, */ - switchable_load_banks = 0, - unit_id = DEFAULT_UPSID; /*!< range: 1-65535, most likely */ +static long + battery_voltage_nominal = 12, + input_voltage_nominal = 120, + input_voltage_scaled = 120, + /* + input_voltage_maximum = -1, + input_voltage_minimum = -1, + */ + switchable_load_banks = 0, + unit_id = DEFAULT_UPSID; /*!< range: 1-65535, most likely */ /*! Time in seconds to delay before shutting down. */ static unsigned int offdelay = DEFAULT_OFFDELAY; @@ -556,74 +559,86 @@ static void decode_v(const unsigned char *value) battery_voltage_nominal = bv * 6; } - ivn = value[1]; + ivn = value[1]; lb = value[4]; if( is_smart_protocol() && (tl_model != TRIPP_LITE_SMART_3017) ) { switch(ivn) { case 0: - case '0': input_voltage_nominal = - input_voltage_scaled = 100; - break; + case '0': + input_voltage_nominal = + input_voltage_scaled = 100; + break; case 1: - case '1': input_voltage_nominal = - input_voltage_scaled = 110; - break; + case '1': + input_voltage_nominal = + input_voltage_scaled = 110; + break; case 2: /* protocol 3005 */ - case '2': input_voltage_nominal = - input_voltage_scaled = 120; - break; + case '2': + input_voltage_nominal = + input_voltage_scaled = 120; + break; case 3: - case '3': input_voltage_nominal = - input_voltage_scaled = 127; - break; + case '3': + input_voltage_nominal = + input_voltage_scaled = 127; + break; case 4: - case '4': input_voltage_nominal = - input_voltage_scaled = 208; - break; + case '4': + input_voltage_nominal = + input_voltage_scaled = 208; + break; case 5: - case '5': input_voltage_nominal = - input_voltage_scaled = 220; - break; + case '5': + input_voltage_nominal = + input_voltage_scaled = 220; + break; case 6: - case '6': input_voltage_nominal = - input_voltage_scaled = 230; - break; + case '6': + input_voltage_nominal = + input_voltage_scaled = 230; + break; case 7: - case '7': input_voltage_nominal = - input_voltage_scaled = 240; - break; + case '7': + input_voltage_nominal = + input_voltage_scaled = 240; + break; default: - upslogx(LOG_WARNING, "Unknown input voltage range: 0x%02x", (unsigned int)ivn); - break; + upslogx(LOG_WARNING, "Unknown input voltage range: 0x%02x", (unsigned int)ivn); + break; } } else { /* Lots of odd cases here; maybe some of the SMART protocols got mixed in, too: */ switch(ivn) { - case '0': input_voltage_nominal = - input_voltage_scaled = 100; - break; + case '0': + input_voltage_nominal = + input_voltage_scaled = 100; + break; - case '1': input_voltage_nominal = - input_voltage_scaled = 120; - break; + case '1': + input_voltage_nominal = + input_voltage_scaled = 120; + break; /* UK SMX1200XLHG protocol 3017 confirmed: */ - case '2': input_voltage_nominal = - input_voltage_scaled = 230; - break; + case '2': + input_voltage_nominal = + input_voltage_scaled = 230; + break; - case '3': input_voltage_nominal = 208; - input_voltage_scaled = 230; - break; + case '3': + input_voltage_nominal = 208; + input_voltage_scaled = 230; + break; case 6: input_voltage_nominal = input_voltage_scaled = 230; @@ -1137,7 +1152,7 @@ void upsdrv_initinfo(void) s_msg[] = "S", u_msg[] = "U", v_msg[] = "V", w_msg[] = "W\0"; char *model, *model_end; unsigned char proto_value[9], f_value[9], p_value[9], s_value[9], - u_value[9], v_value[9], w_value[9]; + u_value[9], v_value[9], w_value[9]; long va; ssize_t ret; unsigned int proto_number = 0; @@ -1148,8 +1163,9 @@ void upsdrv_initinfo(void) fatalx(EXIT_FAILURE, "Error reading protocol"); } - proto_number = ((unsigned)(proto_value[1]) << 8) - | (unsigned)(proto_value[2]); + proto_number = + ( (unsigned)(proto_value[1]) << 8 ) + | (unsigned)(proto_value[2]); tl_model = decode_protocol(proto_number); if(tl_model == TRIPP_LITE_UNKNOWN) diff --git a/drivers/tripplitesu.c b/drivers/tripplitesu.c index a9a8e42b3a..3fd1828fae 100644 --- a/drivers/tripplitesu.c +++ b/drivers/tripplitesu.c @@ -435,7 +435,7 @@ static int get_sensitivity(void) { for (i = 0; i < SIZEOF_ARRAY(sensitivity); i++) { if (sensitivity[i].code == atoi(response)) { dstate_setinfo("input.sensitivity", "%s", - sensitivity[i].name); + sensitivity[i].name); return 1; } } @@ -614,7 +614,7 @@ void upsdrv_initinfo(void) if (!init_comm()) fatalx(EXIT_FAILURE, "Unable to detect Tripp Lite SmartOnline UPS on port %s\n", - device_path); + device_path); min_low_transfer = max_low_transfer = 0; min_high_transfer = max_high_transfer = 0; @@ -629,16 +629,16 @@ void upsdrv_initinfo(void) ptr = field(response, 0); if (ptr) dstate_setinfo("input.voltage.nominal", "%d", - atoi(ptr)); + atoi(ptr)); ptr = field(response, 2); if (ptr) { dstate_setinfo("output.voltage.nominal", "%d", - atoi(ptr)); + atoi(ptr)); } ptr = field(response, 14); if (ptr) dstate_setinfo("battery.voltage.nominal", "%d", - atoi(ptr)); + atoi(ptr)); ptr = field(response, 10); if (ptr) { int ipv = atoi(ptr); @@ -685,7 +685,7 @@ void upsdrv_initinfo(void) dstate_setflags("input.sensitivity", ST_FLAG_RW); for (i = 0; i < SIZEOF_ARRAY(sensitivity); i++) dstate_addenum("input.sensitivity", "%s", - sensitivity[i].name); + sensitivity[i].name); } if (ups.outlet_banks) { dstate_addcmd("load.off"); @@ -707,8 +707,10 @@ void upsdrv_initinfo(void) upsh.instcmd = instcmd; upsh.setvar = setvar; - printf("Detected %s %s on %s\n", dstate_getinfo("ups.mfr"), - dstate_getinfo("ups.model"), device_path); + printf("Detected %s %s on %s\n", + dstate_getinfo("ups.mfr"), + dstate_getinfo("ups.model"), + device_path); } void upsdrv_updateinfo(void) @@ -766,15 +768,15 @@ void upsdrv_updateinfo(void) ptr = field(response, 3); if (ptr) dstate_setinfo("output.voltage", "%03.1f", - (double) (atoi(ptr)) / 10.0); + (double) (atoi(ptr)) / 10.0); ptr = field(response, 1); if (ptr) dstate_setinfo("output.frequency", "%03.1f", - (double) (atoi(ptr)) / 10.0); + (double) (atoi(ptr)) / 10.0); ptr = field(response, 4); if (ptr) dstate_setinfo("output.current", "%03.1f", - (double) (atoi(ptr)) / 10.0); + (double) (atoi(ptr)) / 10.0); low_battery = 0; if (do_command(POLL, STATUS_BATTERY, "", response) <= 0) { @@ -805,11 +807,11 @@ void upsdrv_updateinfo(void) ptr = field(response, 6); if (ptr) dstate_setinfo("battery.voltage", "%03.1f", - (double) (atoi(ptr)) / 10.0); + (double) (atoi(ptr)) / 10.0); ptr = field(response, 7); if (ptr) dstate_setinfo("battery.current", "%03.1f", - (double) (atoi(ptr)) / 10.0); + (double) (atoi(ptr)) / 10.0); if (low_battery) status_set("LB"); @@ -825,11 +827,11 @@ void upsdrv_updateinfo(void) ptr = field(response, 2); if (ptr) dstate_setinfo("input.voltage", "%03.1f", - (double) (atoi(ptr)) / 10.0); + (double) (atoi(ptr)) / 10.0); ptr = field(response, 1); if (ptr) dstate_setinfo("input.frequency", "%03.1f", - (double) (atoi(ptr)) / 10.0); + (double) (atoi(ptr)) / 10.0); } if (do_command(POLL, TEST_RESULT, "", response) > 0) { diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index 0b91bed0f5..a6ba76b459 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -1837,7 +1837,7 @@ int main(int argc, char **argv) upscount = 0; while (tmp) { - tmp = (ups_t*)tmp->next; + tmp = (ups_t*)tmp->next; upscount++; } diff --git a/drivers/upshandler.h b/drivers/upshandler.h index 3d8a378968..c2267fd7b3 100644 --- a/drivers/upshandler.h +++ b/drivers/upshandler.h @@ -181,9 +181,9 @@ struct ups_handler strstr(cmdname, "shutdown.") == cmdname || \ strstr(cmdname, "load.off") == cmdname || \ strstr(cmdname, "load.cycle") == cmdname || \ - ( strstr(cmdname, "outlet.") == cmdname && ( \ - strstr(cmdname, "shutdown.") || \ - strstr(cmdname, "load") \ + ( strstr(cmdname, "outlet.") == cmdname && \ + ( strstr(cmdname, "shutdown.") \ + || strstr(cmdname, "load") \ ) ) \ ) { \ upslog_INSTCMD_POWERSTATE_CHANGE(cmdname, extra) ; \ diff --git a/drivers/usb-common.c b/drivers/usb-common.c index 6e50b37cf3..65068c7bff 100644 --- a/drivers/usb-common.c +++ b/drivers/usb-common.c @@ -79,37 +79,37 @@ static int match_function_exact(USBDevice_t *hd, void *privdata) if (hd->VendorID != data->VendorID) { upsdebugx(2, "%s: failed match of %s: %4x != %4x", - __func__, "VendorID", hd->VendorID, data->VendorID); + __func__, "VendorID", hd->VendorID, data->VendorID); return 0; } if (hd->ProductID != data->ProductID) { upsdebugx(2, "%s: failed match of %s: %4x != %4x", - __func__, "ProductID", hd->ProductID, data->ProductID); + __func__, "ProductID", hd->ProductID, data->ProductID); return 0; } if (strcmp_null(hd->Vendor, data->Vendor) != 0) { upsdebugx(2, "%s: failed match of %s: %s != %s", - __func__, "Vendor", hd->Vendor, data->Vendor); + __func__, "Vendor", hd->Vendor, data->Vendor); return 0; } if (strcmp_null(hd->Product, data->Product) != 0) { upsdebugx(2, "%s: failed match of %s: %s != %s", - __func__, "Product", hd->Product, data->Product); + __func__, "Product", hd->Product, data->Product); return 0; } if (strcmp_null(hd->Serial, data->Serial) != 0) { upsdebugx(2, "%s: failed match of %s: %s != %s", - __func__, "Serial", hd->Serial, data->Serial); + __func__, "Serial", hd->Serial, data->Serial); return 0; } #ifdef DEBUG_EXACT_MATCH_BUS if (strcmp_null(hd->Bus, data->Bus) != 0) { upsdebugx(2, "%s: failed match of %s: %s != %s", - __func__, "Bus", hd->Bus, data->Bus); + __func__, "Bus", hd->Bus, data->Bus); return 0; } #endif @@ -117,7 +117,7 @@ static int match_function_exact(USBDevice_t *hd, void *privdata) # ifdef DEBUG_EXACT_MATCH_BUSPORT if (strcmp_null(hd->BusPort, data->BusPort) != 0) { upsdebugx(2, "%s: failed match of %s: %s != %s", - __func__, "BusPort", hd->BusPort, data->BusPort); + __func__, "BusPort", hd->BusPort, data->BusPort); return 0; } # endif @@ -125,7 +125,7 @@ static int match_function_exact(USBDevice_t *hd, void *privdata) #ifdef DEBUG_EXACT_MATCH_DEVICE if (strcmp_null(hd->Device, data->Device) != 0) { upsdebugx(2, "%s: failed match of %s: %s != %s", - __func__, "Device", hd->Device, data->Device); + __func__, "Device", hd->Device, data->Device); return 0; } #endif @@ -223,10 +223,10 @@ static int match_function_regex(USBDevice_t *hd, void *privdata) if (r != 1) { /* upsdebugx(2, "%s: failed match of %s: %4x !~ %s", - __func__, "VendorID", hd->VendorID, data->regex[0]); + __func__, "VendorID", hd->VendorID, data->regex[0]); */ upsdebugx(2, "%s: failed match of %s: %4x", - __func__, "VendorID", hd->VendorID); + __func__, "VendorID", hd->VendorID); return r; } @@ -234,10 +234,10 @@ static int match_function_regex(USBDevice_t *hd, void *privdata) if (r != 1) { /* upsdebugx(2, "%s: failed match of %s: %4x !~ %s", - __func__, "ProductID", hd->ProductID, data->regex[1]); + __func__, "ProductID", hd->ProductID, data->regex[1]); */ upsdebugx(2, "%s: failed match of %s: %4x", - __func__, "ProductID", hd->ProductID); + __func__, "ProductID", hd->ProductID); return r; } @@ -245,10 +245,10 @@ static int match_function_regex(USBDevice_t *hd, void *privdata) if (r != 1) { /* upsdebugx(2, "%s: failed match of %s: %s !~ %s", - __func__, "Vendor", hd->Vendor, data->regex[2]); + __func__, "Vendor", hd->Vendor, data->regex[2]); */ upsdebugx(2, "%s: failed match of %s: %s", - __func__, "Vendor", hd->Vendor); + __func__, "Vendor", hd->Vendor); return r; } @@ -256,10 +256,10 @@ static int match_function_regex(USBDevice_t *hd, void *privdata) if (r != 1) { /* upsdebugx(2, "%s: failed match of %s: %s !~ %s", - __func__, "Product", hd->Product, data->regex[3]); + __func__, "Product", hd->Product, data->regex[3]); */ upsdebugx(2, "%s: failed match of %s: %s", - __func__, "Product", hd->Product); + __func__, "Product", hd->Product); return r; } @@ -267,10 +267,10 @@ static int match_function_regex(USBDevice_t *hd, void *privdata) if (r != 1) { /* upsdebugx(2, "%s: failed match of %s: %s !~ %s", - __func__, "Serial", hd->Serial, data->regex[4]); + __func__, "Serial", hd->Serial, data->regex[4]); */ upsdebugx(2, "%s: failed match of %s: %s", - __func__, "Serial", hd->Serial); + __func__, "Serial", hd->Serial); return r; } @@ -278,10 +278,10 @@ static int match_function_regex(USBDevice_t *hd, void *privdata) if (r != 1) { /* upsdebugx(2, "%s: failed match of %s: %s !~ %s", - __func__, "Bus", hd->Bus, data->regex[5]); + __func__, "Bus", hd->Bus, data->regex[5]); */ upsdebugx(2, "%s: failed match of %s: %s", - __func__, "Bus", hd->Bus); + __func__, "Bus", hd->Bus); return r; } @@ -289,10 +289,10 @@ static int match_function_regex(USBDevice_t *hd, void *privdata) if (r != 1) { /* upsdebugx(2, "%s: failed match of %s: %s !~ %s", - __func__, "Device", hd->Device, data->regex[6]); + __func__, "Device", hd->Device, data->regex[6]); */ upsdebugx(2, "%s: failed match of %s: %s", - __func__, "Device", hd->Device); + __func__, "Device", hd->Device); return r; } @@ -301,10 +301,10 @@ static int match_function_regex(USBDevice_t *hd, void *privdata) if (r != 1) { /* upsdebugx(2, "%s: failed match of %s: %s !~ %s", - __func__, "Device", hd->Device, data->regex[6]); + __func__, "Device", hd->Device, data->regex[6]); */ upsdebugx(2, "%s: failed match of %s: %s", - __func__, "Bus Port", hd->BusPort); + __func__, "Bus Port", hd->BusPort); return r; } #endif diff --git a/drivers/usb-common.h b/drivers/usb-common.h index 7355b20965..662d17aef7 100644 --- a/drivers/usb-common.h +++ b/drivers/usb-common.h @@ -255,8 +255,9 @@ "usb_interrupt_read() args out of range for libusb_interrupt_transfer() implementation"); } - ret = libusb_interrupt_transfer(dev, (unsigned char)ep, (unsigned char *) bytes, - size, &size, (unsigned int)timeout); + ret = libusb_interrupt_transfer( + dev, (unsigned char)ep, (unsigned char *) bytes, + size, &size, (unsigned int)timeout); /* In case of success, return the operation size, as done with libusb 0.1 */ return (ret == LIBUSB_SUCCESS)?size:ret; } @@ -274,8 +275,9 @@ "usb_interrupt_write() args out of range for libusb_interrupt_transfer() implementation"); } - ret = libusb_interrupt_transfer(dev, (unsigned char)ep, (unsigned char *) bytes, - size, &size, (unsigned int)timeout); + ret = libusb_interrupt_transfer( + dev, (unsigned char)ep, (unsigned char *) bytes, + size, &size, (unsigned int)timeout); /* In case of success, return the operation size, as done with libusb 0.1 */ return (ret == LIBUSB_SUCCESS)?size:ret; } @@ -293,8 +295,9 @@ "usb_bulk_read() args out of range for libusb_interrupt_transfer() implementation"); } - ret = libusb_interrupt_transfer(dev, (unsigned char)ep, (unsigned char *) bytes, - size, &size, (unsigned int)timeout); + ret = libusb_interrupt_transfer( + dev, (unsigned char)ep, (unsigned char *) bytes, + size, &size, (unsigned int)timeout); /* In case of success, return the operation size, as done with libusb 0.1 */ return (ret == LIBUSB_SUCCESS)?size:ret; } @@ -312,8 +315,9 @@ "usb_bulk_write() args out of range for libusb_interrupt_transfer() implementation"); } - ret = libusb_interrupt_transfer(dev, (unsigned char)ep, (unsigned char *) bytes, - size, &size, (unsigned int)timeout); + ret = libusb_interrupt_transfer( + dev, (unsigned char)ep, (unsigned char *) bytes, + size, &size, (unsigned int)timeout); /* In case of success, return the operation size, as done with libusb 0.1 */ return (ret == LIBUSB_SUCCESS)?size:ret; } diff --git a/drivers/ydn23.h b/drivers/ydn23.h index 5006bb5111..9daf07e7dd 100644 --- a/drivers/ydn23.h +++ b/drivers/ydn23.h @@ -280,8 +280,9 @@ static inline int ydn23_frame_send(TYPE_FD_SER fd, struct ydn23_frame *frame) } } - ret = ser_send_buf(fd, frame->CHKSUM, - ((char *) &frame->infolen) - frame->CHKSUM); + ret = ser_send_buf( + fd, frame->CHKSUM, + ((char *) &frame->infolen) - frame->CHKSUM); if (ret <= 0) { upslogx(LOG_WARNING, "ydn23_frame_send: %s", ret ? strerror(errno) : "timeout"); return ret; diff --git a/include/common.h b/include/common.h index 502c1eabdf..39987916ca 100644 --- a/include/common.h +++ b/include/common.h @@ -396,9 +396,12 @@ int str_contains_token(const char *string, const char *token); * checking for uniqueness and going to add a newly seen token. * If such callback returns 0, abort the addition of token and return -3. */ -int str_add_unique_token(char *tgt, size_t tgtsize, const char *token, - int (*callback_always)(char *, size_t, const char *), - int (*callback_unique)(char *, size_t, const char *) +int str_add_unique_token( + char *tgt, + size_t tgtsize, + const char *token, + int (*callback_always)(char *, size_t, const char *), + int (*callback_unique)(char *, size_t, const char *) ); /* Report maximum platform value for the pid_t */ diff --git a/server/conf.c b/server/conf.c index edb05bcb26..b2edf311b6 100644 --- a/server/conf.c +++ b/server/conf.c @@ -475,7 +475,7 @@ void do_upsconf_args(char *upsname, char *var, char *val) /* if not listed, create a new entry and prepend it to the list */ if (temp == NULL) { - temp = (ups_t*)xcalloc(1, sizeof(*temp)); + temp = (ups_t*)xcalloc(1, sizeof(*temp)); temp->upsname = xstrdup(upsname); temp->next = upstable; upstable = temp; diff --git a/server/netlist.c b/server/netlist.c index d480eb1fa3..0d3dc909e5 100644 --- a/server/netlist.c +++ b/server/netlist.c @@ -243,7 +243,7 @@ static void list_ups(nut_ctype_t *client) } else { ret = sendback(client, "UPS %s \"Description unavailable\"\n", - utmp->name); + utmp->name); } if (!ret) diff --git a/server/upsd.c b/server/upsd.c index 5a22ff34f3..09ead23338 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -751,7 +751,7 @@ static void check_command(int cmdnum, nut_ctype_t *client, size_t numarg, && (nut_debug_level > 9 || strcmp(arg[0], "PASSWORD")) /* Do not log credentials by default */ ) { /* Not xcalloc() here, not too fatal if we fail */ - char *s = (char*)calloc(LARGEBUF, sizeof(char)); + char *s = (char*)calloc(LARGEBUF, sizeof(char)); if (s) { size_t i; diff --git a/tests/generic_gpio_liblocal.c b/tests/generic_gpio_liblocal.c index 471052d734..9cce190e0d 100644 --- a/tests/generic_gpio_liblocal.c +++ b/tests/generic_gpio_liblocal.c @@ -35,17 +35,20 @@ static unsigned int num_lines=0; static int gStatus = 0; static int errReqFor_line_get_value_bulk=0; -void setNextLinesReadToFail(void) { +void setNextLinesReadToFail(void) +{ errReqFor_line_get_value_bulk=1; } -void gpiod_chip_close(struct gpiod_chip *chip) { +void gpiod_chip_close(struct gpiod_chip *chip) +{ NUT_UNUSED_VARIABLE(chip); } #if WITH_LIBGPIO_VERSION < 0x00020000 -struct gpiod_chip *gpiod_chip_open_by_name(const char *name) { +struct gpiod_chip *gpiod_chip_open_by_name(const char *name) +{ snprintf(chipName, sizeof(chipName), "%s", name); if (strcmp(name, "gpiochip1")) return (struct gpiod_chip *)1; @@ -55,16 +58,18 @@ struct gpiod_chip *gpiod_chip_open_by_name(const char *name) { } } -unsigned int gpiod_chip_num_lines(struct gpiod_chip *chip) { +unsigned int gpiod_chip_num_lines(struct gpiod_chip *chip) +{ NUT_UNUSED_VARIABLE(chip); if (!strcmp(chipName, "gpiochip2")) return 2; return 32; } -int gpiod_chip_get_lines(struct gpiod_chip *chip, - unsigned int *offsets, unsigned int num_offsets, - struct gpiod_line_bulk *bulk) +int gpiod_chip_get_lines( + struct gpiod_chip *chip, + unsigned int *offsets, unsigned int num_offsets, + struct gpiod_line_bulk *bulk) { NUT_UNUSED_VARIABLE(chip); NUT_UNUSED_VARIABLE(offsets); @@ -73,9 +78,10 @@ int gpiod_chip_get_lines(struct gpiod_chip *chip, return 0; } -int gpiod_line_request_bulk(struct gpiod_line_bulk *bulk, - const struct gpiod_line_request_config *config, - const int *default_vals) +int gpiod_line_request_bulk( + struct gpiod_line_bulk *bulk, + const struct gpiod_line_request_config *config, + const int *default_vals) { NUT_UNUSED_VARIABLE(bulk); NUT_UNUSED_VARIABLE(config); @@ -83,8 +89,9 @@ int gpiod_line_request_bulk(struct gpiod_line_bulk *bulk, return 0; } -int gpiod_line_get_value_bulk(struct gpiod_line_bulk *bulk, - int *values) +int gpiod_line_get_value_bulk( + struct gpiod_line_bulk *bulk, + int *values) { unsigned int i; int pinPos = 1; @@ -104,9 +111,10 @@ int gpiod_line_get_value_bulk(struct gpiod_line_bulk *bulk, return 0; } -int gpiod_line_event_wait_bulk(struct gpiod_line_bulk *bulk, - const struct timespec *timeout, - struct gpiod_line_bulk *event_bulk) +int gpiod_line_event_wait_bulk( + struct gpiod_line_bulk *bulk, + const struct timespec *timeout, + struct gpiod_line_bulk *event_bulk) { NUT_UNUSED_VARIABLE(bulk); NUT_UNUSED_VARIABLE(timeout); @@ -131,35 +139,42 @@ int gpiod_line_event_wait_bulk(struct gpiod_line_bulk *bulk, return 0; } -int gpiod_line_event_read(struct gpiod_line *line, - struct gpiod_line_event *event) { +int gpiod_line_event_read( + struct gpiod_line *line, + struct gpiod_line_event *event) +{ NUT_UNUSED_VARIABLE(line); NUT_UNUSED_VARIABLE(event); return 0; } -unsigned int gpiod_line_offset(struct gpiod_line *line) { +unsigned int gpiod_line_offset(struct gpiod_line *line) +{ NUT_UNUSED_VARIABLE(line); return 0; } -void gpiod_line_release_bulk(struct gpiod_line_bulk *bulk) { +void gpiod_line_release_bulk(struct gpiod_line_bulk *bulk) +{ NUT_UNUSED_VARIABLE(bulk); } #else /* #if WITH_LIBGPIO_VERSION >= 0x00020000 */ struct gpiod_line_request * -gpiod_chip_request_lines(struct gpiod_chip *chip, - struct gpiod_request_config *req_cfg, - struct gpiod_line_config *line_cfg) { +gpiod_chip_request_lines( + struct gpiod_chip *chip, + struct gpiod_request_config *req_cfg, + struct gpiod_line_config *line_cfg) +{ NUT_UNUSED_VARIABLE(chip); NUT_UNUSED_VARIABLE(req_cfg); NUT_UNUSED_VARIABLE(line_cfg); return (struct gpiod_line_request *)1; } -struct gpiod_chip *gpiod_chip_open(const char *path) { +struct gpiod_chip *gpiod_chip_open(const char *path) +{ snprintf(chipName, sizeof(chipName), "%s", path); if (!strstr(path, "gpiochip1")) return (struct gpiod_chip *)1; @@ -169,48 +184,59 @@ struct gpiod_chip *gpiod_chip_open(const char *path) { } } -struct gpiod_chip_info *gpiod_chip_get_info(struct gpiod_chip *chip) { +struct gpiod_chip_info *gpiod_chip_get_info(struct gpiod_chip *chip) +{ NUT_UNUSED_VARIABLE(chip); return (struct gpiod_chip_info *)1; } -size_t gpiod_chip_info_get_num_lines(struct gpiod_chip_info *info) { +size_t gpiod_chip_info_get_num_lines(struct gpiod_chip_info *info) +{ NUT_UNUSED_VARIABLE(info); if(strstr(chipName, "gpiochip2")) return 2; return 32; } -void gpiod_chip_info_free(struct gpiod_chip_info *info) { +void gpiod_chip_info_free(struct gpiod_chip_info *info) +{ NUT_UNUSED_VARIABLE(info); } -struct gpiod_line_settings *gpiod_line_settings_new(void) { +struct gpiod_line_settings *gpiod_line_settings_new(void) +{ return (struct gpiod_line_settings *)1; } -int gpiod_line_settings_set_direction(struct gpiod_line_settings *settings, - enum gpiod_line_direction direction) { +int gpiod_line_settings_set_direction( + struct gpiod_line_settings *settings, + enum gpiod_line_direction direction) +{ NUT_UNUSED_VARIABLE(settings); NUT_UNUSED_VARIABLE(direction); return 0; } -int gpiod_line_settings_set_edge_detection(struct gpiod_line_settings *settings, - enum gpiod_line_edge edge) { +int gpiod_line_settings_set_edge_detection( + struct gpiod_line_settings *settings, + enum gpiod_line_edge edge) +{ NUT_UNUSED_VARIABLE(settings); NUT_UNUSED_VARIABLE(edge); return 0; } -struct gpiod_line_config *gpiod_line_config_new(void) { +struct gpiod_line_config *gpiod_line_config_new(void) +{ return (struct gpiod_line_config *)1; } -int gpiod_line_config_add_line_settings(struct gpiod_line_config *config, - const unsigned int *offsets, - size_t num_offsets, - struct gpiod_line_settings *settings) { +int gpiod_line_config_add_line_settings( + struct gpiod_line_config *config, + const unsigned int *offsets, + size_t num_offsets, + struct gpiod_line_settings *settings) +{ NUT_UNUSED_VARIABLE(config); NUT_UNUSED_VARIABLE(offsets); NUT_UNUSED_VARIABLE(num_offsets); @@ -218,18 +244,23 @@ int gpiod_line_config_add_line_settings(struct gpiod_line_config *config, return 0; } -struct gpiod_request_config *gpiod_request_config_new(void) { +struct gpiod_request_config *gpiod_request_config_new(void) +{ return (struct gpiod_request_config *)1; } -void gpiod_request_config_set_consumer(struct gpiod_request_config *config, - const char *consumer) { +void gpiod_request_config_set_consumer( + struct gpiod_request_config *config, + const char *consumer) +{ NUT_UNUSED_VARIABLE(config); NUT_UNUSED_VARIABLE(consumer); } -int gpiod_line_request_get_values(struct gpiod_line_request *request, - enum gpiod_line_value *values) { +int gpiod_line_request_get_values( + struct gpiod_line_request *request, + enum gpiod_line_value *values) +{ unsigned int i; int pinPos = 1; NUT_UNUSED_VARIABLE(request); @@ -248,20 +279,25 @@ int gpiod_line_request_get_values(struct gpiod_line_request *request, return 0; } -void gpiod_line_settings_free(struct gpiod_line_settings *settings) { +void gpiod_line_settings_free(struct gpiod_line_settings *settings) +{ NUT_UNUSED_VARIABLE(settings); } -void gpiod_line_config_free(struct gpiod_line_config *config) { +void gpiod_line_config_free(struct gpiod_line_config *config) +{ NUT_UNUSED_VARIABLE(config); } -void gpiod_request_config_free(struct gpiod_request_config *config) { +void gpiod_request_config_free(struct gpiod_request_config *config) +{ NUT_UNUSED_VARIABLE(config); } -int gpiod_line_request_wait_edge_events(struct gpiod_line_request *request, - int64_t timeout_ns) { +int gpiod_line_request_wait_edge_events( + struct gpiod_line_request *request, + int64_t timeout_ns) +{ NUT_UNUSED_VARIABLE(request); NUT_UNUSED_VARIABLE(timeout_ns); switch(gStatus%3) { @@ -284,7 +320,8 @@ int gpiod_line_request_wait_edge_events(struct gpiod_line_request *request, return 0; } -void gpiod_line_request_release(struct gpiod_line_request *request) { +void gpiod_line_request_release(struct gpiod_line_request *request) +{ NUT_UNUSED_VARIABLE(request); } #endif /* WITH_LIBGPIO_VERSION */ diff --git a/tools/nut-scanner/nut-scanner.c b/tools/nut-scanner/nut-scanner.c index 4d95e0cc12..d6587484ea 100644 --- a/tools/nut-scanner/nut-scanner.c +++ b/tools/nut-scanner/nut-scanner.c @@ -476,13 +476,13 @@ static void handle_arg_cidr(const char *arg_addr, int *auto_nets_ptr) pAddresses = (IP_ADAPTER_ADDRESSES *) xcalloc(1, outBufLen); dwRetVal = - GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen); + GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen); if (dwRetVal == ERROR_BUFFER_OVERFLOW) { - free(pAddresses); - pAddresses = NULL; + free(pAddresses); + pAddresses = NULL; } else { - break; + break; } Iterations++; diff --git a/tools/nut-scanner/nutscan-ip.c b/tools/nut-scanner/nutscan-ip.c index 629fee13f5..a4439bdbdc 100644 --- a/tools/nut-scanner/nutscan-ip.c +++ b/tools/nut-scanner/nutscan-ip.c @@ -149,12 +149,12 @@ size_t nutscan_add_ip_range(nutscan_ip_range_list_t *irl, char * start_ip, char if (start_ip == NULL) { upsdebugx(5, "%s: only end address was provided, setting start to same: %s", - __func__, end_ip); + __func__, end_ip); start_ip = end_ip; } if (end_ip == NULL) { upsdebugx(5, "%s: only start address was provided, setting end to same: %s", - __func__, start_ip); + __func__, start_ip); end_ip = start_ip; } diff --git a/tools/nut-scanner/scan_avahi.c b/tools/nut-scanner/scan_avahi.c index 9f3469f82c..74e0a247ab 100644 --- a/tools/nut-scanner/scan_avahi.c +++ b/tools/nut-scanner/scan_avahi.c @@ -488,7 +488,7 @@ static void browse_callback( void* userdata) { - AvahiClient *c = (AvahiClient*)userdata; + AvahiClient *c = (AvahiClient*)userdata; assert(b); NUT_UNUSED_VARIABLE(flags); @@ -521,7 +521,7 @@ static void browse_callback( * but lacks a value in that enum for lack of flags (unconstrained * lookup). So we have to silence a warning here... */ - if (!((*nut_avahi_service_resolver_new)(c, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, (AvahiLookupFlags)0, resolve_callback, c))) + if (!((*nut_avahi_service_resolver_new)(c, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, (AvahiLookupFlags)0, resolve_callback, c))) #if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_ASSIGN_ENUM) # pragma GCC diagnostic pop #endif @@ -646,7 +646,8 @@ nutscan_device_t * nutscan_scan_avahi(useconds_t usec_timeout) /* See comments about flags just a bit above */ if (!(sb = (*nut_avahi_service_browser_new)( client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, - "_upsd._tcp", NULL, (AvahiLookupFlags)0, browse_callback, client)) + "_upsd._tcp", NULL, (AvahiLookupFlags)0, + browse_callback, client)) ) { #if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_ASSIGN_ENUM) # pragma GCC diagnostic pop diff --git a/tools/nut-scanner/scan_ipmi.c b/tools/nut-scanner/scan_ipmi.c index e3b7403074..b2097bf63c 100644 --- a/tools/nut-scanner/scan_ipmi.c +++ b/tools/nut-scanner/scan_ipmi.c @@ -295,12 +295,14 @@ int nutscan_load_ipmi_library(const char *libname_path) /* Cleanup IPMI contexts */ #ifdef HAVE_FREEIPMI_11X_12X -static void nut_freeipmi_cleanup(ipmi_fru_parse_ctx_t fru_parse_ctx, - ipmi_sdr_ctx_t sdr_ctx) +static void nut_freeipmi_cleanup( + ipmi_fru_parse_ctx_t fru_parse_ctx, + ipmi_sdr_ctx_t sdr_ctx) #else /* HAVE_FREEIPMI_11X_12X */ -static void nut_freeipmi_cleanup(ipmi_fru_parse_ctx_t fru_parse_ctx, - ipmi_sdr_cache_ctx_t sdr_cache_ctx, - ipmi_sdr_parse_ctx_t sdr_parse_ctx) +static void nut_freeipmi_cleanup( + ipmi_fru_parse_ctx_t fru_parse_ctx, + ipmi_sdr_cache_ctx_t sdr_cache_ctx, + ipmi_sdr_parse_ctx_t sdr_parse_ctx) #endif /* HAVE_FREEIPMI_11X_12X */ { if (fru_parse_ctx) { @@ -934,7 +936,7 @@ nutscan_device_t * nutscan_scan_ip_range_ipmi(nutscan_ip_range_list_t * irl, nut #endif /* HAVE_PTHREAD */ if (pass) { - tmp_sec = (nutscan_ipmi_t*)malloc(sizeof(nutscan_ipmi_t)); + tmp_sec = (nutscan_ipmi_t*)malloc(sizeof(nutscan_ipmi_t)); if (tmp_sec == NULL) { upsdebugx(0, "%s: Memory allocation error", __func__); break; diff --git a/tools/nut-scanner/scan_snmp.c b/tools/nut-scanner/scan_snmp.c index bad7233596..e2f8bcbc2d 100644 --- a/tools/nut-scanner/scan_snmp.c +++ b/tools/nut-scanner/scan_snmp.c @@ -522,7 +522,7 @@ static void scan_snmp_add_device(nutscan_snmp_t * sec, struct snmp_pdu *response * Does our driver support the notation? */ dev->port = strdup(session->peername); if (response != NULL) { - buf = (char*)malloc (response->variables->val_len + 1); + buf = (char*)malloc (response->variables->val_len + 1); if (buf) { memcpy(buf, response->variables->val.string, response->variables->val_len); @@ -562,7 +562,7 @@ static void scan_snmp_add_device(nutscan_snmp_t * sec, struct snmp_pdu *response } } else { - buf = (char*)malloc(session->community_len + 1); + buf = (char*)malloc(session->community_len + 1); if (buf) { memcpy(buf, session->community, session->community_len); @@ -617,8 +617,8 @@ static struct snmp_pdu * scan_snmp_get_oid(char* oid_str, void* handle) || response->variables == NULL || response->variables->name == NULL || ((*nut_snmp_oid_compare)(response->variables->name, - response->variables->name_length, - name, name_len) != 0) + response->variables->name_length, + name, name_len) != 0) || response->variables->val.string == NULL ) { (*nut_snmp_free_pdu)(response); @@ -1323,7 +1323,7 @@ nutscan_device_t * nutscan_scan_ip_range_snmp(nutscan_ip_range_list_t * irl, #endif /* HAVE_PTHREAD */ if (pass) { - tmp_sec = (nutscan_snmp_t*)malloc(sizeof(nutscan_snmp_t)); + tmp_sec = (nutscan_snmp_t*)malloc(sizeof(nutscan_snmp_t)); if (tmp_sec == NULL) { upsdebugx(0, "%s: Memory allocation error", __func__); break; diff --git a/tools/nut-scanner/scan_usb.c b/tools/nut-scanner/scan_usb.c index 77050c8267..40dbc8bbfb 100644 --- a/tools/nut-scanner/scan_usb.c +++ b/tools/nut-scanner/scan_usb.c @@ -594,7 +594,7 @@ nutscan_device_t * nutscan_scan_usb(nutscan_usb_t * scanopts) "bus/port '%s', skipping: %s", __func__, busname, device_port, bus_port, - (*nut_usb_strerror)((enum libusb_error)ret)); + (*nut_usb_strerror)((enum libusb_error)ret)); /* Note: closing is not applicable * it seems, and can even segfault diff --git a/tools/nut-scanner/scan_xml_http.c b/tools/nut-scanner/scan_xml_http.c index c4cc8f2326..240c352dfa 100644 --- a/tools/nut-scanner/scan_xml_http.c +++ b/tools/nut-scanner/scan_xml_http.c @@ -698,7 +698,7 @@ nutscan_device_t * nutscan_scan_ip_range_xml_http(nutscan_ip_range_list_t * irl, #endif /* HAVE_PTHREAD */ if (pass) { - tmp_sec = (nutscan_xml_t*)malloc(sizeof(nutscan_xml_t)); + tmp_sec = (nutscan_xml_t*)malloc(sizeof(nutscan_xml_t)); if (tmp_sec == NULL) { upsdebugx(0, "%s: Memory allocation error", __func__); break; From a4ed73b7dc66a1072bda87243cf9785795230e04 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 13:40:55 +0100 Subject: [PATCH 074/198] clients/upsmon.c: indent back a block of code changed by the PR [#3293] Signed-off-by: Jim Klimov --- clients/upsmon.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/clients/upsmon.c b/clients/upsmon.c index dc1a41ce38..25d04ba437 100644 --- a/clients/upsmon.c +++ b/clients/upsmon.c @@ -3687,16 +3687,16 @@ static void reload_conf(void) loadconfig(); /* go through the utype_t struct again */ - tmp = firstups; - while (tmp) { - next = (utype_t *)tmp->next; + tmp = firstups; + while (tmp) { + next = (utype_t *)tmp->next; - /* !retain means it wasn't in the .conf this time around */ - if (tmp->retain == 0) - delete_ups(tmp); + /* !retain means it wasn't in the .conf this time around */ + if (tmp->retain == 0) + delete_ups(tmp); - tmp = next; - } + tmp = next; + } /* see if the user just blew off a foot */ if (totalpv < minsupplies) { From 2f97d7575d05f6e174550bfb5802652ac9a0ce6e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 13:41:26 +0100 Subject: [PATCH 075/198] clients/upsmon.c: there is little point checking configfile for non-NULLness at the beginning of main() [#3293] Signed-off-by: Jim Klimov --- clients/upsmon.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/clients/upsmon.c b/clients/upsmon.c index 25d04ba437..1e29250ce9 100644 --- a/clients/upsmon.c +++ b/clients/upsmon.c @@ -3815,14 +3815,9 @@ int main(int argc, char *argv[]) print_banner_once(prog, 0); /* if no configuration file is specified on the command line, use default */ - /* get the real filename */ - if (configfile) { - configfile = (char *)xrealloc(configfile, strlen(configfile) + 1); - } else { - configfile = (char *)xmalloc(SMALLBUF); - snprintf(configfile, SMALLBUF, "%s/upsmon.conf", confpath()); - configfile = (char *)xrealloc(configfile, strlen(configfile) + 1); - } + configfile = (char *)xmalloc(SMALLBUF); + snprintf(configfile, SMALLBUF, "%s/upsmon.conf", confpath()); + configfile = (char *)xrealloc(configfile, strlen(configfile) + 1); run_as_user = xstrdup(RUN_AS_USER); From 698b4ea1075baad6c9c4a4d61b59e7ef9465c6af Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 13:42:38 +0100 Subject: [PATCH 076/198] drivers/libshut.c, drivers/netxml-ups.c: standardize on "try_num" as the iteration variable name Signed-off-by: Jim Klimov --- drivers/libshut.c | 6 +++--- drivers/netxml-ups.c | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/libshut.c b/drivers/libshut.c index 84341407ed..e35077b879 100644 --- a/drivers/libshut.c +++ b/drivers/libshut.c @@ -876,7 +876,7 @@ int shut_synchronise(usb_dev_handle arg_upsfd) { int retCode = 0; unsigned char c = SHUT_SYNC_OFF, reply; - int attempt; + int try_num; upsdebugx (2, "entering shut_synchronise()"); reply = '\0'; @@ -898,9 +898,9 @@ int shut_synchronise(usb_dev_handle arg_upsfd) */ /* Sync with the UPS according to notification */ - for (attempt = 0; attempt < MAX_TRY; attempt++) + for (try_num = 0; try_num < MAX_TRY; try_num++) { - upsdebugx (3, "Syncing communication (try %i)", attempt); + upsdebugx (3, "Syncing communication (try %i)", try_num); if ((ser_send_char(arg_upsfd, c)) == -1) { diff --git a/drivers/netxml-ups.c b/drivers/netxml-ups.c index f6dd42392b..8313a75eaa 100644 --- a/drivers/netxml-ups.c +++ b/drivers/netxml-ups.c @@ -247,7 +247,7 @@ static char *product_page = NULL; /* Support functions */ static void netxml_alarm_set(void); static void netxml_status_set(void); -static int netxml_authenticate(void *userdata, const char *realm, int attempt, char *username, char *password); +static int netxml_authenticate(void *userdata, const char *realm, int try_num, char *username, char *password); static int netxml_dispatch_request(ne_request *request, ne_xml_parser *parser); static int netxml_get_page(const char *page); @@ -974,12 +974,12 @@ static int netxml_dispatch_request(ne_request *request, ne_xml_parser *parser) } /* Supply the 'login' and 'password' when authentication is required */ -static int netxml_authenticate(void *userdata, const char *realm, int attempt, char *username, char *password) +static int netxml_authenticate(void *userdata, const char *realm, int try_num, char *username, char *password) { char *val; NUT_UNUSED_VARIABLE(userdata); - upsdebugx(2, "%s: realm = [%s], attempt = %d", __func__, realm, attempt); + upsdebugx(2, "%s: realm = [%s], attempt = %d", __func__, realm, try_num); val = getval("login"); snprintf(username, NE_ABUFSIZ, "%s", val ? val : ""); @@ -987,7 +987,7 @@ static int netxml_authenticate(void *userdata, const char *realm, int attempt, c val = getval("password"); snprintf(password, NE_ABUFSIZ, "%s", val ? val : ""); - return attempt; + return try_num; } /* Convert the local status information to NUT format and set NUT From 373ca9f15e3cfaed4fdf0af2ca3c7c9572b5a7d1 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 13:43:54 +0100 Subject: [PATCH 077/198] drivers/nutdrv_qx.c: revert bogus change to qx_process() error handling of xmalloc() [#3293] Signed-off-by: Jim Klimov --- drivers/nutdrv_qx.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index 66e521e6d0..ba6d6a4914 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -4739,11 +4739,8 @@ int qx_process(item_t *item, const char *command) size_t cmdsz = (sizeof(char) * cmdlen); /* in bytes, to be pedantic */ int cmd_len; - /* - * (see comments in `mecer.c` and `blazer.c` / `blazer_ser.c`). - */ if ( !(cmd = (char *)xmalloc(cmdsz)) ) { - upslogx(LOG_ERR, "blazer_ser_command() failed to allocate buffer"); + upslogx(LOG_ERR, "qx_process() failed to allocate buffer"); return -1; } From 0182ddef70ed53926b361bf9e4c0dd4303767107 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 13:44:22 +0100 Subject: [PATCH 078/198] server/upsd.c: add a comment to FTS_T *fds [#3293] Bonus question: what could Gemini mean by "FTS"?.. Signed-off-by: Jim Klimov --- server/upsd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/server/upsd.c b/server/upsd.c index 09ead23338..12ca91beea 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -156,6 +156,7 @@ static tracking_t *tracking_list = NULL; #define FTS_T HANDLE static HANDLE mutex = INVALID_HANDLE_VALUE; #endif /* WIN32 */ +/* Dynamic array of file descriptors (or WIN32 handles) that we poll */ static FTS_T *fds = NULL; static handler_t *handler = NULL; From e44d5a137adeb70676f3803b26388f552eedb5d6 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 13:43:18 +0100 Subject: [PATCH 079/198] drivers/mge-hid.c: add a note about using enum value in sentinel for mge_model_names[] [#3293] Signed-off-by: Jim Klimov --- drivers/mge-hid.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/mge-hid.c b/drivers/mge-hid.c index 265b2e1f97..07f0d678ce 100644 --- a/drivers/mge-hid.c +++ b/drivers/mge-hid.c @@ -121,6 +121,8 @@ static usb_device_id_t mge_usb_device_table[] = { #endif /* !SHUT_MODE => USB */ typedef enum { + /* See note in the sentinel (last) entry of the mapping table + * if you ever want to change this name to a different number */ MGE_DEFAULT_OFFLINE = 0, MGE_PEGASUS = 0x100, MGE_3S = 0x110, @@ -1971,6 +1973,11 @@ static models_name_t mge_model_names [] = { "GALAXY", "3000_30", MGE_DEFAULT, "Galaxy 3000 30 kVA" }, /* end of structure. */ + /* NOTE: Compilers want a named enum value here; + * table-iteration code may care about it being + * exactly zero to act as a sentinel. If you ever + * need to redefine MGE_DEFAULT_OFFLINE to another + * number, provide a name that resolves to zero here. */ { NULL, NULL, MGE_DEFAULT_OFFLINE, NULL } }; From 2e129d81832295d15605511c00ee0c912f92f823 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 15:42:17 +0100 Subject: [PATCH 080/198] tools/nut-scanner/*.c: use `(lt_dlhandle)1` casting instead of `(void *)1` also in comparisons Signed-off-by: Jim Klimov --- tools/nut-scanner/nutscan-init.c | 2 +- tools/nut-scanner/scan_avahi.c | 2 +- tools/nut-scanner/scan_ipmi.c | 2 +- tools/nut-scanner/scan_nut.c | 2 +- tools/nut-scanner/scan_snmp.c | 2 +- tools/nut-scanner/scan_usb.c | 2 +- tools/nut-scanner/scan_xml_http.c | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/nut-scanner/nutscan-init.c b/tools/nut-scanner/nutscan-init.c index 69402d2399..5570c5417e 100644 --- a/tools/nut-scanner/nutscan-init.c +++ b/tools/nut-scanner/nutscan-init.c @@ -662,7 +662,7 @@ int nutscan_unload_library(int *avail, lt_dlhandle *pdl_handle, char **libpath) } /* if previous init failed */ - if (*pdl_handle == (void *)1) { + if (*pdl_handle == (lt_dlhandle)1) { goto end; } diff --git a/tools/nut-scanner/scan_avahi.c b/tools/nut-scanner/scan_avahi.c index 74e0a247ab..f9afce3ef5 100644 --- a/tools/nut-scanner/scan_avahi.c +++ b/tools/nut-scanner/scan_avahi.c @@ -110,7 +110,7 @@ int nutscan_load_avahi_library(const char *libname_path) { if (dl_handle != NULL) { /* if previous init failed */ - if (dl_handle == (void *)1) { + if (dl_handle == (lt_dlhandle)1) { return 0; } /* init has already been done */ diff --git a/tools/nut-scanner/scan_ipmi.c b/tools/nut-scanner/scan_ipmi.c index b2097bf63c..cb94825adf 100644 --- a/tools/nut-scanner/scan_ipmi.c +++ b/tools/nut-scanner/scan_ipmi.c @@ -152,7 +152,7 @@ int nutscan_load_ipmi_library(const char *libname_path) { if (dl_handle != NULL) { /* if previous init failed */ - if (dl_handle == (void *)1) { + if (dl_handle == (lt_dlhandle)1) { return 0; } /* init has already been done */ diff --git a/tools/nut-scanner/scan_nut.c b/tools/nut-scanner/scan_nut.c index bad82d6ba5..fb1b1f99d5 100644 --- a/tools/nut-scanner/scan_nut.c +++ b/tools/nut-scanner/scan_nut.c @@ -88,7 +88,7 @@ int nutscan_load_upsclient_library(const char *libname_path) { if (dl_handle != NULL) { /* if previous init failed */ - if (dl_handle == (void *)1) { + if (dl_handle == (lt_dlhandle)1) { return 0; } /* init has already been done */ diff --git a/tools/nut-scanner/scan_snmp.c b/tools/nut-scanner/scan_snmp.c index e2f8bcbc2d..bcbfc2d517 100644 --- a/tools/nut-scanner/scan_snmp.c +++ b/tools/nut-scanner/scan_snmp.c @@ -294,7 +294,7 @@ int nutscan_load_snmp_library(const char *libname_path) #else /* not WITH_SNMP_STATIC */ if (dl_handle != NULL) { /* if previous init failed */ - if (dl_handle == (void *)1) { + if (dl_handle == (lt_dlhandle)1) { return 0; } /* init has already been done */ diff --git a/tools/nut-scanner/scan_usb.c b/tools/nut-scanner/scan_usb.c index 40dbc8bbfb..c7dc58203c 100644 --- a/tools/nut-scanner/scan_usb.c +++ b/tools/nut-scanner/scan_usb.c @@ -105,7 +105,7 @@ int nutscan_load_usb_library(const char *libname_path) { if (dl_handle != NULL) { /* if previous init failed */ - if (dl_handle == (void *)1) { + if (dl_handle == (lt_dlhandle)1) { return 0; } /* init has already been done */ diff --git a/tools/nut-scanner/scan_xml_http.c b/tools/nut-scanner/scan_xml_http.c index 240c352dfa..8225df06ff 100644 --- a/tools/nut-scanner/scan_xml_http.c +++ b/tools/nut-scanner/scan_xml_http.c @@ -103,7 +103,7 @@ int nutscan_load_neon_library(const char *libname_path) { if (dl_handle != NULL) { /* if previous init failed */ - if (dl_handle == (void *)1) { + if (dl_handle == (lt_dlhandle)1) { return 0; } /* init has already been done */ From 1e9bbef8da690e3e6fe4e2b0e2b8e05ba57eeeda Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 15:57:33 +0100 Subject: [PATCH 081/198] tools/nut-scanner/scan_ipmi.c: uncomment code block that detects "No IPMI on this host" to report the message Signed-off-by: Jim Klimov --- tools/nut-scanner/scan_ipmi.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/tools/nut-scanner/scan_ipmi.c b/tools/nut-scanner/scan_ipmi.c index cb94825adf..2be77ab160 100644 --- a/tools/nut-scanner/scan_ipmi.c +++ b/tools/nut-scanner/scan_ipmi.c @@ -590,21 +590,24 @@ nutscan_device_t * nutscan_scan_ipmi_device(const char * IPaddr, nutscan_ipmi_t IPMI_FLAGS_DEFAULT )) < 0) { - /* No IPMI device detected on this host! - if ((*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_USERNAME_INVALID + if ( (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_USERNAME_INVALID || (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_PASSWORD_INVALID || (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_PRIVILEGE_LEVEL_INSUFFICIENT || (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_PRIVILEGE_LEVEL_CANNOT_BE_OBTAINED || (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_AUTHENTICATION_TYPE_UNAVAILABLE || (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_PASSWORD_VERIFICATION_TIMEOUT || (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_HOSTNAME_INVALID - || (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_CONNECTION_TIMEOUT) { */ + || (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_CONNECTION_TIMEOUT + ) { + upsdebugx(3, "nut_ipmi_ctx_open_outofband (%s): " + "No IPMI device detected on this host!", + IPaddr); + } - /* FIXME: don't log timeout errors */ - upsdebugx(2, "nut_ipmi_ctx_open_outofband (%s): %s", - IPaddr, (*nut_ipmi_ctx_errormsg) (ipmi_ctx)); - return NULL; - /*}*/ + /* FIXME: don't log timeout errors */ + upsdebugx(2, "nut_ipmi_ctx_open_outofband (%s): %s", + IPaddr, (*nut_ipmi_ctx_errormsg) (ipmi_ctx)); + return NULL; } } From cb564b7ed52e7dc14cdc37adfb168d4a246ec912 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 16:24:08 +0100 Subject: [PATCH 082/198] tools/nut-scanner/scan_*.c: fix more inconsistent indentations Signed-off-by: Jim Klimov --- tools/nut-scanner/scan_ipmi.c | 119 ++++++++++++------------ tools/nut-scanner/scan_nut.c | 22 ++--- tools/nut-scanner/scan_snmp.c | 146 ++++++++++++++++-------------- tools/nut-scanner/scan_usb.c | 128 +++++++++++++------------- tools/nut-scanner/scan_xml_http.c | 26 +++--- 5 files changed, 229 insertions(+), 212 deletions(-) diff --git a/tools/nut-scanner/scan_ipmi.c b/tools/nut-scanner/scan_ipmi.c index 2be77ab160..740381cba5 100644 --- a/tools/nut-scanner/scan_ipmi.c +++ b/tools/nut-scanner/scan_ipmi.c @@ -180,97 +180,97 @@ int nutscan_load_ipmi_library(const char *libname_path) *(void **) (&nut_ipmi_fru_close_device_id) = lt_dlsym(dl_handle, IPMI_FRU_CLOSE_DEVICE_ID); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } *(void **) (&nut_ipmi_fru_ctx_destroy) = lt_dlsym(dl_handle, IPMI_FRU_CTX_DESTROY); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } #ifdef HAVE_FREEIPMI_11X_12X *(void **) (&nut_ipmi_sdr_ctx_destroy) = lt_dlsym(dl_handle, "ipmi_sdr_ctx_destroy"); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } #else /* HAVE_FREEIPMI_11X_12X */ *(void **) (&nut_ipmi_sdr_cache_ctx_destroy) = lt_dlsym(dl_handle, "ipmi_sdr_cache_ctx_destroy"); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } *(void **) (&nut_ipmi_sdr_parse_ctx_destroy) = lt_dlsym(dl_handle, "ipmi_sdr_parse_ctx_destroy"); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } #endif /* HAVE_FREEIPMI_11X_12X */ *(void **) (&nut_ipmi_fru_ctx_create) = lt_dlsym(dl_handle, IPMI_FRU_CTX_CREATE); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } *(void **) (&nut_ipmi_fru_ctx_set_flags) = lt_dlsym(dl_handle, IPMI_FRU_CTX_SET_FLAGS); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } *(void **) (&nut_ipmi_fru_open_device_id) = lt_dlsym(dl_handle, IPMI_FRU_OPEN_DEVICE_ID); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } *(void **) (&nut_ipmi_fru_ctx_errormsg) = lt_dlsym(dl_handle, IPMI_FRU_CTX_ERRORMSG); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } *(void **) (&nut_ipmi_fru_read_data_area) = lt_dlsym(dl_handle, IPMI_FRU_READ_DATA_AREA); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } *(void **) (&nut_ipmi_fru_next) = lt_dlsym(dl_handle, IPMI_FRU_PARSE_NEXT); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } *(void **) (&nut_ipmi_ctx_create) = lt_dlsym(dl_handle, "ipmi_ctx_create"); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } *(void **) (&nut_ipmi_ctx_find_inband) = lt_dlsym(dl_handle, "ipmi_ctx_find_inband"); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } *(void **) (&nut_ipmi_ctx_open_outofband) = lt_dlsym(dl_handle, "ipmi_ctx_open_outofband"); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } *(void **) (&nut_ipmi_ctx_errnum) = lt_dlsym(dl_handle, "ipmi_ctx_errnum"); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } *(void **) (&nut_ipmi_ctx_errormsg) = lt_dlsym(dl_handle, "ipmi_ctx_errormsg"); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } *(void **) (&nut_ipmi_ctx_close) = lt_dlsym(dl_handle, "ipmi_ctx_close"); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } *(void **) (&nut_ipmi_ctx_destroy) = lt_dlsym(dl_handle, "ipmi_ctx_destroy"); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } if (dl_saved_libname) @@ -391,11 +391,13 @@ static int is_ipmi_device_supported(ipmi_ctx_t ipmi_ctx, int ipmi_id) memset (areabuf, '\0', IPMI_FRU_AREA_SIZE_MAX + 1); /* parse FRU buffer */ - if ((*nut_ipmi_fru_read_data_area) (fru_parse_ctx, - &area_type, - &area_length, - areabuf, - IPMI_FRU_AREA_SIZE_MAX) < 0) + if ((*nut_ipmi_fru_read_data_area) ( + fru_parse_ctx, + &area_type, + &area_length, + areabuf, + IPMI_FRU_AREA_SIZE_MAX + ) < 0) { #ifdef HAVE_FREEIPMI_11X_12X nut_freeipmi_cleanup(fru_parse_ctx, sdr_ctx); @@ -467,15 +469,16 @@ nutscan_device_t * nutscan_scan_ipmi_device(const char * IPaddr, nutscan_ipmi_t upsdebugx(0, "%s: IPMI scan: %s", __func__, ipmi_ctx_strerror (IPMI_ERR_PERMISSION)); } */ - if ((ret = (*nut_ipmi_ctx_find_inband) (ipmi_ctx, - NULL, - 0, /* don't disable auto-probe */ - 0, - 0, - NULL, - 0, /* workaround flags, none by default */ - 0 /* flags */ - )) < 0) + if ((ret = (*nut_ipmi_ctx_find_inband) ( + ipmi_ctx, + NULL, + 0, /* don't disable auto-probe */ + 0, + 0, + NULL, + 0, /* workaround flags, none by default */ + 0 /* flags */ + )) < 0) { upsdebugx(2, "ipmi_ctx_find_inband (local scan): %s", (*nut_ipmi_ctx_errormsg) (ipmi_ctx)); @@ -501,18 +504,19 @@ nutscan_device_t * nutscan_scan_ipmi_device(const char * IPaddr, nutscan_ipmi_t * upsdebugx(0, "%s: Config File Error: k_g input formatted incorrectly", __func__); * exit (EXIT_FAILURE); * }*/ - if ((ret = (*nut_ipmi_ctx_open_outofband_2_0) (ipmi_ctx, - IPaddr, - ipmi_sec->username, - ipmi_sec->password, - ipmi_sec->K_g_BMC_key, -/*???*/ (ipmi_sec->K_g_BMC_key) ? config->k_g_len : 0, - ipmi_sec->privilege_level, - ipmi_sec->cipher_suite_id, - IPMI_SESSION_TIMEOUT_LENGTH_DEFAULT, - IPMI_RETRANSMISSION_TIMEOUT_LENGTH_DEFAULT, - ipmi_dev->workaround_flags, - flags) < 0) + if ((ret = (*nut_ipmi_ctx_open_outofband_2_0) ( + ipmi_ctx, + IPaddr, + ipmi_sec->username, + ipmi_sec->password, + ipmi_sec->K_g_BMC_key, +/*???*/ (ipmi_sec->K_g_BMC_key) ? config->k_g_len : 0, + ipmi_sec->privilege_level, + ipmi_sec->cipher_suite_id, + IPMI_SESSION_TIMEOUT_LENGTH_DEFAULT, + IPMI_RETRANSMISSION_TIMEOUT_LENGTH_DEFAULT, + ipmi_dev->workaround_flags, + flags) < 0) { upsdebugx(2, "nut_ipmi_ctx_open_outofband_2_0 (%s): %s", IPaddr, (*nut_ipmi_ctx_errormsg) (c->ipmi_ctx)); @@ -578,17 +582,18 @@ nutscan_device_t * nutscan_scan_ipmi_device(const char * IPaddr, nutscan_ipmi_t IPaddr, ipmi_sec->privilege_level); return 0; } - if ((ret = (*nut_ipmi_ctx_open_outofband) (ipmi_ctx, - IPaddr, - ipmi_sec->username, - ipmi_sec->password, - (uint8_t)ipmi_sec->authentication_type, - (uint8_t)ipmi_sec->privilege_level, - IPMI_SESSION_TIMEOUT_LENGTH_DEFAULT, - IPMI_RETRANSMISSION_TIMEOUT_LENGTH_DEFAULT, - ipmi_sec->workaround_flags, - IPMI_FLAGS_DEFAULT - )) < 0) + if ((ret = (*nut_ipmi_ctx_open_outofband) ( + ipmi_ctx, + IPaddr, + ipmi_sec->username, + ipmi_sec->password, + (uint8_t)ipmi_sec->authentication_type, + (uint8_t)ipmi_sec->privilege_level, + IPMI_SESSION_TIMEOUT_LENGTH_DEFAULT, + IPMI_RETRANSMISSION_TIMEOUT_LENGTH_DEFAULT, + ipmi_sec->workaround_flags, + IPMI_FLAGS_DEFAULT + )) < 0) { if ( (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_USERNAME_INVALID || (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_PASSWORD_INVALID @@ -639,8 +644,8 @@ nutscan_device_t * nutscan_scan_ipmi_device(const char * IPaddr, nutscan_ipmi_t * using drivers/libfreeipmi_get_board_info() */ current_nut_dev = nutscan_add_device_to_device( - current_nut_dev, - nut_dev); + current_nut_dev, + nut_dev); memset (port_id, 0, sizeof(port_id)); } diff --git a/tools/nut-scanner/scan_nut.c b/tools/nut-scanner/scan_nut.c index fb1b1f99d5..368a80b99d 100644 --- a/tools/nut-scanner/scan_nut.c +++ b/tools/nut-scanner/scan_nut.c @@ -89,7 +89,7 @@ int nutscan_load_upsclient_library(const char *libname_path) if (dl_handle != NULL) { /* if previous init failed */ if (dl_handle == (lt_dlhandle)1) { - return 0; + return 0; } /* init has already been done */ return 1; @@ -115,33 +115,33 @@ int nutscan_load_upsclient_library(const char *libname_path) lt_dlerror(); *(void **) (&nut_upscli_splitaddr) = lt_dlsym(dl_handle, - "upscli_splitaddr"); + "upscli_splitaddr"); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } *(void **) (&nut_upscli_tryconnect) = lt_dlsym(dl_handle, - "upscli_tryconnect"); + "upscli_tryconnect"); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } *(void **) (&nut_upscli_list_start) = lt_dlsym(dl_handle, - "upscli_list_start"); + "upscli_list_start"); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } *(void **) (&nut_upscli_list_next) = lt_dlsym(dl_handle, - "upscli_list_next"); + "upscli_list_next"); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } *(void **) (&nut_upscli_disconnect) = lt_dlsym(dl_handle, - "upscli_disconnect"); + "upscli_disconnect"); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } if (dl_saved_libname) diff --git a/tools/nut-scanner/scan_snmp.c b/tools/nut-scanner/scan_snmp.c index bcbfc2d517..d70a7917d2 100644 --- a/tools/nut-scanner/scan_snmp.c +++ b/tools/nut-scanner/scan_snmp.c @@ -219,72 +219,75 @@ int nutscan_load_snmp_library(const char *libname_path) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wpedantic" # endif - *(void **) (&nut_init_snmp) = init_snmp; + *(void **) (&nut_init_snmp) = + init_snmp; *(void **) (&nut_snmp_sess_init) = - snmp_sess_init; + snmp_sess_init; *(void **) (&nut_snmp_sess_open) = - snmp_sess_open; + snmp_sess_open; *(void **) (&nut_snmp_sess_close) = - snmp_sess_close; + snmp_sess_close; *(void **) (&nut_snmp_sess_session) = - snmp_sess_session; + snmp_sess_session; *(void **) (&nut_snmp_parse_oid) = - snmp_parse_oid; + snmp_parse_oid; *(void **) (&nut_snmp_pdu_create) = - snmp_pdu_create; + snmp_pdu_create; *(void **) (&nut_snmp_add_null_var) = - snmp_add_null_var; + snmp_add_null_var; *(void **) (&nut_snmp_sess_synch_response) = - snmp_sess_synch_response; + snmp_sess_synch_response; *(void **) (&nut_snmp_oid_compare) = - snmp_oid_compare; - *(void **) (&nut_snmp_free_pdu) = snmp_free_pdu; - *(void **) (&nut_generate_Ku) = generate_Ku; + snmp_oid_compare; + *(void **) (&nut_snmp_free_pdu) = + snmp_free_pdu; + *(void **) (&nut_generate_Ku) = + generate_Ku; *(void **) (&nut_snmp_out_toggle_options) = - snmp_out_toggle_options; + snmp_out_toggle_options; *(void **) (&nut_snmp_api_errstring) = - snmp_api_errstring; + snmp_api_errstring; /* Note: this one is an (int) exposed by netsnmp, not a function! */ nut_snmp_errno = &snmp_errno; #if NUT_HAVE_LIBNETSNMP_usmAESPrivProtocol || NUT_HAVE_LIBNETSNMP_usmAES128PrivProtocol *(void **) (&nut_usmAESPrivProtocol) = - USMAESPRIVPROTOCOL_PTR; + USMAESPRIVPROTOCOL_PTR; #endif #if NUT_HAVE_LIBNETSNMP_usmHMACMD5AuthProtocol *(void **) (&nut_usmHMACMD5AuthProtocol) = - usmHMACMD5AuthProtocol; + usmHMACMD5AuthProtocol; #endif #if NUT_HAVE_LIBNETSNMP_usmHMACSHA1AuthProtocol *(void **) (&nut_usmHMACSHA1AuthProtocol) = - usmHMACSHA1AuthProtocol; + usmHMACSHA1AuthProtocol; #endif #if NUT_HAVE_LIBNETSNMP_usmDESPrivProtocol *(void **) (&nut_usmDESPrivProtocol) = - usmDESPrivProtocol; + usmDESPrivProtocol; #endif #if NUT_HAVE_LIBNETSNMP_DRAFT_BLUMENTHAL_AES_04 # if NUT_HAVE_LIBNETSNMP_usmAES192PrivProtocol *(void **) (&nut_usmAES192PrivProtocol) = - usmAES192PrivProtocol; + usmAES192PrivProtocol; # endif # if NUT_HAVE_LIBNETSNMP_usmAES256PrivProtocol *(void **) (&nut_usmAES256PrivProtocol) = - usmAES256PrivProtocol; + usmAES256PrivProtocol; # endif #endif #if NUT_HAVE_LIBNETSNMP_usmHMAC192SHA256AuthProtocol *(void **) (&nut_usmHMAC192SHA256AuthProtocol) = - usmHMAC192SHA256AuthProtocol; + usmHMAC192SHA256AuthProtocol; #endif #if NUT_HAVE_LIBNETSNMP_usmHMAC256SHA384AuthProtocol *(void **) (&nut_usmHMAC256SHA384AuthProtocol) = - usmHMAC256SHA384AuthProtocol; + usmHMAC256SHA384AuthProtocol; #endif #if NUT_HAVE_LIBNETSNMP_usmHMAC384SHA512AuthProtocol *(void **) (&nut_usmHMAC384SHA512AuthProtocol) = - usmHMAC384SHA512AuthProtocol; + usmHMAC384SHA512AuthProtocol; #endif # if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) @@ -326,55 +329,55 @@ int nutscan_load_snmp_library(const char *libname_path) } *(void **) (&nut_snmp_sess_init) = lt_dlsym(dl_handle, - "snmp_sess_init"); + "snmp_sess_init"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_sess_open) = lt_dlsym(dl_handle, - "snmp_sess_open"); + "snmp_sess_open"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_sess_close) = lt_dlsym(dl_handle, - "snmp_sess_close"); + "snmp_sess_close"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_sess_session) = lt_dlsym(dl_handle, - "snmp_sess_session"); + "snmp_sess_session"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_parse_oid) = lt_dlsym(dl_handle, - "snmp_parse_oid"); + "snmp_parse_oid"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_pdu_create) = lt_dlsym(dl_handle, - "snmp_pdu_create"); + "snmp_pdu_create"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_add_null_var) = lt_dlsym(dl_handle, - "snmp_add_null_var"); + "snmp_add_null_var"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_sess_synch_response) = lt_dlsym(dl_handle, - "snmp_sess_synch_response"); + "snmp_sess_synch_response"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_oid_compare) = lt_dlsym(dl_handle, - "snmp_oid_compare"); + "snmp_oid_compare"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -390,13 +393,13 @@ int nutscan_load_snmp_library(const char *libname_path) } *(void **) (&nut_snmp_out_toggle_options) = lt_dlsym(dl_handle, - "snmp_out_toggle_options"); + "snmp_out_toggle_options"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_api_errstring) = lt_dlsym(dl_handle, - "snmp_api_errstring"); + "snmp_api_errstring"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -408,7 +411,7 @@ int nutscan_load_snmp_library(const char *libname_path) #if NUT_HAVE_LIBNETSNMP_usmAESPrivProtocol || NUT_HAVE_LIBNETSNMP_usmAES128PrivProtocol *(void **) (&nut_usmAESPrivProtocol) = lt_dlsym(dl_handle, - USMAESPRIVPROTOCOL); + USMAESPRIVPROTOCOL); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -416,7 +419,7 @@ int nutscan_load_snmp_library(const char *libname_path) #if NUT_HAVE_LIBNETSNMP_usmHMACMD5AuthProtocol *(void **) (&nut_usmHMACMD5AuthProtocol) = lt_dlsym(dl_handle, - "usmHMACMD5AuthProtocol"); + "usmHMACMD5AuthProtocol"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -424,7 +427,7 @@ int nutscan_load_snmp_library(const char *libname_path) #if NUT_HAVE_LIBNETSNMP_usmHMACSHA1AuthProtocol *(void **) (&nut_usmHMACSHA1AuthProtocol) = lt_dlsym(dl_handle, - "usmHMACSHA1AuthProtocol"); + "usmHMACSHA1AuthProtocol"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -432,7 +435,7 @@ int nutscan_load_snmp_library(const char *libname_path) #if NUT_HAVE_LIBNETSNMP_usmDESPrivProtocol *(void **) (&nut_usmDESPrivProtocol) = lt_dlsym(dl_handle, - "usmDESPrivProtocol"); + "usmDESPrivProtocol"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -441,7 +444,7 @@ int nutscan_load_snmp_library(const char *libname_path) #if NUT_HAVE_LIBNETSNMP_DRAFT_BLUMENTHAL_AES_04 # if NUT_HAVE_LIBNETSNMP_usmAES192PrivProtocol *(void **) (&nut_usmAES192PrivProtocol) = lt_dlsym(dl_handle, - "usmAES192PrivProtocol"); + "usmAES192PrivProtocol"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -449,7 +452,7 @@ int nutscan_load_snmp_library(const char *libname_path) # if NUT_HAVE_LIBNETSNMP_usmAES256PrivProtocol *(void **) (&nut_usmAES256PrivProtocol) = lt_dlsym(dl_handle, - "usmAES256PrivProtocol"); + "usmAES256PrivProtocol"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -458,7 +461,7 @@ int nutscan_load_snmp_library(const char *libname_path) #if NUT_HAVE_LIBNETSNMP_usmHMAC192SHA256AuthProtocol *(void **) (&nut_usmHMAC192SHA256AuthProtocol) = lt_dlsym(dl_handle, - "usmHMAC192SHA256AuthProtocol"); + "usmHMAC192SHA256AuthProtocol"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -466,7 +469,7 @@ int nutscan_load_snmp_library(const char *libname_path) #if NUT_HAVE_LIBNETSNMP_usmHMAC256SHA384AuthProtocol *(void **) (&nut_usmHMAC256SHA384AuthProtocol) = lt_dlsym(dl_handle, - "usmHMAC256SHA384AuthProtocol"); + "usmHMAC256SHA384AuthProtocol"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -474,7 +477,7 @@ int nutscan_load_snmp_library(const char *libname_path) #if NUT_HAVE_LIBNETSNMP_usmHMAC384SHA512AuthProtocol *(void **) (&nut_usmHMAC384SHA512AuthProtocol) = lt_dlsym(dl_handle, - "usmHMAC384SHA512AuthProtocol"); + "usmHMAC384SHA512AuthProtocol"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -823,13 +826,14 @@ static int init_session(struct snmp_session * snmp_sess, nutscan_snmp_t * sec) __func__, snmp_sess->securityAuthProtoLen); return 0; } - if ((*nut_generate_Ku)(snmp_sess->securityAuthProto, - (u_int)snmp_sess->securityAuthProtoLen, - (unsigned char *) sec->authPassword, - strlen(sec->authPassword), - snmp_sess->securityAuthKey, - &snmp_sess->securityAuthKeyLen) - != SNMPERR_SUCCESS + if ((*nut_generate_Ku)( + snmp_sess->securityAuthProto, + (u_int)snmp_sess->securityAuthProtoLen, + (unsigned char *) sec->authPassword, + strlen(sec->authPassword), + snmp_sess->securityAuthKey, + &snmp_sess->securityAuthKeyLen + ) != SNMPERR_SUCCESS ) { upsdebugx(0, "WARNING: %s: " "Error generating Ku from " @@ -912,13 +916,14 @@ static int init_session(struct snmp_session * snmp_sess, nutscan_snmp_t * sec) __func__, snmp_sess->securityAuthProtoLen); return 0; } - if ((*nut_generate_Ku)(snmp_sess->securityAuthProto, - (u_int)snmp_sess->securityAuthProtoLen, - (unsigned char *) sec->privPassword, - strlen(sec->privPassword), - snmp_sess->securityPrivKey, - &snmp_sess->securityPrivKeyLen) - != SNMPERR_SUCCESS + if ((*nut_generate_Ku)( + snmp_sess->securityAuthProto, + (u_int)snmp_sess->securityAuthProtoLen, + (unsigned char *) sec->privPassword, + strlen(sec->privPassword), + snmp_sess->securityPrivKey, + &snmp_sess->securityPrivKeyLen + ) != SNMPERR_SUCCESS ) { upsdebugx(0, "WARNING: %s: " "Error generating Ku from " @@ -995,8 +1000,7 @@ static void * try_SysOID_thready(void * arg) (*nut_snmp_add_null_var)(pdu, name, name_len); - (*nut_snmp_sess_synch_response)(handle, - pdu, &response); + (*nut_snmp_sess_synch_response)(handle, pdu, &response); if (response) { sec->handle = handle; @@ -1005,8 +1009,8 @@ static void * try_SysOID_thready(void * arg) /* SysOID is supposed to give the required MIB. */ /* Check if the received OID match with a known sysOID */ - if (response->variables != NULL && - response->variables->val.objid != NULL + if (response->variables != NULL + && response->variables->val.objid != NULL ) { while (snmp_device_table[index].mib != NULL) { if (snmp_device_table[index].sysoid == NULL) { @@ -1082,8 +1086,9 @@ static void init_snmp_once(void) } } -nutscan_device_t * nutscan_scan_snmp(const char * start_ip, const char * stop_ip, - useconds_t usec_timeout, nutscan_snmp_t * sec) +nutscan_device_t * nutscan_scan_snmp( + const char * start_ip, const char * stop_ip, + useconds_t usec_timeout, nutscan_snmp_t * sec) { nutscan_device_t *ndret; nutscan_ip_range_list_t irl; @@ -1101,8 +1106,9 @@ nutscan_device_t * nutscan_scan_snmp(const char * start_ip, const char * stop_ip return ndret; } -nutscan_device_t * nutscan_scan_ip_range_snmp(nutscan_ip_range_list_t * irl, - useconds_t usec_timeout, nutscan_snmp_t * sec) +nutscan_device_t * nutscan_scan_ip_range_snmp( + nutscan_ip_range_list_t * irl, + useconds_t usec_timeout, nutscan_snmp_t * sec) { bool_t pass = TRUE; /* Track that we may spawn a scanning thread */ nutscan_device_t * result; @@ -1473,8 +1479,9 @@ nutscan_device_t * nutscan_scan_ip_range_snmp(nutscan_ip_range_list_t * irl, #else /* not WITH_SNMP */ /* stub function */ -nutscan_device_t * nutscan_scan_snmp(const char * start_ip, const char * stop_ip, - useconds_t usec_timeout, nutscan_snmp_t * sec) +nutscan_device_t * nutscan_scan_snmp( + const char * start_ip, const char * stop_ip, + useconds_t usec_timeout, nutscan_snmp_t * sec) { NUT_UNUSED_VARIABLE(start_ip); NUT_UNUSED_VARIABLE(stop_ip); @@ -1485,8 +1492,9 @@ nutscan_device_t * nutscan_scan_snmp(const char * start_ip, const char * stop_ip } /* stub function */ -nutscan_device_t * nutscan_scan_ip_range_snmp(nutscan_ip_range_list_t * irl, - useconds_t usec_timeout, nutscan_snmp_t * sec) +nutscan_device_t * nutscan_scan_ip_range_snmp( + nutscan_ip_range_list_t * irl, + useconds_t usec_timeout, nutscan_snmp_t * sec) { NUT_UNUSED_VARIABLE(irl); NUT_UNUSED_VARIABLE(usec_timeout); diff --git a/tools/nut-scanner/scan_usb.c b/tools/nut-scanner/scan_usb.c index c7dc58203c..37faefb614 100644 --- a/tools/nut-scanner/scan_usb.c +++ b/tools/nut-scanner/scan_usb.c @@ -43,15 +43,17 @@ static const char *dl_error = NULL; static char *dl_saved_libname = NULL; static int (*nut_usb_close)(libusb_device_handle *dev); -static int (*nut_usb_control_transfer)(libusb_device_handle *dev, - uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, - unsigned char *data, uint16_t wLength, unsigned int timeout); -static int (*nut_usb_get_string_with_langid)(libusb_device_handle *dev, int index, int langid, - char *buf, size_t buflen); +static int (*nut_usb_control_transfer)( + libusb_device_handle *dev, + uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, + unsigned char *data, uint16_t wLength, unsigned int timeout); +static int (*nut_usb_get_string_with_langid)( + libusb_device_handle *dev, int index, int langid, + char *buf, size_t buflen); /* Fallback implem if the above is not a library symbol */ static int nut_usb_get_string_with_langid_control_transfer( - libusb_device_handle *dev, int index, int langid, - char *buf, size_t buflen); + libusb_device_handle *dev, int index, int langid, + char *buf, size_t buflen); /* Compatibility layer between libusb 0.1 and 1.0 */ #if WITH_LIBUSB_1_0 @@ -68,7 +70,8 @@ static int nut_usb_get_string_with_langid_control_transfer( static uint8_t (*nut_usb_get_bus_number)(libusb_device *dev); static uint8_t (*nut_usb_get_device_address)(libusb_device *dev); static uint8_t (*nut_usb_get_port_number)(libusb_device *dev); - static int (*nut_usb_get_device_descriptor)(libusb_device *dev, + static int (*nut_usb_get_device_descriptor)( + libusb_device *dev, struct libusb_device_descriptor *desc); # define USB_DT_STRING LIBUSB_DT_STRING # define USB_ENDPOINT_IN LIBUSB_ENDPOINT_IN @@ -104,12 +107,12 @@ int nutscan_load_usb_library(const char *libname_path); int nutscan_load_usb_library(const char *libname_path) { if (dl_handle != NULL) { - /* if previous init failed */ - if (dl_handle == (lt_dlhandle)1) { - return 0; - } - /* init has already been done */ - return 1; + /* if previous init failed */ + if (dl_handle == (lt_dlhandle)1) { + return 0; + } + /* init has already been done */ + return 1; } if (libname_path == NULL) { @@ -124,8 +127,8 @@ int nutscan_load_usb_library(const char *libname_path) dl_handle = lt_dlopen(libname_path); if (!dl_handle) { - dl_error = lt_dlerror(); - goto err; + dl_error = lt_dlerror(); + goto err; } /* Clear any existing error */ @@ -133,46 +136,46 @@ int nutscan_load_usb_library(const char *libname_path) *(void **) (&nut_usb_init) = lt_dlsym(dl_handle, USB_INIT_SYMBOL); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } *(void **) (&nut_usb_open) = lt_dlsym(dl_handle, USB_OPEN_SYMBOL); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } *(void **) (&nut_usb_close) = lt_dlsym(dl_handle, USB_CLOSE_SYMBOL); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } *(void **) (&nut_usb_strerror) = lt_dlsym(dl_handle, USB_STRERROR_SYMBOL); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } #if WITH_LIBUSB_1_0 *(void **) (&nut_usb_exit) = lt_dlsym(dl_handle, "libusb_exit"); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } *(void **) (&nut_usb_get_device_list) = lt_dlsym(dl_handle, - "libusb_get_device_list"); + "libusb_get_device_list"); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } *(void **) (&nut_usb_free_device_list) = lt_dlsym(dl_handle, - "libusb_free_device_list"); + "libusb_free_device_list"); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } *(void **) (&nut_usb_get_bus_number) = lt_dlsym(dl_handle, - "libusb_get_bus_number"); + "libusb_get_bus_number"); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } /* Note: per https://nxmnpg.lemoda.net/3/libusb_get_device_address there @@ -180,9 +183,9 @@ int nutscan_load_usb_library(const char *libname_path) * not for too long (libusb-1.0.12...1.0.16) and now it is deprecated. */ *(void **) (&nut_usb_get_device_address) = lt_dlsym(dl_handle, - "libusb_get_device_address"); + "libusb_get_device_address"); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } /* This method may be absent in some libusb versions, and we should @@ -190,78 +193,78 @@ int nutscan_load_usb_library(const char *libname_path) * #if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) */ *(void **) (&nut_usb_get_port_number) = lt_dlsym(dl_handle, - "libusb_get_port_number"); + "libusb_get_port_number"); if ((dl_error = lt_dlerror()) != NULL) { - upsdebugx(0, "WARNING: %s: " - "While loading USB library (%s), failed to find libusb_get_port_number() : %s. " - "The \"busport\" USB matching option will be disabled.", - __func__, libname_path, dl_error); - nut_usb_get_port_number = NULL; + upsdebugx(0, "WARNING: %s: " + "While loading USB library (%s), failed to find libusb_get_port_number() : %s. " + "The \"busport\" USB matching option will be disabled.", + __func__, libname_path, dl_error); + nut_usb_get_port_number = NULL; } *(void **) (&nut_usb_get_device_descriptor) = lt_dlsym(dl_handle, - "libusb_get_device_descriptor"); + "libusb_get_device_descriptor"); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } *(void **) (&nut_usb_control_transfer) = lt_dlsym(dl_handle, - "libusb_control_transfer"); + "libusb_control_transfer"); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } *(void **) (&nut_usb_get_string_with_langid) = lt_dlsym(dl_handle, - "libusb_get_string_descriptor"); + "libusb_get_string_descriptor"); if ((dl_error = lt_dlerror()) != NULL) { - /* This one may be only defined in a header as an inline method; - * then we are adapting it via nut_usb_control_transfer(). - */ - nut_usb_get_string_with_langid = NULL; + /* This one may be only defined in a header as an inline method; + * then we are adapting it via nut_usb_control_transfer(). + */ + nut_usb_get_string_with_langid = NULL; } #else /* for libusb 0.1 */ *(void **) (&nut_usb_find_busses) = lt_dlsym(dl_handle, - "usb_find_busses"); + "usb_find_busses"); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } # ifndef WIN32 *(void **) (&nut_usb_busses) = lt_dlsym(dl_handle, - "usb_busses"); + "usb_busses"); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } # else *(void **) (&nut_usb_get_busses) = lt_dlsym(dl_handle, - "usb_get_busses"); + "usb_get_busses"); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } # endif /* WIN32 */ *(void **)(&nut_usb_find_devices) = lt_dlsym(dl_handle, - "usb_find_devices"); + "usb_find_devices"); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } *(void **) (&nut_usb_control_transfer) = lt_dlsym(dl_handle, - "usb_control_msg"); + "usb_control_msg"); if ((dl_error = lt_dlerror()) != NULL) { - goto err; + goto err; } *(void **) (&nut_usb_get_string_with_langid) = lt_dlsym(dl_handle, - "usb_get_string"); + "usb_get_string"); if ((dl_error = lt_dlerror()) != NULL) { - /* See comment above */ - nut_usb_get_string_with_langid = NULL; + /* See comment above */ + nut_usb_get_string_with_langid = NULL; } #endif /* not WITH_LIBUSB_1_0 => for libusb 0.1 */ if (nut_usb_get_string_with_langid == NULL) { - nut_usb_get_string_with_langid = nut_usb_get_string_with_langid_control_transfer; + nut_usb_get_string_with_langid = nut_usb_get_string_with_langid_control_transfer; } if (dl_saved_libname) @@ -284,8 +287,9 @@ int nutscan_load_usb_library(const char *libname_path) } /* end of dynamic link library stuff */ -static char* is_usb_device_supported(usb_device_id_t *usb_device_id_list, - int dev_VendorID, int dev_ProductID, char **alt) +static char* is_usb_device_supported( + usb_device_id_t *usb_device_id_list, + int dev_VendorID, int dev_ProductID, char **alt) { usb_device_id_t *usbdev; @@ -307,8 +311,8 @@ static char* is_usb_device_supported(usb_device_id_t *usb_device_id_list, * https://github.com/libusb/libusb-compat-0.1/blob/eaed7b8f11badaf07a91e07538f6e8842f59eaab/libusb/libusb-dload.h#L165-L171 */ static int nut_usb_get_string_with_langid_control_transfer( - libusb_device_handle *dev, int index, int langid, - char *buf, size_t buflen) + libusb_device_handle *dev, int index, int langid, + char *buf, size_t buflen) { return (*nut_usb_control_transfer)( dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, diff --git a/tools/nut-scanner/scan_xml_http.c b/tools/nut-scanner/scan_xml_http.c index 8225df06ff..23b0c96073 100644 --- a/tools/nut-scanner/scan_xml_http.c +++ b/tools/nut-scanner/scan_xml_http.c @@ -64,11 +64,12 @@ static lt_dlhandle dl_handle = NULL; static const char *dl_error = NULL; static char *dl_saved_libname = NULL; -static void (*nut_ne_xml_push_handler)(ne_xml_parser *p, - ne_xml_startelm_cb *startelm, - ne_xml_cdata_cb *cdata, - ne_xml_endelm_cb *endelm, - void *userdata); +static void (*nut_ne_xml_push_handler)( + ne_xml_parser *p, + ne_xml_startelm_cb *startelm, + ne_xml_cdata_cb *cdata, + ne_xml_endelm_cb *endelm, + void *userdata); static void (*nut_ne_xml_destroy)(ne_xml_parser *p); static int (*nut_ne_xml_failed)(ne_xml_parser *p); static ne_xml_parser * (*nut_ne_xml_create)(void); @@ -104,7 +105,7 @@ int nutscan_load_neon_library(const char *libname_path) if (dl_handle != NULL) { /* if previous init failed */ if (dl_handle == (lt_dlhandle)1) { - return 0; + return 0; } /* init has already been done */ return 1; @@ -130,7 +131,7 @@ int nutscan_load_neon_library(const char *libname_path) lt_dlerror(); *(void **) (&nut_ne_xml_push_handler) = lt_dlsym(dl_handle, - "ne_xml_push_handler"); + "ne_xml_push_handler"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -309,9 +310,7 @@ static void * nutscan_scan_xml_http_thready(void * arg) upsdebugx(5, "%s: sent request to %s, " "loop #%d/%d, waiting for responses", __func__, (ip ? ip : ""), (i + 1), MAX_RETRIES); - while ((ret = select(peerSocket + 1, &fds, NULL, NULL, - &timeout)) - ) { + while ((ret = select(peerSocket + 1, &fds, NULL, NULL, &timeout))) { ne_xml_parser *parser; int parserFailed; @@ -372,8 +371,9 @@ static void * nutscan_scan_xml_http_thready(void * arg) nut_dev->type = TYPE_XML; /* Try to read device type */ parser = (*nut_ne_xml_create)(); - (*nut_ne_xml_push_handler)(parser, startelm_cb, - NULL, NULL, nut_dev); + (*nut_ne_xml_push_handler)( + parser, startelm_cb, + NULL, NULL, nut_dev); /* recv_size is a ssize_t, so in range of size_t */ (*nut_ne_xml_parse)(parser, buf, (size_t)recv_size); parserFailed = (*nut_ne_xml_failed)(parser); /* 0 = ok, nonzero = fail */ @@ -685,7 +685,7 @@ nutscan_device_t * nutscan_scan_ip_range_xml_http(nutscan_ip_range_list_t * irl, if (curr_threads >= max_threads || (curr_threads >= max_threads_scantype && max_threads_scantype > 0) ) { - usleep (10000); /* microSec's, so 0.01s here */ + usleep (10000); /* microSec's, so 0.01s here */ } } upsdebugx(2, "%s: proceeding with scan", __func__); From 838c162bb48afc1798f014dbc85f8404006777f1 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 16:38:12 +0100 Subject: [PATCH 083/198] *.{c,h}: rectify more indentations and line-wrapping in block comments Signed-off-by: Jim Klimov --- clients/upsimagearg.h | 4 ++-- drivers/apcsmart-old.h | 13 ++++++------- drivers/metasys.c | 18 +++++++++--------- drivers/usb-common.h | 32 ++++++++++++++++---------------- 4 files changed, 33 insertions(+), 34 deletions(-) diff --git a/clients/upsimagearg.h b/clients/upsimagearg.h index 7064b7f82a..9590ff38d0 100644 --- a/clients/upsimagearg.h +++ b/clients/upsimagearg.h @@ -59,8 +59,8 @@ static struct { typedef struct { char *name; /* name of the UPS variable */ - char *minimum; /* name of minimum value UPS variable - or variable in imgarg table */ + char *minimum; /* name of minimum value UPS variable */ + /* or variable in imgarg table */ char *nominal; /* as above, only for nominal value */ char *maximum; /* as above, only for maximum value */ int deviation; /* variable deviation - width of green zone */ diff --git a/drivers/apcsmart-old.h b/drivers/apcsmart-old.h index 752c6a1273..723f33642f 100644 --- a/drivers/apcsmart-old.h +++ b/drivers/apcsmart-old.h @@ -191,13 +191,12 @@ static apc_vartab_t apc_vartab[] = { { "battery.alarm.threshold", 0, 'k' }, /* todo: - - I = alarm enable (hex field) - split into alarm.n.enable - J = alarm status (hex field) - split into alarm.n.status - - 0x15 = output voltage selection (APC_F_VOLT) - 0x5C = load power (APC_POLL|APC_F_PERCENT) - + * + * I = alarm enable (hex field) - split into alarm.n.enable + * J = alarm status (hex field) - split into alarm.n.status + * + * 0x15 = output voltage selection (APC_F_VOLT) + * 0x5C = load power (APC_POLL|APC_F_PERCENT) */ {NULL, 0, 0}, diff --git a/drivers/metasys.c b/drivers/metasys.c index bfe9a65851..19af864ad8 100644 --- a/drivers/metasys.c +++ b/drivers/metasys.c @@ -127,7 +127,7 @@ static void dump_buffer(unsigned char *buffer, int buf_len) { } /* send a read command to the UPS, it retries 5 times before give up - it's a 4 byte request (STX, LENGTH, COMMAND and CHECKSUM) */ + * it's a 4 byte request (STX, LENGTH, COMMAND and CHECKSUM) */ static void send_read_command(unsigned char command) { int retry; ssize_t sent; @@ -147,8 +147,8 @@ static void send_read_command(unsigned char command) { } /* send a write command to the UPS, the write command and the value to be written are passed - with a char* buffer - it retries 5 times before give up */ + * with a char* buffer + * it retries 5 times before give up */ static void send_write_command(unsigned char *command, size_t command_length) { int retry, checksum; ssize_t sent; @@ -215,8 +215,8 @@ static int get_answer(unsigned char *data) { } /* now we have the whole answer from the ups, we can checksum it - checksum byte is equal to the sum modulus 256 of all the data bytes + packet_length - (no STX no checksum byte itself) */ + * checksum byte is equal to the sum modulus 256 of all the data bytes + packet_length + * (no STX no checksum byte itself) */ checksum = packet_length; for (i = 0; i < (packet_length - 1); i++) checksum += my_buf[i]; checksum = checksum % 256; @@ -231,8 +231,8 @@ static int get_answer(unsigned char *data) { } /* send a read command and try get the answer, if something fails, it retries (5 times max) - if it is on the 4th or 5th retry, it will flush the serial before sending commands - it returns the length of the received answer or -1 in case of failure */ + * if it is on the 4th or 5th retry, it will flush the serial before sending commands + * it returns the length of the received answer or -1 in case of failure */ static int command_read_sequence(unsigned char command, unsigned char *data) { int bytes_read = 0; int retry = 0; @@ -253,8 +253,8 @@ static int command_read_sequence(unsigned char command, unsigned char *data) { } /* send a write command and try get the answer, if something fails, it retries (5 times max) - if it is on the 4th or 5th retry, it will flush the serial before sending commands - it returns the length of the received answer or -1 in case of failure */ + * if it is on the 4th or 5th retry, it will flush the serial before sending commands + * it returns the length of the received answer or -1 in case of failure */ static int command_write_sequence(unsigned char *command, size_t command_length, unsigned char *answer) { int bytes_read = 0; int retry = 0; diff --git a/drivers/usb-common.h b/drivers/usb-common.h index 662d17aef7..35dae8b146 100644 --- a/drivers/usb-common.h +++ b/drivers/usb-common.h @@ -203,14 +203,14 @@ usb_ctrl_charbuf bytes, int size, int timeout) { /* - Map from libusb-0.1 API => libusb-1.0 API: - int LIBUSB_CALL libusb_control_transfer( - libusb_device_handle *dev_handle, uint8_t request_type, - uint8_t bRequest, uint16_t wValue, uint16_t wIndex, - unsigned char *data, uint16_t wLength, unsigned int timeout); - Note: In libusb-0.1 bytes was a (char*) but our consumer code - was already fixed to use "usb_ctrl_charbuf" to match other methods. - */ + * Map from libusb-0.1 API => libusb-1.0 API: + * int LIBUSB_CALL libusb_control_transfer( + * libusb_device_handle *dev_handle, uint8_t request_type, + * uint8_t bRequest, uint16_t wValue, uint16_t wIndex, + * unsigned char *data, uint16_t wLength, unsigned int timeout); + * Note: In libusb-0.1 bytes was a (char*) but our consumer code + * was already fixed to use "usb_ctrl_charbuf" to match other methods. + */ if (requesttype < 0 || (uintmax_t)requesttype > UINT8_MAX || request < 0 || (uintmax_t)request > UINT8_MAX @@ -239,13 +239,13 @@ usb_ctrl_charbuf bytes, int size, int timeout) { /* NOTE: Also for routines below: - Map from libusb-0.1 API => libusb-1.0 API plus change of logic per below code: - int LIBUSB_CALL libusb_interrupt_transfer(libusb_device_handle *dev_handle, - unsigned char endpoint, unsigned char *data, int length, - int *actual_length, unsigned int timeout); - Note: In libusb-0.1 bytes was a (char*) but our consumer code - was already fixed to use "usb_ctrl_charbuf" to match other methods. - */ + * Map from libusb-0.1 API => libusb-1.0 API plus change of logic per below code: + * int LIBUSB_CALL libusb_interrupt_transfer(libusb_device_handle *dev_handle, + * unsigned char endpoint, unsigned char *data, int length, + * int *actual_length, unsigned int timeout); + * Note: In libusb-0.1 bytes was a (char*) but our consumer code + * was already fixed to use "usb_ctrl_charbuf" to match other methods. + */ int ret; if (ep < 0 || (uintmax_t)ep > UCHAR_MAX @@ -501,7 +501,7 @@ typedef struct USBDevice_s { char *Product; /*!< Device's Product Name */ char *Serial; /*!< Product serial number */ /* These data points can be determined by the driver for some devices - or by libusb to detail its connection topology: */ + * or by libusb to detail its connection topology: */ char *Bus; /*!< Bus name, e.g. "003" */ uint16_t bcdDevice; /*!< Device release number */ char *Device; /*!< Device name on the bus, e.g. "001" */ From da70fe73a1c9c1aad0461e71419a56bfb330bcc7 Mon Sep 17 00:00:00 2001 From: Tim Niemueller Date: Sat, 24 Jan 2026 19:46:52 +0100 Subject: [PATCH 084/198] Add UPower support to nut-scanner - Added support for scanning UPower devices via GDBus/libgio. - Implemented dynamic loading of libgio/libglib to avoid hard dependencies. - Added --upower_scan (-J) option to nut-scanner. - Added m4/nut_check_libglib.m4 to detect GLib/GIO. - Updated configure.ac to check for UPower support requirements. - Updated nut-scanner build system and initialization. - Updated nut-scanner man page Signed-off-by: Tim Niemueller --- configure.ac | 16 ++ docs/acknowledgements.txt | 1 + docs/man/nut-scanner.txt | 22 ++- docs/nut.dict | 4 +- m4/nut_check_libglib.m4 | 104 ++++++++++ tools/nut-scanner/Makefile.am | 6 +- tools/nut-scanner/nut-scan.h | 2 + tools/nut-scanner/nut-scanner.c | 54 ++++- tools/nut-scanner/nutscan-device.c | 2 + tools/nut-scanner/nutscan-device.h | 1 + tools/nut-scanner/nutscan-init.c | 51 +++++ tools/nut-scanner/nutscan-init.h | 1 + tools/nut-scanner/scan_upower.c | 303 +++++++++++++++++++++++++++++ 13 files changed, 561 insertions(+), 6 deletions(-) create mode 100644 m4/nut_check_libglib.m4 create mode 100644 tools/nut-scanner/scan_upower.c diff --git a/configure.ac b/configure.ac index 3109b7b084..ac52e3eeda 100644 --- a/configure.ac +++ b/configure.ac @@ -2855,6 +2855,7 @@ dnl spelled out in configure.ac NUT_ARG_WITH([macosx_ups], [build and install Mac OS X Power Sources meta-driver], [auto]) NUT_ARG_WITH([linux_i2c], [build and install i2c drivers], [auto]) NUT_ARG_WITH([upower], [build and install UPower driver (requires GLib/GIO)], [auto]) +NUT_CHECK_LIBGLIB dnl A Python GUI client application for the sysadmin desktop dnl (not necessarily on the NUT server itself): @@ -3003,6 +3004,21 @@ fi NUT_REPORT_FEATURE([enable Avahi support], [${nut_with_avahi}], [], [WITH_AVAHI], [Define to enable Avahi support]) +dnl ---------------------------------------------------------------------- +dnl checks related to --with-upower + +dnl ${nut_with_upower}: any value except "yes" or "no" is treated as "auto". +if test "${nut_with_upower}" = "yes" -a "${nut_have_libglib}" != "yes"; then + AC_MSG_ERROR([GLib/GIO libraries not found, required for UPower support]) +fi + +if test "${nut_with_upower}" != "no"; then + nut_with_upower="${nut_have_libglib}" +fi + +NUT_REPORT_FEATURE([enable UPower support], [${nut_with_upower}], [], + [WITH_UPOWER], [Define to enable UPower support]) + dnl ---------------------------------------------------------------------- dnl checks related to --with-powerman diff --git a/docs/acknowledgements.txt b/docs/acknowledgements.txt index 22c7bd2512..7be1be399e 100644 --- a/docs/acknowledgements.txt +++ b/docs/acknowledgements.txt @@ -161,6 +161,7 @@ document - Tank provided documentation on the Belkin/Delta protocol - Potrans provided a Fenton PowerPal 600 (P series) for development of the safenet driver. +- Tim Niemueller wrote nut-upower driver for UPower devices and scanner support. Older entries (before 2005) --------------------------- diff --git a/docs/man/nut-scanner.txt b/docs/man/nut-scanner.txt index 8366e2bf23..9a28b51099 100644 --- a/docs/man/nut-scanner.txt +++ b/docs/man/nut-scanner.txt @@ -29,11 +29,12 @@ INSTALLATION *nut-scanner* is only built if libltdl (part of libtool development suite) is available. -Available scanning options (USB, SNMP, IPMI, ...) will vary according +Available scanning options (USB, SNMP, IPMI, UPower, ...) will vary according to the available compile-time and run-time dependencies. For example, if Net-SNMP is installed, thus providing libsnmp libraries (`*.so` or `*.dll`) and header files during compilation, and at least the library files on the -monitoring system, then SNMP discovery will be available. +monitoring system, then SNMP discovery will be available. Similarly, UPower +discovery requires GDBus/libgio libraries. OPTIONS ------- @@ -106,6 +107,9 @@ No IP address options are required or used. Scan NUT compatible power supplies available via IPMI on the current host, or over the network if IP address ranges are specified. +*-J* | *--upower_scan*:: +Scan UPower devices. Requires GDBus/libgio libraries to be available. + *-E* | *--eaton_serial* 'serial ports':: Scan Eaton devices (XCP and SHUT) available via serial bus on the current host. This option must be requested explicitly, even for a complete scan. @@ -363,6 +367,20 @@ on Windows): :; nut-scanner --eaton_serial 1-2 ---- +To scan for UPower devices: + +---- +:; nut-scanner -J + +[nutdev-upower1] + driver = "upower" + port = "/org/freedesktop/UPower/devices/ups_hiddev0" + vendor = "APC" + product = "Back-UPS ES 700G" + serial = "5B1234567890" + bus = "upower" +---- + SEE ALSO -------- diff --git a/docs/nut.dict b/docs/nut.dict index e81d1fc663..718bab4e1a 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3646 utf-8 +personal_ws-1.1 en 3648 utf-8 AAC AAS ABI @@ -434,6 +434,7 @@ FullLoad Fuß GC GCCVER +GDBus GES GETADDRINFO GETPID @@ -2446,6 +2447,7 @@ libexecdir libexpat libfreeipmi libgd +libgio libglib libgpgme libgpiod diff --git a/m4/nut_check_libglib.m4 b/m4/nut_check_libglib.m4 new file mode 100644 index 0000000000..be30fd5e59 --- /dev/null +++ b/m4/nut_check_libglib.m4 @@ -0,0 +1,104 @@ +dnl Check for LIBGLIB compiler flags. On success, set nut_have_libglib="yes" +dnl and set LIBGLIB_CFLAGS and LIBGLIB_LIBS. On failure, set +dnl nut_have_libglib="no". This macro can be run multiple times, but will +dnl do the checking only once. + +AC_DEFUN([NUT_CHECK_LIBGLIB], +[ +if test -z "${nut_have_libglib_seen}"; then + nut_have_libglib_seen=yes + AC_REQUIRE([NUT_CHECK_PKGCONFIG]) + + dnl save CFLAGS and LIBS + CFLAGS_ORIG="${CFLAGS}" + LIBS_ORIG="${LIBS}" + CFLAGS="" + LIBS="" + depCFLAGS="" + depCFLAGS_SOURCE="" + depLIBS="" + depLIBS_SOURCE="" + + AS_IF([test x"$have_PKG_CONFIG" = xyes], + [dnl See which version of the glib/gio library (if any) is installed + AC_MSG_CHECKING(for gio-2.0 version via pkg-config (2.26.0 minimum required)) + LIBGLIB_VERSION="`$PKG_CONFIG --silence-errors --modversion gio-2.0 2>/dev/null`" + if test "$?" != "0" -o -z "${LIBGLIB_VERSION}"; then + LIBGLIB_VERSION="none" + fi + AC_MSG_RESULT(${LIBGLIB_VERSION} found) + ], [AC_MSG_NOTICE([can not check gio-2.0 settings via pkg-config])] + ) + + AC_MSG_CHECKING(for gio-2.0 cflags) + NUT_ARG_WITH_LIBOPTS_INCLUDES([gio], [auto]) + AS_CASE([${nut_with_gio_includes}], + [auto], [AS_IF([test x"$have_PKG_CONFIG" = xyes], + [ { depCFLAGS="`$PKG_CONFIG --silence-errors --cflags gio-2.0 2>/dev/null`" \ + && depCFLAGS_SOURCE="pkg-config" ; } \ + || { depCFLAGS="-I/usr/local/include/glib-2.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include" \ + && depCFLAGS_SOURCE="default" ; }], + [depCFLAGS="-I/usr/local/include/glib-2.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include" + depCFLAGS_SOURCE="default"] + )], + [depCFLAGS="${nut_with_gio_includes}" + depCFLAGS_SOURCE="confarg"] + ) + AC_MSG_RESULT([${depCFLAGS} (source: ${depCFLAGS_SOURCE})]) + + AC_MSG_CHECKING(for gio-2.0 ldflags) + NUT_ARG_WITH_LIBOPTS_LIBS([gio], [auto]) + AS_CASE([${nut_with_gio_libs}], + [auto], [AS_IF([test x"$have_PKG_CONFIG" = xyes], + [ { depLIBS="`$PKG_CONFIG --silence-errors --libs gio-2.0 2>/dev/null`" \ + && depLIBS_SOURCE="pkg-config" ; } \ + || { depLIBS="-lgio-2.0 -lgobject-2.0 -lglib-2.0" \ + && depLIBS_SOURCE="default" ; }], + [depLIBS="-lgio-2.0 -lgobject-2.0 -lglib-2.0" + depLIBS_SOURCE="default"] + )], + [depLIBS="${nut_with_gio_libs}" + depLIBS_SOURCE="confarg"] + ) + AC_MSG_RESULT([${depLIBS} (source: ${depLIBS_SOURCE})]) + + dnl check if gio-2.0 is usable + CFLAGS="${CFLAGS_ORIG} ${depCFLAGS}" + LIBS="${LIBS_ORIG} ${depLIBS}" + AC_CHECK_HEADERS(gio/gio.h, [nut_have_libglib=yes], [nut_have_libglib=no], [AC_INCLUDES_DEFAULT]) + dnl AC_CHECK_FUNCS(g_bus_get_sync, [], [nut_have_libglib=no]) + + if test "${nut_have_libglib}" = "yes"; then + LIBGLIB_CFLAGS="${depCFLAGS}" + LIBGLIB_LIBS="${depLIBS}" + + dnl Help ltdl if we can (nut-scanner etc.) + for TOKEN in $depLIBS ; do + AS_CASE(["${TOKEN}"], + [-l*gio*], [ + AX_REALPATH_LIB([${TOKEN}], [SOPATH_LIBGLIB], []) + AS_IF([test -n "${SOPATH_LIBGLIB}" && test -s "${SOPATH_LIBGLIB}"], [ + AC_DEFINE_UNQUOTED([SOPATH_LIBGLIB],["${SOPATH_LIBGLIB}"],[Path to dynamic library on build system]) + SOFILE_LIBGLIB="`basename \"$SOPATH_LIBGLIB\"`" + AC_DEFINE_UNQUOTED([SOFILE_LIBGLIB],["${SOFILE_LIBGLIB}"],[Base file name of dynamic library on build system]) + break + ]) + ] + ) + done + unset TOKEN + fi + + unset depCFLAGS + unset depLIBS + unset depCFLAGS_SOURCE + unset depLIBS_SOURCE + + dnl restore original CFLAGS and LIBS + CFLAGS="${CFLAGS_ORIG}" + LIBS="${LIBS_ORIG}" +fi + +AC_SUBST([LIBGLIB_CFLAGS]) +AC_SUBST([LIBGLIB_LIBS]) +]) diff --git a/tools/nut-scanner/Makefile.am b/tools/nut-scanner/Makefile.am index de6e57af10..8227da255d 100644 --- a/tools/nut-scanner/Makefile.am +++ b/tools/nut-scanner/Makefile.am @@ -97,7 +97,8 @@ endif WITH_NUT_SCANNER libnutscan_la_SOURCES = scan_nut.c scan_nut_simulation.c scan_ipmi.c \ nutscan-device.c nutscan-ip.c nutscan-display.c \ nutscan-init.c scan_usb.c scan_snmp.c scan_xml_http.c \ - scan_avahi.c scan_eaton_serial.c nutscan-serial.c + scan_avahi.c scan_eaton_serial.c nutscan-serial.c \ + scan_upower.c libnutscan_la_LIBADD = $(NETLIBS) libnutscan_la_LIBADD += $(top_builddir)/drivers/libserial-nutscan.la @@ -215,6 +216,9 @@ endif WITH_AVAHI if WITH_IPMI libnutscan_la_CFLAGS += $(LIBIPMI_CFLAGS) endif WITH_IPMI +if WITH_UPOWER + libnutscan_la_CFLAGS += $(LIBGLIB_CFLAGS) +endif WITH_UPOWER # C is not a header, but there is no dist_noinst_SOURCES dist_noinst_HEADERS += $(NUT_SCANNER_DEPS_H) $(NUT_SCANNER_DEPS_C) diff --git a/tools/nut-scanner/nut-scan.h b/tools/nut-scanner/nut-scan.h index 3d66ba12e8..bf1925d919 100644 --- a/tools/nut-scanner/nut-scan.h +++ b/tools/nut-scanner/nut-scan.h @@ -208,6 +208,8 @@ nutscan_device_t * nutscan_scan_ip_range_ipmi(nutscan_ip_range_list_t * irl, nut nutscan_device_t * nutscan_scan_eaton_serial(const char* ports_list); +nutscan_device_t * nutscan_scan_upower(void); + #ifdef HAVE_PTHREAD # if (defined HAVE_SEMAPHORE_UNNAMED) || (defined HAVE_SEMAPHORE_NAMED) /* Expose shared libnutscan semaphore for overall thread count diff --git a/tools/nut-scanner/nut-scanner.c b/tools/nut-scanner/nut-scanner.c index d6587484ea..e8b485cf6a 100644 --- a/tools/nut-scanner/nut-scanner.c +++ b/tools/nut-scanner/nut-scanner.c @@ -92,7 +92,7 @@ #define ERR_BAD_OPTION (-1) -static const char optstring[] = "?ht:T:s:e:E:c:l:u:W:X:w:x:p:b:B:d:L:CUSMOAm:QnNPqIVaD"; +static const char optstring[] = "?ht:T:s:e:E:c:l:u:W:X:w:x:p:b:B:d:L:CUSMOAm:QnNPqIVaDJ"; #ifdef HAVE_GETOPT_LONG static const struct option longopts[] = { @@ -122,6 +122,7 @@ static const struct option longopts[] = { { "avahi_scan", no_argument, NULL, 'A' }, /* "new" NUT scan where deployed */ { "nut_simulation_scan", no_argument, NULL, 'n' }, { "ipmi_scan", no_argument, NULL, 'I' }, + { "upower_scan", no_argument, NULL, 'J' }, { "disp_nut_conf_with_sanity_check", no_argument, NULL, 'Q' }, { "disp_nut_conf", no_argument, NULL, 'N' }, { "disp_parsable", no_argument, NULL, 'P' }, @@ -280,6 +281,14 @@ static void * run_eaton_serial(void *arg) return NULL; } +static void * run_upower(void *arg) +{ + NUT_UNUSED_VARIABLE(arg); + + dev[TYPE_UPOWER] = nutscan_scan_upower(); + return NULL; +} + static void handle_arg_cidr(const char *arg_addr, int *auto_nets_ptr) { char *start_ip = NULL, *end_ip = NULL; @@ -1007,6 +1016,11 @@ static void show_usage(const char *arg_progname) } else { printf("* Options for IPMI devices scan not enabled: library not detected.\n"); } + if (nutscan_avail_upower) { + printf(" -J, --upower_scan: Scan UPower devices.\n"); + } else { + printf("* Options for UPower devices scan not enabled: library not detected.\n"); + } printf(" -E, --eaton_serial : Scan serial Eaton devices (XCP, SHUT and Q1).\n"); @@ -1175,6 +1189,7 @@ int main(int argc, char *argv[]) int allow_nut_simulation = 0; int allow_avahi = 0; int allow_ipmi = 0; + int allow_upower = 0; int allow_eaton_serial = 0; /* MUST be requested explicitly! */ int quiet = 0; /* The debugging level for certain upsdebugx() progress messages; 0 = print always, quiet==1 is to require at least one -D */ void (*display_func)(nutscan_device_t * device); @@ -1533,6 +1548,12 @@ int main(int argc, char *argv[]) } allow_ipmi = 1; break; + case 'J': + if (!nutscan_avail_upower) { + goto display_help; + } + allow_upower = 1; + break; case 'Q': display_func = nutscan_display_ups_conf_with_sanity_check; break; @@ -1568,6 +1589,9 @@ int main(int argc, char *argv[]) if (nutscan_avail_ipmi) { printf("IPMI\n"); } + if (nutscan_avail_upower) { + printf("UPOWER\n"); + } printf("EATON_SERIAL\n"); exit(EXIT_SUCCESS); case '?': @@ -1674,7 +1698,7 @@ int main(int argc, char *argv[]) } if (!allow_usb && !allow_snmp && !allow_xml && !allow_oldnut && !allow_nut_simulation && - !allow_avahi && !allow_ipmi && !allow_eaton_serial + !allow_avahi && !allow_ipmi && !allow_eaton_serial && !allow_upower ) { allow_all = 1; } @@ -1692,6 +1716,7 @@ int main(int argc, char *argv[]) allow_nut_simulation = 1; allow_avahi = 1; allow_ipmi = 1; + allow_upower = 1; /* BEWARE: allow_all does not include allow_eaton_serial! */ } @@ -1840,6 +1865,22 @@ int main(int argc, char *argv[]) upsdebugx(1, "IPMI SCAN: not requested or supported, SKIPPED"); } + if (allow_upower && nutscan_avail_upower) { + upsdebugx(quiet, "Scanning UPower bus."); +#ifdef HAVE_PTHREAD + upsdebugx(1, "UPOWER SCAN: starting pthread_create with run_upower..."); + if (pthread_create(&thread[TYPE_UPOWER], NULL, run_upower, NULL)) { + upsdebugx(1, "pthread_create returned an error; disabling this scan mode"); + nutscan_avail_upower = 0; + } +#else + upsdebugx(1, "UPOWER SCAN: no pthread support, starting nutscan_scan_upower..."); + run_upower(NULL); +#endif /* HAVE_PTHREAD */ + } else { + upsdebugx(1, "UPOWER SCAN: not requested or supported, SKIPPED"); + } + /* Eaton serial scan */ if (allow_eaton_serial) { upsdebugx(quiet, "Scanning serial bus for Eaton devices."); @@ -1887,6 +1928,10 @@ int main(int argc, char *argv[]) upsdebugx(1, "IPMI SCAN: join back the pthread"); pthread_join(thread[TYPE_IPMI], NULL); } + if (allow_upower && nutscan_avail_upower && thread[TYPE_UPOWER]) { + upsdebugx(1, "UPOWER SCAN: join back the pthread"); + pthread_join(thread[TYPE_UPOWER], NULL); + } if (allow_eaton_serial && thread[TYPE_EATON_SERIAL]) { upsdebugx(1, "SERIAL SCAN: join back the pthread"); pthread_join(thread[TYPE_EATON_SERIAL], NULL); @@ -1930,6 +1975,11 @@ int main(int argc, char *argv[]) upsdebugx(1, "SCANS DONE: free resources: IPMI"); nutscan_free_device(dev[TYPE_IPMI]); + upsdebugx(1, "SCANS DONE: display results: UPOWER"); + display_func(dev[TYPE_UPOWER]); + upsdebugx(1, "SCANS DONE: free resources: UPOWER"); + nutscan_free_device(dev[TYPE_UPOWER]); + upsdebugx(1, "SCANS DONE: display results: SERIAL"); display_func(dev[TYPE_EATON_SERIAL]); upsdebugx(1, "SCANS DONE: free resources: SERIAL"); diff --git a/tools/nut-scanner/nutscan-device.c b/tools/nut-scanner/nutscan-device.c index 7f57cf9638..b0b9cf6f32 100644 --- a/tools/nut-scanner/nutscan-device.c +++ b/tools/nut-scanner/nutscan-device.c @@ -41,6 +41,7 @@ const char * nutscan_device_type_strings[TYPE_END] = { "IPMI", "Avahi", "serial", + "UPOWER", }; /* lower strings, used for device names */ @@ -54,6 +55,7 @@ const char * nutscan_device_type_lstrings[TYPE_END] = { "ipmi", "avahi", "serial", + "upower", }; nutscan_device_t * nutscan_new_device(void) diff --git a/tools/nut-scanner/nutscan-device.h b/tools/nut-scanner/nutscan-device.h index 2e536c7294..c969f1f755 100644 --- a/tools/nut-scanner/nutscan-device.h +++ b/tools/nut-scanner/nutscan-device.h @@ -55,6 +55,7 @@ typedef enum nutscan_device_type { TYPE_IPMI, TYPE_AVAHI, TYPE_EATON_SERIAL, + TYPE_UPOWER, TYPE_END /* Sentinel; numeric value serves as array size at compile time */ } nutscan_device_type_t; diff --git a/tools/nut-scanner/nutscan-init.c b/tools/nut-scanner/nutscan-init.c index 5570c5417e..4b0f622f0c 100644 --- a/tools/nut-scanner/nutscan-init.c +++ b/tools/nut-scanner/nutscan-init.c @@ -58,6 +58,7 @@ int nutscan_avail_nut_simulation = 0; int nutscan_avail_snmp = 0; int nutscan_avail_usb = 0; int nutscan_avail_xml_http = 0; +int nutscan_avail_upower = 0; /* Methods defined in scan_*.c source files */ int nutscan_load_usb_library(const char *libname_path); @@ -72,6 +73,8 @@ int nutscan_load_ipmi_library(const char *libname_path); int nutscan_unload_ipmi_library(void); int nutscan_load_upsclient_library(const char *libname_path); int nutscan_unload_upsclient_library(void); +int nutscan_load_upower_library(const char *libname_path); +int nutscan_unload_upower_library(void); #ifdef HAVE_PTHREAD # ifdef HAVE_SEMAPHORE_UNNAMED @@ -532,6 +535,53 @@ void nutscan_init(void) __func__, "LibAvahi"); #endif /* WITH_AVAHI */ +#if (defined WITH_UPOWER) && WITH_UPOWER +# ifdef SOFILE_LIBGLIB + if (!libname) { + libname = get_libname(SOFILE_LIBGLIB); + } +# endif /* SOFILE_LIBGLIB */ + if (!libname) { + libname = get_libname("libgio-2.0" SOEXT); + } +# ifdef SOPATH_LIBGLIB + if (!libname) { + libname = get_libname(SOPATH_LIBGLIB); + } +# endif /* SOPATH_LIBGLIB */ + + if (libname) { + upsdebugx(1, "%s: get_libname() resolved '%s' for %s, loading it", + __func__, libname, "LibGIO"); + nutscan_avail_upower = nutscan_load_upower_library(libname); + free(libname); + libname = NULL; + } else { + /* let libtool (lt_dlopen) do its default magic maybe better */ + upsdebugx(1, "%s: get_libname() did not resolve libname for %s, " + "trying to load it with libtool default resolver", + __func__, "LibGIO"); +# ifdef SOFILE_LIBGLIB + if (!nutscan_avail_upower) { + nutscan_avail_upower = nutscan_load_upower_library(SOFILE_LIBGLIB); + } +# endif /* SOFILE_LIBGLIB */ + if (!nutscan_avail_upower) { + nutscan_avail_upower = nutscan_load_upower_library("libgio-2.0" SOEXT); + } +# ifdef SOPATH_LIBGLIB + if (!nutscan_avail_upower) { + nutscan_avail_upower = nutscan_load_upower_library(SOPATH_LIBGLIB); + } +# endif /* SOPATH_LIBGLIB */ + } + upsdebugx(1, "%s: %s to load the library for %s", + __func__, nutscan_avail_upower ? "succeeded" : "failed", "LibGIO"); +#else /* not WITH_UPOWER */ + upsdebugx(1, "%s: skipped loading the library for %s: was absent during NUT build", + __func__, "LibGIO"); +#endif /* WITH_UPOWER */ + #if (defined WITH_FREEIPMI) && WITH_FREEIPMI # ifdef SOFILE_LIBFREEIPMI if (!libname) { @@ -703,6 +753,7 @@ void nutscan_free(void) nutscan_unload_avahi_library(); nutscan_unload_ipmi_library(); nutscan_unload_upsclient_library(); + nutscan_unload_upower_library(); #ifdef HAVE_PTHREAD /* TOTHINK: See comments near mutex/semaphore init code above */ diff --git a/tools/nut-scanner/nutscan-init.h b/tools/nut-scanner/nutscan-init.h index b9531b1cdc..b8306c50f8 100644 --- a/tools/nut-scanner/nutscan-init.h +++ b/tools/nut-scanner/nutscan-init.h @@ -39,6 +39,7 @@ extern int nutscan_avail_nut_simulation; extern int nutscan_avail_snmp; extern int nutscan_avail_usb; extern int nutscan_avail_xml_http; +extern int nutscan_avail_upower; void nutscan_init(void); void nutscan_free(void); diff --git a/tools/nut-scanner/scan_upower.c b/tools/nut-scanner/scan_upower.c new file mode 100644 index 0000000000..80d5028bb6 --- /dev/null +++ b/tools/nut-scanner/scan_upower.c @@ -0,0 +1,303 @@ +/* + * Copyright (C) 2026 Tim Niemueller + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/*! \file scan_upower.c + \brief detect NUT supported devices via UPower (GDBus/GIO) + \author Tim Niemueller +*/ + +#include "common.h" +#include "nut-scan.h" + +/* externally visible to nutscan-init */ +int nutscan_unload_upower_library(void); +/* externally visible to nut-scanner */ +nutscan_device_t * nutscan_scan_upower(void); + +#ifdef WITH_UPOWER + +#include +#include +#include +#include +#include + +/* dynamic link library stuff */ +static lt_dlhandle dl_handle = NULL; +static const char *dl_error = NULL; +static char *dl_saved_libname = NULL; + +/* Function pointers */ +static GDBusConnection * (*nut_g_bus_get_sync)(GBusType bus_type, GCancellable *cancellable, GError **error); +static GDBusProxy * (*nut_g_dbus_proxy_new_sync)(GDBusConnection *connection, GDBusProxyFlags flags, GDBusInterfaceInfo *info, const gchar *name, const gchar *object_path, const gchar *interface_name, GCancellable *cancellable, GError **error); +static GVariant * (*nut_g_dbus_proxy_call_sync)(GDBusProxy *proxy, const gchar *method_name, GVariant *parameters, GDBusCallFlags flags, gint timeout_msec, GCancellable *cancellable, GError **error); +static GVariant * (*nut_g_dbus_proxy_get_cached_property)(GDBusProxy *proxy, const gchar *property_name); +static void (*nut_g_variant_get)(GVariant *value, const gchar *format_string, ...); +static void (*nut_g_variant_unref)(GVariant *value); +static void (*nut_g_object_unref)(gpointer object); +static void (*nut_g_error_free)(GError *error); +static const gchar * (*nut_g_variant_get_string)(GVariant *value, gsize *length); +static gboolean (*nut_g_variant_iter_next)(GVariantIter *iter, const gchar *format_string, ...); +static gsize (*nut_g_variant_iter_init)(GVariantIter *iter, GVariant *value); +static guint32 (*nut_g_variant_get_uint32)(GVariant *value); +static GVariant * (*nut_g_variant_get_child_value)(GVariant *value, gsize index_); + +/* Return 0 on success, -1 on error e.g. "was not loaded"; + * other values may be possible if lt_dlclose() errors set them; + * visible externally */ +int nutscan_unload_library(int *avail, lt_dlhandle *pdl_handle, char **libpath); +int nutscan_unload_upower_library(void) +{ + return nutscan_unload_library(&nutscan_avail_upower, &dl_handle, &dl_saved_libname); +} + +/* Return 0 on error; visible externally */ +int nutscan_load_upower_library(const char *libname_path); +int nutscan_load_upower_library(const char *libname_path) +{ + if (dl_handle != NULL) { + /* if previous init failed */ + if (dl_handle == (void *)1) { + return 0; + } + /* init has already been done */ + return 1; + } + + if (libname_path == NULL) { + upsdebugx(0, "GIO library not found. UPower search disabled."); + return 0; + } + + if (lt_dlinit() != 0) { + upsdebugx(0, "%s: Error initializing lt_dlinit", __func__); + return 0; + } + + dl_handle = lt_dlopen(libname_path); + if (!dl_handle) { + dl_error = lt_dlerror(); + goto err; + } + + /* Clear any existing error */ + lt_dlerror(); + + *(void **) (&nut_g_bus_get_sync) = lt_dlsym(dl_handle, "g_bus_get_sync"); + if ((dl_error = lt_dlerror()) != NULL) goto err; + + *(void **) (&nut_g_dbus_proxy_new_sync) = lt_dlsym(dl_handle, "g_dbus_proxy_new_sync"); + if ((dl_error = lt_dlerror()) != NULL) goto err; + + *(void **) (&nut_g_dbus_proxy_call_sync) = lt_dlsym(dl_handle, "g_dbus_proxy_call_sync"); + if ((dl_error = lt_dlerror()) != NULL) goto err; + + *(void **) (&nut_g_dbus_proxy_get_cached_property) = lt_dlsym(dl_handle, "g_dbus_proxy_get_cached_property"); + if ((dl_error = lt_dlerror()) != NULL) goto err; + + *(void **) (&nut_g_variant_get) = lt_dlsym(dl_handle, "g_variant_get"); + if ((dl_error = lt_dlerror()) != NULL) goto err; + + *(void **) (&nut_g_variant_unref) = lt_dlsym(dl_handle, "g_variant_unref"); + if ((dl_error = lt_dlerror()) != NULL) goto err; + + *(void **) (&nut_g_object_unref) = lt_dlsym(dl_handle, "g_object_unref"); + if ((dl_error = lt_dlerror()) != NULL) goto err; + + *(void **) (&nut_g_error_free) = lt_dlsym(dl_handle, "g_error_free"); + if ((dl_error = lt_dlerror()) != NULL) goto err; + + *(void **) (&nut_g_variant_get_string) = lt_dlsym(dl_handle, "g_variant_get_string"); + if ((dl_error = lt_dlerror()) != NULL) goto err; + + *(void **) (&nut_g_variant_iter_next) = lt_dlsym(dl_handle, "g_variant_iter_next"); + if ((dl_error = lt_dlerror()) != NULL) goto err; + + *(void **) (&nut_g_variant_iter_init) = lt_dlsym(dl_handle, "g_variant_iter_init"); + if ((dl_error = lt_dlerror()) != NULL) goto err; + + *(void **) (&nut_g_variant_get_uint32) = lt_dlsym(dl_handle, "g_variant_get_uint32"); + if ((dl_error = lt_dlerror()) != NULL) goto err; + + *(void **) (&nut_g_variant_get_child_value) = lt_dlsym(dl_handle, "g_variant_get_child_value"); + if ((dl_error = lt_dlerror()) != NULL) goto err; + + if (dl_saved_libname) + free(dl_saved_libname); + dl_saved_libname = xstrdup(libname_path); + + return 1; + +err: + upsdebugx(0, + "Cannot load GIO library (%s) : %s. UPower search disabled.", + libname_path, dl_error); + dl_handle = (void *)1; + lt_dlexit(); + if (dl_saved_libname) { + free(dl_saved_libname); + dl_saved_libname = NULL; + } + return 0; +} + +nutscan_device_t * nutscan_scan_upower(void) +{ + GError *error = NULL; + GDBusConnection *connection; + GDBusProxy *proxy_upower = NULL; + GVariant *result = NULL; + GVariantIter iter; + gchar *object_path; + nutscan_device_t * dev_ret = NULL; + + if (!nutscan_avail_upower) { + return NULL; + } + + connection = (*nut_g_bus_get_sync)(G_BUS_TYPE_SYSTEM, NULL, &error); + if (connection == NULL) { + upsdebugx(1, "Error connecting to system bus: %s", error->message); + (*nut_g_error_free)(error); + return NULL; + } + + proxy_upower = (*nut_g_dbus_proxy_new_sync)(connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + "org.freedesktop.UPower", + "/org/freedesktop/UPower", + "org.freedesktop.UPower", + NULL, + &error); + + if (proxy_upower == NULL) { + upsdebugx(1, "Error creating UPower proxy: %s", error->message); + (*nut_g_error_free)(error); + (*nut_g_object_unref)(connection); + return NULL; + } + + result = (*nut_g_dbus_proxy_call_sync)(proxy_upower, + "EnumerateDevices", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (result == NULL) { + upsdebugx(1, "Error enumerating devices: %s", error->message); + (*nut_g_error_free)(error); + (*nut_g_object_unref)(proxy_upower); + (*nut_g_object_unref)(connection); + return NULL; + } + + /* Result is (ao) - array of object paths */ + GVariant *child = (*nut_g_variant_get_child_value)(result, 0); + (*nut_g_variant_iter_init)(&iter, child); + + while ((*nut_g_variant_iter_next)(&iter, "o", &object_path)) { + GDBusProxy *proxy_device; + GVariant *v_type, *v_model, *v_vendor, *v_serial, *v_native_path; + nutscan_device_t * dev; + + proxy_device = (*nut_g_dbus_proxy_new_sync)(connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + "org.freedesktop.UPower", + object_path, + "org.freedesktop.UPower.Device", + NULL, + &error); + + if (proxy_device == NULL) { + upsdebugx(1, "Error creating device proxy for %s: %s", object_path, error->message); + (*nut_g_error_free)(error); + free(object_path); + continue; + } + + /* Check Type property: 2 is Battery, 3 is UPS */ + v_type = (*nut_g_dbus_proxy_get_cached_property)(proxy_device, "Type"); + if (v_type) { + guint32 type = (*nut_g_variant_get_uint32)(v_type); + (*nut_g_variant_unref)(v_type); + + if (type == 2 || type == 3) { /* Battery or UPS */ + dev = nutscan_new_device(); + dev->type = TYPE_UPOWER; + dev->driver = strdup("upower"); + dev->port = strdup(object_path); + + v_vendor = (*nut_g_dbus_proxy_get_cached_property)(proxy_device, "Vendor"); + if (v_vendor) { + nutscan_add_option_to_device(dev, "vendor", (char*)(*nut_g_variant_get_string)(v_vendor, NULL)); + (*nut_g_variant_unref)(v_vendor); + } + + v_model = (*nut_g_dbus_proxy_get_cached_property)(proxy_device, "Model"); + if (v_model) { + nutscan_add_option_to_device(dev, "product", (char*)(*nut_g_variant_get_string)(v_model, NULL)); + (*nut_g_variant_unref)(v_model); + } + + v_serial = (*nut_g_dbus_proxy_get_cached_property)(proxy_device, "Serial"); + if (v_serial) { + nutscan_add_option_to_device(dev, "serial", (char*)(*nut_g_variant_get_string)(v_serial, NULL)); + (*nut_g_variant_unref)(v_serial); + } + + v_native_path = (*nut_g_dbus_proxy_get_cached_property)(proxy_device, "NativePath"); + if (v_native_path) { + nutscan_add_option_to_device(dev, "native_path", (char*)(*nut_g_variant_get_string)(v_native_path, NULL)); + (*nut_g_variant_unref)(v_native_path); + } + + nutscan_add_option_to_device(dev, "bus", "upower"); + + dev_ret = nutscan_add_device_to_device(dev_ret, dev); + } + } + + (*nut_g_object_unref)(proxy_device); + free(object_path); + } + + (*nut_g_variant_unref)(child); + (*nut_g_variant_unref)(result); + (*nut_g_object_unref)(proxy_upower); + (*nut_g_object_unref)(connection); + + return nutscan_rewind_device(dev_ret); +} + +#else /* not WITH_UPOWER */ + +nutscan_device_t * nutscan_scan_upower(void) +{ + return NULL; +} + +int nutscan_unload_upower_library(void) +{ + return 0; +} + +#endif /* WITH_UPOWER */ From a6ed5f02752dad5eda0bcf689bfe00217afa644f Mon Sep 17 00:00:00 2001 From: Tim Niemueller Date: Sat, 31 Jan 2026 12:54:42 +0100 Subject: [PATCH 085/198] Add entry to NEWS.adoc for nut-scanner upower support Signed-off-by: Tim Niemueller --- NEWS.adoc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS.adoc b/NEWS.adoc index 2fb1339723..d660c1cee2 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -221,6 +221,8 @@ https://github.com/networkupstools/nut/milestone/12 via D-Bus. This also introduces a new category of drivers that talk to operating system services to obtain power state information. [PR #3279] + - Introduced a nut-scanner support for new `nut-upower` driver. [PR #3293] + - `usbhid-ups` driver updates: * Declared support for APC with USB ID `051d:0005` (details may evolve as the devices become better known). [issue #3047, PR #3081] From beef994314c4693514510bbc588213a8d6130185 Mon Sep 17 00:00:00 2001 From: Tim Niemueller Date: Sat, 31 Jan 2026 13:06:45 +0100 Subject: [PATCH 086/198] Variable ordering fix Pretend it's 1999 and put declaration of the variable further up. Signed-off-by: Tim Niemueller --- tools/nut-scanner/scan_upower.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/nut-scanner/scan_upower.c b/tools/nut-scanner/scan_upower.c index 80d5028bb6..62e4d6a79c 100644 --- a/tools/nut-scanner/scan_upower.c +++ b/tools/nut-scanner/scan_upower.c @@ -162,6 +162,7 @@ nutscan_device_t * nutscan_scan_upower(void) GDBusConnection *connection; GDBusProxy *proxy_upower = NULL; GVariant *result = NULL; + GVariant *child = NULL; GVariantIter iter; gchar *object_path; nutscan_device_t * dev_ret = NULL; @@ -210,7 +211,7 @@ nutscan_device_t * nutscan_scan_upower(void) } /* Result is (ao) - array of object paths */ - GVariant *child = (*nut_g_variant_get_child_value)(result, 0); + child = (*nut_g_variant_get_child_value)(result, 0); (*nut_g_variant_iter_init)(&iter, child); while ((*nut_g_variant_iter_next)(&iter, "o", &object_path)) { From 26b26c6fa30e4d00cadebf4964cdd76cc02fed39 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 1 Feb 2026 00:11:37 +0100 Subject: [PATCH 087/198] configure.ac, m4/nut_check_libglib.m4, Makefiles: clearer name and user (and hack) the variables for libglib and for libgio [#3293] Signed-off-by: Jim Klimov --- configure.ac | 73 +++---------- docs/man/Makefile.am | 8 +- drivers/Makefile.am | 8 +- m4/nut_check_libglib.m4 | 181 +++++++++++++++++++++++++++---- tools/nut-scanner/Makefile.am | 2 +- tools/nut-scanner/nutscan-init.c | 24 ++-- 6 files changed, 198 insertions(+), 98 deletions(-) diff --git a/configure.ac b/configure.ac index ac52e3eeda..ee36725c23 100644 --- a/configure.ac +++ b/configure.ac @@ -3163,70 +3163,27 @@ NUT_REPORT_DRIVER([build Mac OS X meta-driver], [WITH_MACOSX], [Define to enable Mac OS X meta-driver]) dnl ---------------------------------------------------------------------- -dnl Check for libGLib / libGIO (Required for UPower driver) +dnl Check if we have detected libGLib / libGIO above (Required for UPower driver) dnl NOTE: Do not confuse libglib{2} (GNOME) with glibc (part of compiler) dnl ---------------------------------------------------------------------- -have_glib=no - -AS_IF([test "${with_upower}" != "no"], [ - AS_IF([test x"$have_PKG_CONFIG" = xyes], - [ifdef([PKG_CHECK_MODULES], - [PKG_CHECK_MODULES(GLIB, [glib-2.0 gio-2.0], [have_glib=yes], [have_glib=no])], - [have_glib=no]) - ], - [AC_MSG_WARN([pkg-config not found, cannot look properly for glib-2.0/gio-2.0])] - ) -]) - -AS_IF([test "${have_glib}" = "yes"], [ - AC_DEFINE(HAVE_GLIB, 1, [Define to 1 if GLib and GIO are available]) - - dnl GLib headers seem incorrect and offensive to many compilers - dnl (starting names with underscores and capital characters, - dnl varying support for attributes, method pointer mismatches). - dnl There is nothing NUT can do about it, except telling the - dnl compiler that we take these headers from the system as they - dnl are, so strict checks should not apply to them. - dnl On newer releases (2025+) the headers and CLANG seem to work - dnl together out of the box, but during the decade before this is - dnl troublesome. - AS_IF([test "${CLANGCC}" = "yes" || test "${GCC}" = "yes"], [ - myGLIB_CFLAGS="" - for TOKEN in ${GLIB_CFLAGS} ; do - AS_CASE(["${TOKEN}"], - [-I/*], [ - _IDIR="`echo \"${TOKEN}\" | sed 's/^-I//'`" - AS_IF([echo " ${GLIB_CFLAGS}" | ${EGREP} " -isystem *${_IDIR}" >/dev/null], - [myGLIB_CFLAGS="${myGLIB_CFLAGS} ${TOKEN}"], - [myGLIB_CFLAGS="${myGLIB_CFLAGS} -isystem ${_IDIR} ${TOKEN}"] - )], - [myGLIB_CFLAGS="${myGLIB_CFLAGS} ${TOKEN}"] - ) - done - unset TOKEN - unset _IDIR - myGLIB_CFLAGS="`echo \"${myGLIB_CFLAGS}\" | sed 's/^ *//'`" - - AS_IF([test x"${GLIB_CFLAGS}" != x -a x"${GLIB_CFLAGS}" != x"${myGLIB_CFLAGS}"], [ - AC_MSG_NOTICE([Patched libglib/libgio CFLAGS to declare -isystem]) - AS_IF([test x"${nut_enable_configure_debug}" = xyes], [ - AC_MSG_NOTICE([(CONFIGURE-DEVEL-DEBUG) old: ${GLIB_CFLAGS}]) - AC_MSG_NOTICE([(CONFIGURE-DEVEL-DEBUG) new: ${myGLIB_CFLAGS}]) - ]) - GLIB_CFLAGS="${myGLIB_CFLAGS}" - ]) - unset myGLIB_CFLAGS - ]) +AC_MSG_CHECKING([whether to build nut-upower driver]) +nut_with_upower=no +AS_IF([test "${nut_have_libglib}${nut_have_libgio}" = "yesyes"], [ + AS_CASE(["${with_upower}"], + [yes|auto], [nut_with_upower=yes] + ) ], [ - AS_CASE(["${with_upower}"], - [yes], [AC_MSG_ERROR([GLib/GIO not found but requested via --with-upower])], - [auto],[AC_MSG_WARN([GLib/GIO not found. The 'upower' driver will not be built.])] - ) + AS_CASE(["${with_upower}"], + [yes], [AC_MSG_ERROR([GLib/GIO not found but requested via --with-upower])], + [auto],[AC_MSG_WARN([GLib/GIO not found. The 'upower' driver will not be built.])] + ) ]) -AM_CONDITIONAL(HAVE_GLIB, test "${have_glib}" = "yes") -AC_MSG_RESULT(${have_glib}) +AC_MSG_RESULT(${nut_with_upower}) +NUT_REPORT_DRIVER([build UPower driver], + [${nut_with_upower}], [], + [WITH_UPOWER], [Define to build UPower driver]) dnl ---------------------------------------------------------------------- dnl checks related to --with_linux_i2c diff --git a/docs/man/Makefile.am b/docs/man/Makefile.am index 98d87c4adc..8ad5c11ac0 100644 --- a/docs/man/Makefile.am +++ b/docs/man/Makefile.am @@ -1473,9 +1473,9 @@ if WITH_MANS MAN_UPOWER_PAGES = $(INST_MAN_UPOWER_PAGES) endif WITH_MANS -if HAVE_GLIB +if WITH_UPOWER mansys_DATA += $(MAN_UPOWER_PAGES) -endif HAVE_GLIB +endif WITH_UPOWER endif ! SOME_DRIVERS INST_HTML_UPOWER_MANS = \ @@ -1488,9 +1488,9 @@ endif ! SOME_DRIVERS # FIXME? Refine for HTML etc.? if DOC_INSTALL_SELECTED_MANS_PROGS_BUILT -if HAVE_GLIB +if WITH_UPOWER LINKMAN_PAGES_DRIVERS += $(SRC_UPOWER_PAGES) -endif HAVE_GLIB +endif WITH_UPOWER else !DOC_INSTALL_SELECTED_MANS_PROGS_BUILT LINKMAN_PAGES_DRIVERS += $(SRC_UPOWER_PAGES) endif !DOC_INSTALL_SELECTED_MANS_PROGS_BUILT diff --git a/drivers/Makefile.am b/drivers/Makefile.am index db6b148702..ac6cd671db 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -367,14 +367,14 @@ mge_shut_CFLAGS = $(AM_CFLAGS) -DSHUT_MODE=1 mge_shut_LDADD = $(LDADD_DRIVERS_SERIAL) -lm # UPower -if HAVE_GLIB +if WITH_UPOWER # Only build nut-upower if the set of libGLib/libGIO was found driverexec_PROGRAMS += $(UPOWER_DRIVERLIST) nut_upower_SOURCES = nut-upower.c - nut_upower_LDADD = $(LDADD_DRIVERS) $(GLIB_LIBS) - nut_upower_CFLAGS = $(AM_CFLAGS) $(GLIB_CFLAGS) -endif + nut_upower_LDADD = $(LDADD_DRIVERS) $(LIBGLIB_LIBS) $(LIBGIO_LIBS) + nut_upower_CFLAGS = $(AM_CFLAGS) $(LIBGLIB_CFLAGS) $(LIBGIO_CFLAGS) +endif WITH_UPOWER # SNMP # Please keep the MIB table below sorted roughly alphabetically (incidentally diff --git a/m4/nut_check_libglib.m4 b/m4/nut_check_libglib.m4 index be30fd5e59..d2328067f1 100644 --- a/m4/nut_check_libglib.m4 +++ b/m4/nut_check_libglib.m4 @@ -1,7 +1,9 @@ -dnl Check for LIBGLIB compiler flags. On success, set nut_have_libglib="yes" -dnl and set LIBGLIB_CFLAGS and LIBGLIB_LIBS. On failure, set -dnl nut_have_libglib="no". This macro can be run multiple times, but will -dnl do the checking only once. +dnl Check for LIBGLIB (used by nut-upower driver) and related LIBGIO (optionally +dnl used by nut-scanner) compiler and linker flags. +dnl On success, set nut_have_libglib="yes" and set LIBGLIB_CFLAGS and LIBGLIB_LIBS. +dnl On failure, set nut_have_libglib="no". +dnl Similarly for LIBGIO_FLAGS, LIBGIO_LIBS and nut_have_libgio. +dnl This macro can be run multiple times, but will do the checking only once. AC_DEFUN([NUT_CHECK_LIBGLIB], [ @@ -21,12 +23,122 @@ if test -z "${nut_have_libglib_seen}"; then AS_IF([test x"$have_PKG_CONFIG" = xyes], [dnl See which version of the glib/gio library (if any) is installed - AC_MSG_CHECKING(for gio-2.0 version via pkg-config (2.26.0 minimum required)) - LIBGLIB_VERSION="`$PKG_CONFIG --silence-errors --modversion gio-2.0 2>/dev/null`" + AC_MSG_CHECKING(for glib-2.0 version via pkg-config (2.26.0 minimum required)) + LIBGLIB_VERSION="`$PKG_CONFIG --silence-errors --modversion glib-2.0 2>/dev/null`" if test "$?" != "0" -o -z "${LIBGLIB_VERSION}"; then LIBGLIB_VERSION="none" fi AC_MSG_RESULT(${LIBGLIB_VERSION} found) + ], [AC_MSG_NOTICE([can not check glib-2.0 settings via pkg-config])] + ) + + AC_MSG_CHECKING(for glib-2.0 cflags) + NUT_ARG_WITH_LIBOPTS_INCLUDES([glib], [auto]) + AS_CASE([${nut_with_glib_includes}], + [auto], [AS_IF([test x"$have_PKG_CONFIG" = xyes], + [ { depCFLAGS="`$PKG_CONFIG --silence-errors --cflags glib-2.0 2>/dev/null`" \ + && depCFLAGS_SOURCE="pkg-config" ; } \ + || { depCFLAGS="-I/usr/local/include/glib-2.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include" \ + && depCFLAGS_SOURCE="default" ; }], + [depCFLAGS="-I/usr/local/include/glib-2.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include" + depCFLAGS_SOURCE="default"] + )], + [depCFLAGS="${nut_with_glib_includes}" + depCFLAGS_SOURCE="confarg"] + ) + AC_MSG_RESULT([${depCFLAGS} (source: ${depCFLAGS_SOURCE})]) + + AC_MSG_CHECKING(for glib-2.0 ldflags) + NUT_ARG_WITH_LIBOPTS_LIBS([glib], [auto]) + AS_CASE([${nut_with_glib_libs}], + [auto], [AS_IF([test x"$have_PKG_CONFIG" = xyes], + [ { depLIBS="`$PKG_CONFIG --silence-errors --libs glib-2.0 2>/dev/null`" \ + && depLIBS_SOURCE="pkg-config" ; } \ + || { depLIBS="-lgobject-2.0 -lglib-2.0" \ + && depLIBS_SOURCE="default" ; }], + [depLIBS="-lgobject-2.0 -lglib-2.0" + depLIBS_SOURCE="default"] + )], + [depLIBS="${nut_with_glib_libs}" + depLIBS_SOURCE="confarg"] + ) + AC_MSG_RESULT([${depLIBS} (source: ${depLIBS_SOURCE})]) + + dnl check if glib-2.0 is usable + CFLAGS="${CFLAGS_ORIG} ${depCFLAGS}" + LIBS="${LIBS_ORIG} ${depLIBS}" + AC_CHECK_HEADERS(glib.h, [nut_have_libglib=yes], [nut_have_libglib=no], [AC_INCLUDES_DEFAULT]) + + if test "${nut_have_libglib}" = "yes"; then + LIBGLIB_CFLAGS="${depCFLAGS}" + LIBGLIB_LIBS="${depLIBS}" + + dnl GLib headers seem incorrect and offensive to many compilers + dnl (starting names with underscores and capital characters, + dnl varying support for attributes, method pointer mismatches). + dnl There is nothing NUT can do about it, except telling the + dnl compiler that we take these headers from the system as they + dnl are, so strict checks should not apply to them. + dnl On newer releases (2025+) the headers and CLANG seem to work + dnl together out of the box, but during the decade before this is + dnl troublesome. + AS_IF([test "${CLANGCC}" = "yes" || test "${GCC}" = "yes"], [ + myGLIB_CFLAGS="" + for TOKEN in ${LIBGLIB_CFLAGS} ; do + AS_CASE(["${TOKEN}"], + [-I/*], [ + _IDIR="`echo \"${TOKEN}\" | sed 's/^-I//'`" + AS_IF([echo " ${LIBGLIB_CFLAGS}" | ${EGREP} " -isystem *${_IDIR}" >/dev/null], + [myGLIB_CFLAGS="${myGLIB_CFLAGS} ${TOKEN}"], + [myGLIB_CFLAGS="${myGLIB_CFLAGS} -isystem ${_IDIR} ${TOKEN}"] + )], + [myGLIB_CFLAGS="${myGLIB_CFLAGS} ${TOKEN}"] + ) + done + unset TOKEN + unset _IDIR + myGLIB_CFLAGS="`echo \"${myGLIB_CFLAGS}\" | sed 's/^ *//'`" + + AS_IF([test x"${LIBGLIB_CFLAGS}" != x -a x"${LIBGLIB_CFLAGS}" != x"${myGLIB_CFLAGS}"], [ + AC_MSG_NOTICE([Patched libglib CFLAGS to declare -isystem]) + AS_IF([test x"${nut_enable_configure_debug}" = xyes], [ + AC_MSG_NOTICE([(CONFIGURE-DEVEL-DEBUG) old: ${LIBGLIB_CFLAGS}]) + AC_MSG_NOTICE([(CONFIGURE-DEVEL-DEBUG) new: ${myGLIB_CFLAGS}]) + ]) + LIBGLIB_CFLAGS="${myGLIB_CFLAGS}" + ]) + unset myGLIB_CFLAGS + ]) + + dnl Help ltdl if we can (nut-scanner etc.) + for TOKEN in $depLIBS ; do + AS_CASE(["${TOKEN}"], + [-l*glib*], [ + AX_REALPATH_LIB([${TOKEN}], [SOPATH_LIBGLIB], []) + AS_IF([test -n "${SOPATH_LIBGLIB}" && test -s "${SOPATH_LIBGLIB}"], [ + AC_DEFINE_UNQUOTED([SOPATH_LIBGLIB],["${SOPATH_LIBGLIB}"],[Path to dynamic library on build system]) + SOFILE_LIBGLIB="`basename \"$SOPATH_LIBGLIB\"`" + AC_DEFINE_UNQUOTED([SOFILE_LIBGLIB],["${SOFILE_LIBGLIB}"],[Base file name of dynamic library on build system]) + break + ]) + ] + ) + done + unset TOKEN + fi + + dnl /////////////////////////////////////// + dnl // Same for libgio // + dnl /////////////////////////////////////// + + AS_IF([test x"$have_PKG_CONFIG" = xyes], + [dnl See which version of the glib/gio library (if any) is installed + AC_MSG_CHECKING(for gio-2.0 version via pkg-config (2.26.0 minimum required)) + LIBGIO_VERSION="`$PKG_CONFIG --silence-errors --modversion gio-2.0 2>/dev/null`" + if test "$?" != "0" -o -z "${LIBGIO_VERSION}"; then + LIBGIO_VERSION="none" + fi + AC_MSG_RESULT(${LIBGIO_VERSION} found) ], [AC_MSG_NOTICE([can not check gio-2.0 settings via pkg-config])] ) @@ -65,22 +177,50 @@ if test -z "${nut_have_libglib_seen}"; then dnl check if gio-2.0 is usable CFLAGS="${CFLAGS_ORIG} ${depCFLAGS}" LIBS="${LIBS_ORIG} ${depLIBS}" - AC_CHECK_HEADERS(gio/gio.h, [nut_have_libglib=yes], [nut_have_libglib=no], [AC_INCLUDES_DEFAULT]) - dnl AC_CHECK_FUNCS(g_bus_get_sync, [], [nut_have_libglib=no]) + AC_CHECK_HEADERS(gio/gio.h, [nut_have_libgio=yes], [nut_have_libgio=no], [AC_INCLUDES_DEFAULT]) + dnl AC_CHECK_FUNCS(g_bus_get_sync, [], [nut_have_libgio=no]) - if test "${nut_have_libglib}" = "yes"; then - LIBGLIB_CFLAGS="${depCFLAGS}" - LIBGLIB_LIBS="${depLIBS}" + if test "${nut_have_libgio}" = "yes"; then + LIBGIO_CFLAGS="${depCFLAGS}" + LIBGIO_LIBS="${depLIBS}" + + AS_IF([test "${CLANGCC}" = "yes" || test "${GCC}" = "yes"], [ + myGIO_CFLAGS="" + for TOKEN in ${LIBGIO_CFLAGS} ; do + AS_CASE(["${TOKEN}"], + [-I/*], [ + _IDIR="`echo \"${TOKEN}\" | sed 's/^-I//'`" + AS_IF([echo " ${LIBGIO_CFLAGS}" | ${EGREP} " -isystem *${_IDIR}" >/dev/null], + [myGIO_CFLAGS="${myGIO_CFLAGS} ${TOKEN}"], + [myGIO_CFLAGS="${myGIO_CFLAGS} -isystem ${_IDIR} ${TOKEN}"] + )], + [myGIO_CFLAGS="${myGIO_CFLAGS} ${TOKEN}"] + ) + done + unset TOKEN + unset _IDIR + myGIO_CFLAGS="`echo \"${myGIO_CFLAGS}\" | sed 's/^ *//'`" + + AS_IF([test x"${LIBGIO_CFLAGS}" != x -a x"${LIBGIO_CFLAGS}" != x"${myGIO_CFLAGS}"], [ + AC_MSG_NOTICE([Patched libgio CFLAGS to declare -isystem]) + AS_IF([test x"${nut_enable_configure_debug}" = xyes], [ + AC_MSG_NOTICE([(CONFIGURE-DEVEL-DEBUG) old: ${LIBGIO_CFLAGS}]) + AC_MSG_NOTICE([(CONFIGURE-DEVEL-DEBUG) new: ${myGIO_CFLAGS}]) + ]) + LIBGIO_CFLAGS="${myGIO_CFLAGS}" + ]) + unset myGIO_CFLAGS + ]) dnl Help ltdl if we can (nut-scanner etc.) for TOKEN in $depLIBS ; do AS_CASE(["${TOKEN}"], [-l*gio*], [ - AX_REALPATH_LIB([${TOKEN}], [SOPATH_LIBGLIB], []) - AS_IF([test -n "${SOPATH_LIBGLIB}" && test -s "${SOPATH_LIBGLIB}"], [ - AC_DEFINE_UNQUOTED([SOPATH_LIBGLIB],["${SOPATH_LIBGLIB}"],[Path to dynamic library on build system]) - SOFILE_LIBGLIB="`basename \"$SOPATH_LIBGLIB\"`" - AC_DEFINE_UNQUOTED([SOFILE_LIBGLIB],["${SOFILE_LIBGLIB}"],[Base file name of dynamic library on build system]) + AX_REALPATH_LIB([${TOKEN}], [SOPATH_LIBGIO], []) + AS_IF([test -n "${SOPATH_LIBGIO}" && test -s "${SOPATH_LIBGIO}"], [ + AC_DEFINE_UNQUOTED([SOPATH_LIBGIO],["${SOPATH_LIBGIO}"],[Path to dynamic library on build system]) + SOFILE_LIBGIO="`basename \"$SOPATH_LIBGIO\"`" + AC_DEFINE_UNQUOTED([SOFILE_LIBGIO],["${SOFILE_LIBGIO}"],[Base file name of dynamic library on build system]) break ]) ] @@ -97,8 +237,11 @@ if test -z "${nut_have_libglib_seen}"; then dnl restore original CFLAGS and LIBS CFLAGS="${CFLAGS_ORIG}" LIBS="${LIBS_ORIG}" -fi -AC_SUBST([LIBGLIB_CFLAGS]) -AC_SUBST([LIBGLIB_LIBS]) + AC_SUBST([LIBGLIB_CFLAGS]) + AC_SUBST([LIBGLIB_LIBS]) + + AC_SUBST([LIBGIO_CFLAGS]) + AC_SUBST([LIBGIO_LIBS]) +fi ]) diff --git a/tools/nut-scanner/Makefile.am b/tools/nut-scanner/Makefile.am index 8227da255d..a3e603650e 100644 --- a/tools/nut-scanner/Makefile.am +++ b/tools/nut-scanner/Makefile.am @@ -217,7 +217,7 @@ if WITH_IPMI libnutscan_la_CFLAGS += $(LIBIPMI_CFLAGS) endif WITH_IPMI if WITH_UPOWER - libnutscan_la_CFLAGS += $(LIBGLIB_CFLAGS) + libnutscan_la_CFLAGS += $(LIBGIO_CFLAGS) endif WITH_UPOWER # C is not a header, but there is no dist_noinst_SOURCES diff --git a/tools/nut-scanner/nutscan-init.c b/tools/nut-scanner/nutscan-init.c index 4b0f622f0c..6e5c4b888a 100644 --- a/tools/nut-scanner/nutscan-init.c +++ b/tools/nut-scanner/nutscan-init.c @@ -536,19 +536,19 @@ void nutscan_init(void) #endif /* WITH_AVAHI */ #if (defined WITH_UPOWER) && WITH_UPOWER -# ifdef SOFILE_LIBGLIB +# ifdef SOFILE_LIBGIO if (!libname) { - libname = get_libname(SOFILE_LIBGLIB); + libname = get_libname(SOFILE_LIBGIO); } -# endif /* SOFILE_LIBGLIB */ +# endif /* SOFILE_LIBGIO */ if (!libname) { libname = get_libname("libgio-2.0" SOEXT); } -# ifdef SOPATH_LIBGLIB +# ifdef SOPATH_LIBGIO if (!libname) { - libname = get_libname(SOPATH_LIBGLIB); + libname = get_libname(SOPATH_LIBGIO); } -# endif /* SOPATH_LIBGLIB */ +# endif /* SOPATH_LIBGIO */ if (libname) { upsdebugx(1, "%s: get_libname() resolved '%s' for %s, loading it", @@ -561,19 +561,19 @@ void nutscan_init(void) upsdebugx(1, "%s: get_libname() did not resolve libname for %s, " "trying to load it with libtool default resolver", __func__, "LibGIO"); -# ifdef SOFILE_LIBGLIB +# ifdef SOFILE_LIBGIO if (!nutscan_avail_upower) { - nutscan_avail_upower = nutscan_load_upower_library(SOFILE_LIBGLIB); + nutscan_avail_upower = nutscan_load_upower_library(SOFILE_LIBGIO); } -# endif /* SOFILE_LIBGLIB */ +# endif /* SOFILE_LIBGIO */ if (!nutscan_avail_upower) { nutscan_avail_upower = nutscan_load_upower_library("libgio-2.0" SOEXT); } -# ifdef SOPATH_LIBGLIB +# ifdef SOPATH_LIBGIO if (!nutscan_avail_upower) { - nutscan_avail_upower = nutscan_load_upower_library(SOPATH_LIBGLIB); + nutscan_avail_upower = nutscan_load_upower_library(SOPATH_LIBGIO); } -# endif /* SOPATH_LIBGLIB */ +# endif /* SOPATH_LIBGIO */ } upsdebugx(1, "%s: %s to load the library for %s", __func__, nutscan_avail_upower ? "succeeded" : "failed", "LibGIO"); From 475fb8f63964244704010c2c6a7a97a1f4a0f82c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 1 Feb 2026 00:38:24 +0100 Subject: [PATCH 088/198] tools/nut-scanner/Makefile.am: bump libnutscan version info [#3293] +1 for "current" (added interfaces) and "+1" for age (only added, not removed) Signed-off-by: Jim Klimov --- tools/nut-scanner/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/nut-scanner/Makefile.am b/tools/nut-scanner/Makefile.am index a3e603650e..385a9f30ef 100644 --- a/tools/nut-scanner/Makefile.am +++ b/tools/nut-scanner/Makefile.am @@ -133,7 +133,7 @@ libnutscan_la_LDFLAGS += @NETLIBS_GETADDRS@ # object .so names would differ) # # libnutscan version information -libnutscan_la_LDFLAGS += -version-info 4:0:0 +libnutscan_la_LDFLAGS += -version-info 5:0:1 # libnutscan exported symbols regex # WARNING: Since the library includes parts of libcommon (as much as needed From 390846f2ee3cbb4339de282ab867cccefd6922d0 Mon Sep 17 00:00:00 2001 From: Tim Niemueller Date: Sun, 1 Feb 2026 11:51:54 +0100 Subject: [PATCH 089/198] Add `-isystem` fix for glib Signed-off-by: Tim Niemueller --- m4/nut_check_libglib.m4 | 42 +++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/m4/nut_check_libglib.m4 b/m4/nut_check_libglib.m4 index d2328067f1..cb3f1bff2b 100644 --- a/m4/nut_check_libglib.m4 +++ b/m4/nut_check_libglib.m4 @@ -180,38 +180,48 @@ if test -z "${nut_have_libglib_seen}"; then AC_CHECK_HEADERS(gio/gio.h, [nut_have_libgio=yes], [nut_have_libgio=no], [AC_INCLUDES_DEFAULT]) dnl AC_CHECK_FUNCS(g_bus_get_sync, [], [nut_have_libgio=no]) - if test "${nut_have_libgio}" = "yes"; then - LIBGIO_CFLAGS="${depCFLAGS}" - LIBGIO_LIBS="${depLIBS}" + if test "${nut_have_libglib}" = "yes"; then + dnl GLib headers seem incorrect and offensive to many compilers + dnl (starting names with underscores and capital characters, + dnl varying support for attributes, method pointer mismatches). + dnl There is nothing NUT can do about it, except telling the + dnl compiler that we take these headers from the system as they + dnl are, so strict checks should not apply to them. + dnl On newer releases (2025+) the headers and CLANG seem to work + dnl together out of the box, but during the decade before this is + dnl troublesome. AS_IF([test "${CLANGCC}" = "yes" || test "${GCC}" = "yes"], [ - myGIO_CFLAGS="" - for TOKEN in ${LIBGIO_CFLAGS} ; do + myGLIB_CFLAGS="" + for TOKEN in ${depCFLAGS} ; do AS_CASE(["${TOKEN}"], [-I/*], [ _IDIR="`echo \"${TOKEN}\" | sed 's/^-I//'`" - AS_IF([echo " ${LIBGIO_CFLAGS}" | ${EGREP} " -isystem *${_IDIR}" >/dev/null], - [myGIO_CFLAGS="${myGIO_CFLAGS} ${TOKEN}"], - [myGIO_CFLAGS="${myGIO_CFLAGS} -isystem ${_IDIR} ${TOKEN}"] + AS_IF([echo " ${depCFLAGS}" | ${EGREP} " -isystem *${_IDIR}" >/dev/null], + [myGLIB_CFLAGS="${myGLIB_CFLAGS} ${TOKEN}"], + [myGLIB_CFLAGS="${myGLIB_CFLAGS} -isystem ${_IDIR} ${TOKEN}"] )], - [myGIO_CFLAGS="${myGIO_CFLAGS} ${TOKEN}"] + [myGLIB_CFLAGS="${myGLIB_CFLAGS} ${TOKEN}"] ) done unset TOKEN unset _IDIR - myGIO_CFLAGS="`echo \"${myGIO_CFLAGS}\" | sed 's/^ *//'`" + myGLIB_CFLAGS="`echo \"${myGLIB_CFLAGS}\" | sed 's/^ *//'`" - AS_IF([test x"${LIBGIO_CFLAGS}" != x -a x"${LIBGIO_CFLAGS}" != x"${myGIO_CFLAGS}"], [ - AC_MSG_NOTICE([Patched libgio CFLAGS to declare -isystem]) + AS_IF([test x"${depCFLAGS}" != x -a x"${depCFLAGS}" != x"${myGLIB_CFLAGS}"], [ + AC_MSG_NOTICE([Patched libglib/libgio CFLAGS to declare -isystem]) AS_IF([test x"${nut_enable_configure_debug}" = xyes], [ - AC_MSG_NOTICE([(CONFIGURE-DEVEL-DEBUG) old: ${LIBGIO_CFLAGS}]) - AC_MSG_NOTICE([(CONFIGURE-DEVEL-DEBUG) new: ${myGIO_CFLAGS}]) + AC_MSG_NOTICE([(CONFIGURE-DEVEL-DEBUG) old: ${depCFLAGS}]) + AC_MSG_NOTICE([(CONFIGURE-DEVEL-DEBUG) new: ${myGLIB_CFLAGS}]) ]) - LIBGIO_CFLAGS="${myGIO_CFLAGS}" + depCFLAGS="${myGLIB_CFLAGS}" ]) - unset myGIO_CFLAGS + unset myGLIB_CFLAGS ]) + LIBGLIB_CFLAGS="${depCFLAGS}" + LIBGLIB_LIBS="${depLIBS}" + dnl Help ltdl if we can (nut-scanner etc.) for TOKEN in $depLIBS ; do AS_CASE(["${TOKEN}"], From 47b199e4f3c8d5392481b40e61034df655666f70 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 1 Feb 2026 13:20:56 +0100 Subject: [PATCH 090/198] m4/nut_check_libglib.m4: Mostly revert 7f0ed5d29fc2035686cf5be820ec48db91ba19c8 [#3293] Earlier commits separated LIBGIO* from LIBGLIB* variables, but a parallel-developed fix happened to conflate them back. Signed-off-by: Jim Klimov --- m4/nut_check_libglib.m4 | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/m4/nut_check_libglib.m4 b/m4/nut_check_libglib.m4 index cb3f1bff2b..40ba6dc109 100644 --- a/m4/nut_check_libglib.m4 +++ b/m4/nut_check_libglib.m4 @@ -180,48 +180,40 @@ if test -z "${nut_have_libglib_seen}"; then AC_CHECK_HEADERS(gio/gio.h, [nut_have_libgio=yes], [nut_have_libgio=no], [AC_INCLUDES_DEFAULT]) dnl AC_CHECK_FUNCS(g_bus_get_sync, [], [nut_have_libgio=no]) - if test "${nut_have_libglib}" = "yes"; then + if test "${nut_have_libgio}" = "yes"; then + LIBGIO_CFLAGS="${depCFLAGS}" + LIBGIO_LIBS="${depLIBS}" dnl GLib headers seem incorrect and offensive to many compilers - dnl (starting names with underscores and capital characters, - dnl varying support for attributes, method pointer mismatches). - dnl There is nothing NUT can do about it, except telling the - dnl compiler that we take these headers from the system as they - dnl are, so strict checks should not apply to them. - dnl On newer releases (2025+) the headers and CLANG seem to work - dnl together out of the box, but during the decade before this is - dnl troublesome. + dnl (see details in big comment above). AS_IF([test "${CLANGCC}" = "yes" || test "${GCC}" = "yes"], [ - myGLIB_CFLAGS="" - for TOKEN in ${depCFLAGS} ; do + myGIO_CFLAGS="" + for TOKEN in ${LIBGIO_CFLAGS} ; do AS_CASE(["${TOKEN}"], [-I/*], [ _IDIR="`echo \"${TOKEN}\" | sed 's/^-I//'`" - AS_IF([echo " ${depCFLAGS}" | ${EGREP} " -isystem *${_IDIR}" >/dev/null], - [myGLIB_CFLAGS="${myGLIB_CFLAGS} ${TOKEN}"], - [myGLIB_CFLAGS="${myGLIB_CFLAGS} -isystem ${_IDIR} ${TOKEN}"] + AS_IF([echo " ${LIBGIO_CFLAGS}" | ${EGREP} " -isystem *${_IDIR}" >/dev/null], + [myGIO_CFLAGS="${myGIO_CFLAGS} ${TOKEN}"], + [myGIO_CFLAGS="${myGIO_CFLAGS} -isystem ${_IDIR} ${TOKEN}"] )], - [myGLIB_CFLAGS="${myGLIB_CFLAGS} ${TOKEN}"] + [myGIO_CFLAGS="${myGIO_CFLAGS} ${TOKEN}"] ) done unset TOKEN unset _IDIR - myGLIB_CFLAGS="`echo \"${myGLIB_CFLAGS}\" | sed 's/^ *//'`" + myGIO_CFLAGS="`echo \"${myGIO_CFLAGS}\" | sed 's/^ *//'`" - AS_IF([test x"${depCFLAGS}" != x -a x"${depCFLAGS}" != x"${myGLIB_CFLAGS}"], [ + AS_IF([test x"${LIBGIO_CFLAGS}" != x -a x"${LIBGIO_CFLAGS}" != x"${myGIO_CFLAGS}"], [ AC_MSG_NOTICE([Patched libglib/libgio CFLAGS to declare -isystem]) AS_IF([test x"${nut_enable_configure_debug}" = xyes], [ - AC_MSG_NOTICE([(CONFIGURE-DEVEL-DEBUG) old: ${depCFLAGS}]) - AC_MSG_NOTICE([(CONFIGURE-DEVEL-DEBUG) new: ${myGLIB_CFLAGS}]) + AC_MSG_NOTICE([(CONFIGURE-DEVEL-DEBUG) old: ${LIBGIO_CFLAGS}]) + AC_MSG_NOTICE([(CONFIGURE-DEVEL-DEBUG) new: ${myGIO_CFLAGS}]) ]) - depCFLAGS="${myGLIB_CFLAGS}" + LIBGIO_CFLAGS="${myGIO_CFLAGS}" ]) - unset myGLIB_CFLAGS + unset myGIO_CFLAGS ]) - LIBGLIB_CFLAGS="${depCFLAGS}" - LIBGLIB_LIBS="${depLIBS}" - dnl Help ltdl if we can (nut-scanner etc.) for TOKEN in $depLIBS ; do AS_CASE(["${TOKEN}"], From 808670a9ec49879cffe1b4cfdffeaf08333bc6b1 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 1 Feb 2026 13:26:32 +0100 Subject: [PATCH 091/198] m4/nut_check_libglib.m4: generalize the -isystem fix to hack depCFLAGS first [#3293] Signed-off-by: Jim Klimov --- m4/nut_check_libglib.m4 | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/m4/nut_check_libglib.m4 b/m4/nut_check_libglib.m4 index 40ba6dc109..e1f348b336 100644 --- a/m4/nut_check_libglib.m4 +++ b/m4/nut_check_libglib.m4 @@ -70,9 +70,6 @@ if test -z "${nut_have_libglib_seen}"; then AC_CHECK_HEADERS(glib.h, [nut_have_libglib=yes], [nut_have_libglib=no], [AC_INCLUDES_DEFAULT]) if test "${nut_have_libglib}" = "yes"; then - LIBGLIB_CFLAGS="${depCFLAGS}" - LIBGLIB_LIBS="${depLIBS}" - dnl GLib headers seem incorrect and offensive to many compilers dnl (starting names with underscores and capital characters, dnl varying support for attributes, method pointer mismatches). @@ -84,11 +81,11 @@ if test -z "${nut_have_libglib_seen}"; then dnl troublesome. AS_IF([test "${CLANGCC}" = "yes" || test "${GCC}" = "yes"], [ myGLIB_CFLAGS="" - for TOKEN in ${LIBGLIB_CFLAGS} ; do + for TOKEN in ${depCFLAGS} ; do AS_CASE(["${TOKEN}"], [-I/*], [ _IDIR="`echo \"${TOKEN}\" | sed 's/^-I//'`" - AS_IF([echo " ${LIBGLIB_CFLAGS}" | ${EGREP} " -isystem *${_IDIR}" >/dev/null], + AS_IF([echo " ${depCFLAGS}" | ${EGREP} " -isystem *${_IDIR}" >/dev/null], [myGLIB_CFLAGS="${myGLIB_CFLAGS} ${TOKEN}"], [myGLIB_CFLAGS="${myGLIB_CFLAGS} -isystem ${_IDIR} ${TOKEN}"] )], @@ -99,17 +96,20 @@ if test -z "${nut_have_libglib_seen}"; then unset _IDIR myGLIB_CFLAGS="`echo \"${myGLIB_CFLAGS}\" | sed 's/^ *//'`" - AS_IF([test x"${LIBGLIB_CFLAGS}" != x -a x"${LIBGLIB_CFLAGS}" != x"${myGLIB_CFLAGS}"], [ + AS_IF([test x"${depCFLAGS}" != x -a x"${depCFLAGS}" != x"${myGLIB_CFLAGS}"], [ AC_MSG_NOTICE([Patched libglib CFLAGS to declare -isystem]) AS_IF([test x"${nut_enable_configure_debug}" = xyes], [ - AC_MSG_NOTICE([(CONFIGURE-DEVEL-DEBUG) old: ${LIBGLIB_CFLAGS}]) + AC_MSG_NOTICE([(CONFIGURE-DEVEL-DEBUG) old: ${depCFLAGS}]) AC_MSG_NOTICE([(CONFIGURE-DEVEL-DEBUG) new: ${myGLIB_CFLAGS}]) ]) - LIBGLIB_CFLAGS="${myGLIB_CFLAGS}" + depCFLAGS="${myGLIB_CFLAGS}" ]) unset myGLIB_CFLAGS ]) + LIBGLIB_CFLAGS="${depCFLAGS}" + LIBGLIB_LIBS="${depLIBS}" + dnl Help ltdl if we can (nut-scanner etc.) for TOKEN in $depLIBS ; do AS_CASE(["${TOKEN}"], @@ -181,18 +181,15 @@ if test -z "${nut_have_libglib_seen}"; then dnl AC_CHECK_FUNCS(g_bus_get_sync, [], [nut_have_libgio=no]) if test "${nut_have_libgio}" = "yes"; then - LIBGIO_CFLAGS="${depCFLAGS}" - LIBGIO_LIBS="${depLIBS}" - dnl GLib headers seem incorrect and offensive to many compilers dnl (see details in big comment above). AS_IF([test "${CLANGCC}" = "yes" || test "${GCC}" = "yes"], [ myGIO_CFLAGS="" - for TOKEN in ${LIBGIO_CFLAGS} ; do + for TOKEN in ${depCFLAGS} ; do AS_CASE(["${TOKEN}"], [-I/*], [ _IDIR="`echo \"${TOKEN}\" | sed 's/^-I//'`" - AS_IF([echo " ${LIBGIO_CFLAGS}" | ${EGREP} " -isystem *${_IDIR}" >/dev/null], + AS_IF([echo " ${depCFLAGS}" | ${EGREP} " -isystem *${_IDIR}" >/dev/null], [myGIO_CFLAGS="${myGIO_CFLAGS} ${TOKEN}"], [myGIO_CFLAGS="${myGIO_CFLAGS} -isystem ${_IDIR} ${TOKEN}"] )], @@ -203,17 +200,20 @@ if test -z "${nut_have_libglib_seen}"; then unset _IDIR myGIO_CFLAGS="`echo \"${myGIO_CFLAGS}\" | sed 's/^ *//'`" - AS_IF([test x"${LIBGIO_CFLAGS}" != x -a x"${LIBGIO_CFLAGS}" != x"${myGIO_CFLAGS}"], [ + AS_IF([test x"${depCFLAGS}" != x -a x"${depCFLAGS}" != x"${myGIO_CFLAGS}"], [ AC_MSG_NOTICE([Patched libglib/libgio CFLAGS to declare -isystem]) AS_IF([test x"${nut_enable_configure_debug}" = xyes], [ - AC_MSG_NOTICE([(CONFIGURE-DEVEL-DEBUG) old: ${LIBGIO_CFLAGS}]) + AC_MSG_NOTICE([(CONFIGURE-DEVEL-DEBUG) old: ${depCFLAGS}]) AC_MSG_NOTICE([(CONFIGURE-DEVEL-DEBUG) new: ${myGIO_CFLAGS}]) ]) - LIBGIO_CFLAGS="${myGIO_CFLAGS}" + depCFLAGS="${myGIO_CFLAGS}" ]) unset myGIO_CFLAGS ]) + LIBGIO_CFLAGS="${depCFLAGS}" + LIBGIO_LIBS="${depLIBS}" + dnl Help ltdl if we can (nut-scanner etc.) for TOKEN in $depLIBS ; do AS_CASE(["${TOKEN}"], From 7c3b7dd70146059d4c1e1c76c8733765d5485220 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 09:10:52 +0100 Subject: [PATCH 092/198] tools/nut-scanner/*.c: be stricter about "ifdef WITH_SOME_NUT_FEATURE" (we may have some defined but zeroed, so not active for a build) [#3293] Signed-off-by: Jim Klimov --- tools/nut-scanner/scan_upower.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/nut-scanner/scan_upower.c b/tools/nut-scanner/scan_upower.c index 62e4d6a79c..ca03a9bd76 100644 --- a/tools/nut-scanner/scan_upower.c +++ b/tools/nut-scanner/scan_upower.c @@ -29,7 +29,7 @@ int nutscan_unload_upower_library(void); /* externally visible to nut-scanner */ nutscan_device_t * nutscan_scan_upower(void); -#ifdef WITH_UPOWER +#if (defined WITH_UPOWER) && WITH_UPOWER #include #include From ea52633873b659e986f40ed4c526b98bf141e4cb Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 09:13:11 +0100 Subject: [PATCH 093/198] NEWS.adoc: move nut-scanner UPower support notice into the `nut-scanner` tool section [#3293] Signed-off-by: Jim Klimov --- NEWS.adoc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index d660c1cee2..d8fe700679 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -221,8 +221,6 @@ https://github.com/networkupstools/nut/milestone/12 via D-Bus. This also introduces a new category of drivers that talk to operating system services to obtain power state information. [PR #3279] - - Introduced a nut-scanner support for new `nut-upower` driver. [PR #3293] - - `usbhid-ups` driver updates: * Declared support for APC with USB ID `051d:0005` (details may evolve as the devices become better known). [issue #3047, PR #3081] @@ -270,6 +268,7 @@ https://github.com/networkupstools/nut/milestone/12 built-in NUT configuration path on all platforms, but to also consider `NUT_CONFPATH` and other fallback locations, like other code does. [PR #3249] + * Introduced `nut-scanner` support for new `nut-upower` driver. [PR #3293] - `upsd` data server updates: * Sometimes "Data for UPS [X] is stale" and "UPS [X] data is no longer From cca6b245e01a1fdc343b09e1cef4d37fa5c98d37 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 13:46:35 +0100 Subject: [PATCH 094/198] tools/nut-scanner/nutscan-init.c: comment the situation about many libs related to UPower where we only load one for scanning [#3293] Signed-off-by: Jim Klimov --- tools/nut-scanner/nutscan-init.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/nut-scanner/nutscan-init.c b/tools/nut-scanner/nutscan-init.c index 6e5c4b888a..cdbd2a611e 100644 --- a/tools/nut-scanner/nutscan-init.c +++ b/tools/nut-scanner/nutscan-init.c @@ -536,6 +536,9 @@ void nutscan_init(void) #endif /* WITH_AVAHI */ #if (defined WITH_UPOWER) && WITH_UPOWER +/* NOTE: There may be a stack of libraries involved (libgio, libglib2, + * libmount...) in driver programs, but one entry point suffices + * (and/or dynamically pulls in the others) for just the scan itself */ # ifdef SOFILE_LIBGIO if (!libname) { libname = get_libname(SOFILE_LIBGIO); From 5beeb0d0bb9615dadf52681e7b04c0822483dcc7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 17:01:01 +0100 Subject: [PATCH 095/198] tools/nut-scanner/scan_upower.c: apply fixes about use of `(lt_dlhandle)1` instead of `(void *)1` [#3293] Signed-off-by: Jim Klimov --- tools/nut-scanner/scan_upower.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/nut-scanner/scan_upower.c b/tools/nut-scanner/scan_upower.c index ca03a9bd76..53f3ebec14 100644 --- a/tools/nut-scanner/scan_upower.c +++ b/tools/nut-scanner/scan_upower.c @@ -72,7 +72,7 @@ int nutscan_load_upower_library(const char *libname_path) { if (dl_handle != NULL) { /* if previous init failed */ - if (dl_handle == (void *)1) { + if (dl_handle == (lt_dlhandle)1) { return 0; } /* init has already been done */ @@ -147,7 +147,7 @@ int nutscan_load_upower_library(const char *libname_path) upsdebugx(0, "Cannot load GIO library (%s) : %s. UPower search disabled.", libname_path, dl_error); - dl_handle = (void *)1; + dl_handle = (lt_dlhandle)1; lt_dlexit(); if (dl_saved_libname) { free(dl_saved_libname); From c21dd68250f6d4e61798c45056cc391ff24e0c07 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 17:01:51 +0100 Subject: [PATCH 096/198] tools/nut-scanner/scan_upower.c: apply simpler indentation [#3293] Signed-off-by: Jim Klimov --- tools/nut-scanner/scan_upower.c | 49 +++++++++++++++++---------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/tools/nut-scanner/scan_upower.c b/tools/nut-scanner/scan_upower.c index 53f3ebec14..3f623ef5a8 100644 --- a/tools/nut-scanner/scan_upower.c +++ b/tools/nut-scanner/scan_upower.c @@ -178,14 +178,15 @@ nutscan_device_t * nutscan_scan_upower(void) return NULL; } - proxy_upower = (*nut_g_dbus_proxy_new_sync)(connection, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.freedesktop.UPower", - "/org/freedesktop/UPower", - "org.freedesktop.UPower", - NULL, - &error); + proxy_upower = (*nut_g_dbus_proxy_new_sync)( + connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + "org.freedesktop.UPower", + "/org/freedesktop/UPower", + "org.freedesktop.UPower", + NULL, + &error); if (proxy_upower == NULL) { upsdebugx(1, "Error creating UPower proxy: %s", error->message); @@ -194,13 +195,14 @@ nutscan_device_t * nutscan_scan_upower(void) return NULL; } - result = (*nut_g_dbus_proxy_call_sync)(proxy_upower, - "EnumerateDevices", - NULL, - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - &error); + result = (*nut_g_dbus_proxy_call_sync)( + proxy_upower, + "EnumerateDevices", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); if (result == NULL) { upsdebugx(1, "Error enumerating devices: %s", error->message); @@ -219,14 +221,15 @@ nutscan_device_t * nutscan_scan_upower(void) GVariant *v_type, *v_model, *v_vendor, *v_serial, *v_native_path; nutscan_device_t * dev; - proxy_device = (*nut_g_dbus_proxy_new_sync)(connection, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.freedesktop.UPower", - object_path, - "org.freedesktop.UPower.Device", - NULL, - &error); + proxy_device = (*nut_g_dbus_proxy_new_sync)( + connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + "org.freedesktop.UPower", + object_path, + "org.freedesktop.UPower.Device", + NULL, + &error); if (proxy_device == NULL) { upsdebugx(1, "Error creating device proxy for %s: %s", object_path, error->message); From 66f1c146e820cc9deb45c8dbc03a553deac1e7fa Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 17:36:56 +0100 Subject: [PATCH 097/198] scripts/obs/debian.rules: make "autotools.mk" inclusion optional (Debian Testing in Jan/Feb 2026 seems to lack it) [#1209] Signed-off-by: Jim Klimov --- scripts/obs/debian.rules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/obs/debian.rules b/scripts/obs/debian.rules index 4f74a97a21..020f397914 100755 --- a/scripts/obs/debian.rules +++ b/scripts/obs/debian.rules @@ -1,7 +1,7 @@ #!/usr/bin/make -f include /usr/share/cdbs/1/rules/debhelper.mk -include /usr/share/cdbs/1/class/autotools.mk +-include /usr/share/cdbs/1/class/autotools.mk -include /usr/share/cdbs/1/class/python-module.mk -include /usr/share/cdbs/1/rules/autoreconf.mk From 3841eb386baabe2dceb15f9a2bbc28a89c14dca8 Mon Sep 17 00:00:00 2001 From: jawz101 Date: Mon, 2 Feb 2026 16:59:59 -0600 Subject: [PATCH 098/198] Add support for Vertiv PSI5 MIB --- drivers/snmp-ups.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/snmp-ups.c b/drivers/snmp-ups.c index 72c93f04c6..58cc035dfa 100644 --- a/drivers/snmp-ups.c +++ b/drivers/snmp-ups.c @@ -72,6 +72,7 @@ #include "emerson-avocent-pdu-mib.h" #include "hpe-pdu-mib.h" #include "hpe-pdu3-cis-mib.h" +#include "vertiv-psi5-mib.h" /* Address API change */ #if ( ! NUT_HAVE_LIBNETSNMP_usmAESPrivProtocol ) && ( ! defined usmAESPrivProtocol ) @@ -128,6 +129,7 @@ static mib2nut_info_t *mib2nut[] = { &netvision, /* This struct comes from : netvision-mib.c */ &raritan, /* This struct comes from : raritan-pdu-mib.c */ &raritan_px2, /* This struct comes from : raritan-px2-mib.c */ + &vertiv_psi5_subdriver, /* This struct comes from : vertiv-psi5-mib.c */ &xppc, /* This struct comes from : xppc-mib.c */ /* * Prepend vendor specific MIB mappings before IETF, so that From c08164d376009c9eefd38313fc2404f802284c17 Mon Sep 17 00:00:00 2001 From: jawz101 Date: Mon, 2 Feb 2026 17:25:30 -0600 Subject: [PATCH 099/198] squash vertiv commits * add c & h driver files * Add files via upload * Add vertiv-psi5-mib.c to Makefile.am * Add vertiv-psi5-mib.h to Makefile.am --- drivers/Makefile.am | 3 +- drivers/vertiv-psi5-mib.c | 90 +++++++++++++++++++++++++++++++++++++++ drivers/vertiv-psi5-mib.h | 29 +++++++++++++ 3 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 drivers/vertiv-psi5-mib.c create mode 100644 drivers/vertiv-psi5-mib.h diff --git a/drivers/Makefile.am b/drivers/Makefile.am index db6b148702..7202c7b386 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -394,6 +394,7 @@ snmp_ups_SOURCES = snmp-ups.c snmp-ups-helpers.c \ mge-mib.c \ netvision-mib.c \ raritan-pdu-mib.c raritan-px2-mib.c \ + vertiv-psi5-mib.c \ xppc-mib.c snmp_ups_CFLAGS = $(AM_CFLAGS) snmp_ups_CFLAGS += $(LIBNETSNMP_CFLAGS) @@ -540,7 +541,7 @@ dist_noinst_HEADERS = \ nutdrv_qx_voltronic-axpert.h nutdrv_qx_voltronic-qs.h nutdrv_qx_voltronic-qs-hex.h \ nutdrv_qx_zinto.h \ upsdrvquery.h \ - xppc-mib.h huawei-mib.h eaton-ats16-nmc-mib.h eaton-ats16-nm2-mib.h apc-ats-mib.h raritan-px2-mib.h eaton-ats30-mib.h \ + xppc-mib.h huawei-mib.h eaton-ats16-nmc-mib.h eaton-ats16-nm2-mib.h apc-ats-mib.h raritan-px2-mib.h vertiv-psi5-mib.h eaton-ats30-mib.h \ apc-pdu-mib.h apc-epdu-mib.h ecoflow-hid.h ever-hid.h eaton-pdu-genesis2-mib.h eaton-pdu-marlin-mib.h eaton-pdu-marlin-helpers.h \ eaton-pdu-pulizzi-mib.h eaton-pdu-revelation-mib.h emerson-avocent-pdu-mib.h eaton-ups-pwnm2-mib.h eaton-ups-pxg-mib.h legrand-hid.h \ hpe-pdu-mib.h hpe-pdu3-cis-mib.h powervar-hid.h delta_ups-hid.h generic_modbus.h salicru-hid.h adelsystem_cbi.h eaton-pdu-nlogic-mib.h ydn23.h diff --git a/drivers/vertiv-psi5-mib.c b/drivers/vertiv-psi5-mib.c new file mode 100644 index 0000000000..fdcd8b7df1 --- /dev/null +++ b/drivers/vertiv-psi5-mib.c @@ -0,0 +1,90 @@ +/* drivers/vertiv-psi5-mib.c - Driver for Vertiv Liebert PSI5 UPS + * + * Copyright (C) + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "vertiv-psi5-mib.h" + +/* Vertiv PSI5-750MT120 Mapping + Based on integer branch at .1.3.6.1.4.1.476.1.42.3.9.30... */ + +static snmp_info_t vertiv_psi5_mib[] = { + /* Load and Temperature */ + { "ups.load", 0, SU_INFOTYPE_INT, NULL, + ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.5861", + NULL, NULL }, + { "ups.temperature", 0, SU_INFOTYPE_INT, NULL, + ".1.3.6.1.4.1.476.1.42.3.9.30.1.10.1.2.1.4291", + NULL, NULL }, + + /* Battery */ + { "battery.charge", 0, SU_INFOTYPE_INT, NULL, + ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4153", + NULL, NULL }, + { "battery.runtime", 0, SU_INFOTYPE_INT, NULL, + ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4150", + NULL, NULL }, /* Note: Raw value is minutes, NUT usually expects seconds */ + { "battery.voltage", 0, SU_INFOTYPE_INT, NULL, + ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4148", + NULL, NULL }, + + /* Input */ + { "input.voltage", 0, SU_INFOTYPE_INT, NULL, + ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4096", + SU_FLAG_OK, NULL }, /* Scale: 0.1 */ + { "input.frequency", 0, SU_INFOTYPE_INT, NULL, + ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4105", + SU_FLAG_OK, NULL }, /* Scale: 0.1 */ + + /* Output */ + { "output.voltage", 0, SU_INFOTYPE_INT, NULL, + ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4385", + SU_FLAG_OK, NULL }, /* Scale: 0.1 */ + { "output.current", 0, SU_INFOTYPE_INT, NULL, + ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4204", + SU_FLAG_OK, NULL }, /* Scale: 0.1 */ + { "output.power", 0, SU_INFOTYPE_INT, NULL, + ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4208", + SU_FLAG_OK, NULL }, + + /* Status Flags */ + { "ups.alarm", 0, SU_INFOTYPE_INT, NULL, + ".1.3.6.1.4.1.476.1.42.3.9.20.1.20.1.2.100.6182", + NULL, NULL }, /* Replace Battery */ + { "ups.alarm", 0, SU_INFOTYPE_INT, NULL, + ".1.3.6.1.4.1.476.1.42.3.9.20.1.20.1.2.100.4233", + NULL, NULL }, /* Inverter Failure */ + { "ups.alarm", 0, SU_INFOTYPE_INT, NULL, + ".1.3.6.1.4.1.476.1.42.3.9.20.1.20.1.2.100.5806", + NULL, NULL }, /* Overload */ + + /* End of list */ + { NULL, 0, 0, NULL, NULL, NULL, NULL } +}; + +snmp_subdriver_t vertiv_psi5_subdriver = { + "vertiv-psi5", + "1.0", + ".1.3.6.1.4.1.476.1.42", /* SysOID for Vertiv/Liebert */ + vertiv_psi5_mib, + NULL, + NULL, + NULL, + NULL +}; \ No newline at end of file diff --git a/drivers/vertiv-psi5-mib.h b/drivers/vertiv-psi5-mib.h new file mode 100644 index 0000000000..ffbeff425a --- /dev/null +++ b/drivers/vertiv-psi5-mib.h @@ -0,0 +1,29 @@ +/* vertiv-psi5-mib.h - Driver for Vertiv Liebert PSI5 UPS + * + * Copyright (C) + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef VERTIV_PSI5_MIB_H +#define VERTIV_PSI5_MIB_H + +#include "snmp-ups.h" + +extern snmp_subdriver_t vertiv_psi5_subdriver; + +#endif /* VERTIV_PSI5_MIB_H */ \ No newline at end of file From e7fafe8ed243fcd87dd75043a776e1ef4add3dc9 Mon Sep 17 00:00:00 2001 From: jawz101 Date: Mon, 2 Feb 2026 17:32:56 -0600 Subject: [PATCH 100/198] Bump driver version to 1.39 --- drivers/snmp-ups.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/snmp-ups.c b/drivers/snmp-ups.c index 58cc035dfa..1b72bda179 100644 --- a/drivers/snmp-ups.c +++ b/drivers/snmp-ups.c @@ -179,7 +179,7 @@ static const char *mibname; static const char *mibvers; #define DRIVER_NAME "Generic SNMP UPS driver" -#define DRIVER_VERSION "1.38" +#define DRIVER_VERSION "1.39" /* driver description structure */ upsdrv_info_t upsdrv_info = { From 63ed473558af35766e4d76d695c83644117d8c98 Mon Sep 17 00:00:00 2001 From: jawz101 Date: Mon, 2 Feb 2026 17:46:45 -0600 Subject: [PATCH 101/198] Enhance Vertiv PSI5 MIB with control features Added shutdown and start delay control for UPS. --- drivers/vertiv-psi5-mib.c | 38 ++++++++++++++------------------------ 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/drivers/vertiv-psi5-mib.c b/drivers/vertiv-psi5-mib.c index fdcd8b7df1..3332ca96e0 100644 --- a/drivers/vertiv-psi5-mib.c +++ b/drivers/vertiv-psi5-mib.c @@ -1,28 +1,9 @@ -/* drivers/vertiv-psi5-mib.c - Driver for Vertiv Liebert PSI5 UPS - * - * Copyright (C) - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - +/* drivers/vertiv-psi5-mib.c */ #include "vertiv-psi5-mib.h" /* Vertiv PSI5-750MT120 Mapping - Based on integer branch at .1.3.6.1.4.1.476.1.42.3.9.30... */ + Monitoring: Based on integer branch at .1.3.6.1.4.1.476.1.42.3.9.30... + Control: Based on standard Liebert Environmental MIB at .1.3.6.1.4.1.476.1.42.3.3.5... */ static snmp_info_t vertiv_psi5_mib[] = { /* Load and Temperature */ @@ -39,7 +20,7 @@ static snmp_info_t vertiv_psi5_mib[] = { NULL, NULL }, { "battery.runtime", 0, SU_INFOTYPE_INT, NULL, ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4150", - NULL, NULL }, /* Note: Raw value is minutes, NUT usually expects seconds */ + NULL, NULL }, /* Raw value is minutes */ { "battery.voltage", 0, SU_INFOTYPE_INT, NULL, ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4148", NULL, NULL }, @@ -63,6 +44,15 @@ static snmp_info_t vertiv_psi5_mib[] = { ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4208", SU_FLAG_OK, NULL }, + /* Shutdown / Restart Control + Derived from lgpEnvControl (LIEBERT-GP-ENVIRONMENTAL-MIB) */ + { "ups.delay.shutdown", 0, SU_INFOTYPE_INT, + ".1.3.6.1.4.1.476.1.42.3.3.5.1.0", + SU_FLAG_RW | SU_FLAG_OK, NULL }, + { "ups.delay.start", 0, SU_INFOTYPE_INT, + ".1.3.6.1.4.1.476.1.42.3.3.5.2.0", + SU_FLAG_RW | SU_FLAG_OK, NULL }, + /* Status Flags */ { "ups.alarm", 0, SU_INFOTYPE_INT, NULL, ".1.3.6.1.4.1.476.1.42.3.9.20.1.20.1.2.100.6182", @@ -87,4 +77,4 @@ snmp_subdriver_t vertiv_psi5_subdriver = { NULL, NULL, NULL -}; \ No newline at end of file +}; From 3fa7341a5598004e8a65f5986b3f26cf1cf53602 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 2 Feb 2026 19:10:41 +0100 Subject: [PATCH 102/198] scripts/obs/debian.rules: stash a copy of CDBS autotools.mk to include if the real thing is not available [#1209] Signed-off-by: Jim Klimov --- scripts/obs/debian.cdbs-autotools.mk | 440 +++++++++++++++++++++++++++ scripts/obs/debian.rules | 21 +- 2 files changed, 460 insertions(+), 1 deletion(-) create mode 100644 scripts/obs/debian.cdbs-autotools.mk diff --git a/scripts/obs/debian.cdbs-autotools.mk b/scripts/obs/debian.cdbs-autotools.mk new file mode 100644 index 0000000000..73f7be0d4b --- /dev/null +++ b/scripts/obs/debian.cdbs-autotools.mk @@ -0,0 +1,440 @@ +# In 2026, Debian obsoletes and removes CDBS and its scripts +# Stashing https://salsa.debian.org/debian/cdbs/-/blob/a110afb99997b94de6acb1e0758210cdfd8ec3dd/1/class/autotools.mk.in +# and neighbors + +# -*- mode: makefile; coding: utf-8 -*- +# Copyright © 2002,2003 Colin Walters +# Copyright © 2008-2010, 2014, 2016 Jonas Smedegaard +# Description: A class to configure and build GNU autoconf+automake packages +# +# 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 +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +#PATH_RULES# + +ifndef _cdbs_class_autotools +_cdbs_class_autotools = 1 + +# BEGIN # include $(_cdbs_class_path)/autotools-files.mk$(_cdbs_makefile_suffix) + +ifndef _cdbs_class_autotools_files +_cdbs_class_autotools_files = 1 + +# BEGIN # include $(_cdbs_class_path)/autotools-vars.mk$(_cdbs_makefile_suffix) + +ifndef _cdbs_class_autotools_vars +_cdbs_class_autotools_vars = 1 + +# BEGIN # include $(_cdbs_class_path)/makefile.mk$(_cdbs_makefile_suffix) + +ifndef _cdbs_class_makefile +_cdbs_class_makefile = 1 + +# Included by caller # include $(_cdbs_rules_path)/buildcore.mk$(_cdbs_makefile_suffix) +# BEGIN # include $(_cdbs_class_path)/makefile-vars.mk$(_cdbs_makefile_suffix) + +ifndef _cdbs_class_makefile_vars +_cdbs_class_makefile_vars = 1 + +# BEGIN # include $(_cdbs_class_path)/langcore.mk$(_cdbs_makefile_suffix) + +ifndef _cdbs_class_langcore +_cdbs_class_langcore = 1 + +include $(_cdbs_rules_path)/buildvars.mk$(_cdbs_makefile_suffix) + +# Resolve our defaults +# GNU Make doesn't export current environment in $(shell ..) function. +# We need at least some of the DEB_* flags for dpkg-buildflags, so +# extract them from the defined variables. Sadly there seems to be no +# way to just get all exported variables. +# +# massage dpkg-buildflag output: +# * filter to include only lines matching expected format +# * transform prefix, e.g. "export LDFLAGS := ..." -> "LDFLAGS ?= ..." +$(shell \ + $(call cdbs_set_nondefaultvars,\ + $(foreach flag,$(shell dpkg-buildflags --list),\ + $(foreach op,SET STRIP APPEND PREPEND,\ + DEB_$(flag)_$(op) DEB_$(flag)_MAINT_$(op)))\ + DEB_BUILD_OPTIONS DEB_BUILD_MAINT_OPTIONS) \ + dpkg-buildflags --export=make \ + | perl -pe 's/^export\s+//; s/:=/?=/' \ + > debian/_cdbs_buildflags.mk ) +-include debian/_cdbs_buildflags.mk +$(shell rm -f debian/_cdbs_buildflags.mk) + +$(eval $(and $(cdbs_crossbuild),$(filter default,$(origin CC)),\ + CC := $(DEB_HOST_GNU_TYPE)-gcc)) +$(eval $(and $(cdbs_crossbuild),$(filter default,$(origin CXX)),\ + CXX := $(DEB_HOST_GNU_TYPE)-g++)) + +ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS))) + DEB_PARALLEL_JOBS ?= $(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS))) +endif + +endif + +# END # include $(_cdbs_class_path)/langcore.mk$(_cdbs_makefile_suffix) + +#DEB_MAKE_MAKEFILE = +DEB_MAKE_ENVVARS ?= $(if $(cdbs_crossbuild),\ + CC="$(CC)" CXX="$(CXX)" PKG_CONFIG="$(DEB_HOST_GNU_TYPE)-pkg-config") +DEB_MAKE_PARALLEL ?= $(and $(DEB_BUILD_PARALLEL),$(DEB_PARALLEL_JOBS),\ + -j$(DEB_PARALLEL_JOBS)) + +# Derived classes that supply the flags some other way (e.g., configure) +# should set this variable to empty. +DEB_MAKE_EXTRA_ARGS ?= \ + CFLAGS="$(or $(CFLAGS_$(cdbs_curpkg)),$(CFLAGS))" \ + CXXFLAGS="$(or $(CXXFLAGS_$(cdbs_curpkg)),$(CXXFLAGS))" \ + CPPFLAGS="$(or $(CPPFLAGS_$(cdbs_curpkg)),$(CPPFLAGS))" \ + LDFLAGS="$(or $(LDFLAGS_$(cdbs_curpkg)),$(LDFLAGS))" \ + $(DEB_MAKE_PARALLEL) + +DEB_MAKE_INVOKE ?= $(strip \ + $(DEB_MAKE_ENVVARS) $(MAKE) \ + $(if $(DEB_MAKE_MAKEFILE),\ + -f $(DEB_MAKE_MAKEFILE)) \ + -C $(or $(cdbs_make_curbuilddir),$(cdbs_curbuilddir)) \ + $(DEB_MAKE_EXTRA_ARGS)) + +#DEB_MAKE_BUILD_TARGET = + +# If your Makefile provides an "install" target, you need to give the requisite commands +# here to install it into the staging directory. For automake-using programs, this +# looks like: install DESTDIR=$(cdbs_make_curdestdir) +# (which expands to either DEB_DESTDIR_xxx or DEB_DESTDIR) +# If you're using automake though, you likely want to be including autotools.mk instead +# of this file. + +DEB_MAKE_CLEAN_TARGET ?= clean + +#DEB_MAKE_CHECK_TARGET = test + +# If DEB_MAKE_FLAVORS is set compilation is done once per flavor. +# NB! This must be declared _before_ including makefile.mk +#DEB_MAKE_FLAVORS = light normal enhanced + +# If building multiple flavors, skeleton strings are used for +# DEB_BUILDDIR and DEB_DESTDIR, with @FLAVOR@ expanding to actual +# flavor. +DEB_MAKE_BUILDDIRSKEL ?= $(cdbs_curbuilddir)/@FLAVOR@ +DEB_MAKE_DESTDIRSKEL ?= $(cdbs_curdestdir)/@FLAVOR@ + +endif + +# END # include $(_cdbs_class_path)/makefile-vars.mk$(_cdbs_makefile_suffix) + +cdbs_make_flavors = $(sort $(DEB_MAKE_FLAVORS)) +cdbs_make_builddir_check = $(if $(call cdbs_streq,$(DEB_BUILDDIR),$(DEB_SRCDIR)),\ + $(error DEB_MAKE_FLAVORS in use: \ + DEB_BUILDDIR must be different from DEB_SRCDIR$(comma) \ + and needs to be declared before including makefile.mk)) +cdbs_make_build_stamps = $(if $(cdbs_make_flavors),\ + $(cdbs_make_builddir_check)\ + $(patsubst %,debian/stamp-makefile-build/%,\ + $(cdbs_make_flavors)),\ + debian/stamp-makefile-build) +cdbs_make_install_stamps = $(if $(cdbs_make_flavors),\ + $(cdbs_make_builddir_check)\ + $(patsubst %,debian/stamp-makefile-install/%,\ + $(cdbs_make_flavors)),\ + debian/stamp-makefile-install) +cdbs_make_check_stamps = $(if $(cdbs_make_flavors),\ + $(cdbs_make_builddir_check)\ + $(patsubst %,debian/stamp-makefile-check/%,\ + $(cdbs_make_flavors)),\ + debian/stamp-makefile-check) +cdbs_make_clean_nonstamps = $(if $(cdbs_make_flavors),\ + $(patsubst %,makefile-clean/%,$(cdbs_make_flavors)),\ + makefile-clean) +cdbs_make_curflavor = $(strip $(if $(cdbs_make_flavors),\ + $(filter-out %/,$(subst /,/ ,$@)))) +cdbs_make_curbuilddir = $(strip $(if $(cdbs_make_flavors),\ + $(subst @FLAVOR@,$(cdbs_make_curflavor),$(or $(strip \ + $(DEB_MAKE_BUILDDIRSKEL_$(cdbs_make_curflavor))),$(strip \ + $(DEB_MAKE_BUILDDIRSKEL)))),\ + $(cdbs_curbuilddir))) +cdbs_make_curdestdir = $(strip $(if $(cdbs_make_flavors),\ + $(subst @FLAVOR@,$(cdbs_make_curflavor),$(or $(strip \ + $(DEB_MAKE_DESTDIRSKEL_$(cdbs_make_curflavor))),$(strip \ + $(DEB_MAKE_DESTDIRSKEL)))),\ + $(cdbs_curdestdir))) + +DEB_PHONY_RULES += makefile-clean $(cdbs_make_clean_nonstamps) + +pre-build:: + $(if $(cdbs_make_flavors),\ + mkdir -p \ + debian/stamp-makefile-build \ + debian/stamp-makefile-install) + $(and $(cdbs_make_flavors),$(DEB_MAKE_CHECK_TARGET),\ + mkdir -p debian/stamp-makefile-check) + +common-build-arch common-build-indep:: $(cdbs_make_build_stamps) +$(cdbs_make_build_stamps): + +$(DEB_MAKE_INVOKE) $(DEB_MAKE_BUILD_TARGET) + touch $@ + +cleanbuilddir:: makefile-clean +makefile-clean:: $(if $(cdbs_make_flavors),$(cdbs_make_clean_nonstamps)) + $(if $(cdbs_make_flavors),\ + -rmdir --ignore-fail-on-non-empty \ + debian/stamp-makefile-build \ + debian/stamp-makefile-install,\ + rm -f \ + debian/stamp-makefile-build \ + debian/stamp-makefile-install) + +$(cdbs_make_clean_nonstamps):: + $(if $(DEB_MAKE_CLEAN_TARGET),\ + +-$(DEB_MAKE_INVOKE) -k $(DEB_MAKE_CLEAN_TARGET),\ + $(call cdbs_warn,DEB_MAKE_CLEAN_TARGET unset$(comma) \ + not running clean)) + $(if $(cdbs_make_flavors),\ + rm -f \ + $(@:makefile-clean%=debian/stamp-makefile-build%) \ + $(@:makefile-clean%=debian/stamp-makefile-install%)) + +common-install-arch common-install-indep:: common-install-impl +common-install-impl:: $(cdbs_make_install_stamps) +$(cdbs_make_install_stamps):: + $(if $(DEB_MAKE_INSTALL_TARGET),\ + +$(DEB_MAKE_INVOKE) $(DEB_MAKE_INSTALL_TARGET),\ + $(call cdbs_warn,DEB_MAKE_INSTALL_TARGET unset$(comma) \ + skipping default makefile.mk common-install target)) + $(if $(DEB_MAKE_INSTALL_TARGET),\ + touch $@) + +ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS))) +common-build-arch common-build-indep:: $(cdbs_make_check_stamps) +$(cdbs_make_check_stamps) : debian/stamp-makefile-check% : debian/stamp-makefile-build% + $(if $(DEB_MAKE_CHECK_TARGET),\ + +$(DEB_MAKE_INVOKE) $(DEB_MAKE_CHECK_TARGET),\ + $(call cdbs_warn,DEB_MAKE_CHECK_TARGET unset$(comma) \ + not running checks)) + $(if $(DEB_MAKE_CHECK_TARGET),\ + touch $@) + +makefile-clean:: + $(if $(DEB_MAKE_CHECK_TARGET),\ + $(if $(cdbs_make_flavors),\ + -rmdir --ignore-fail-on-non-empty \ + debian/stamp-makefile-check,\ + rm -f debian/stamp-makefile-check)) + +$(cdbs_make_clean_nonstamps):: + $(if $(cdbs_make_flavors),\ + rm -f $(@:makefile-clean%=debian/stamp-makefile-check%)) +endif + +endif + + +# END # include $(_cdbs_class_path)/makefile.mk$(_cdbs_makefile_suffix) + +DEB_MAKE_INSTALL_TARGET ?= install DESTDIR=$(cdbs_make_curdestdir) +# FIXME: Restructure to allow early override +DEB_MAKE_CLEAN_TARGET = distclean +#DEB_MAKE_CHECK_TARGET = check + +DEB_AC_AUX_DIR ?= $(DEB_SRCDIR) + +# Declare CC and CXX only if explicitly set in environment or makefile +# (i.e. skip if builtin make default would have been used) +# This is needed for proper cross-compilation - see bug#450483) +DEB_CONFIGURE_SCRIPT_ENV ?= \ + $(call cdbs_set_nondefaultvars,CC CXX) \ + CFLAGS="$(CFLAGS)" \ + CXXFLAGS="$(CXXFLAGS)" \ + CPPFLAGS="$(CPPFLAGS)" \ + LDFLAGS="$(LDFLAGS)" + +DEB_CONFIGURE_SCRIPT ?= $(CURDIR)/$(DEB_SRCDIR)/configure + +# Provide --host only if different from --build, to support cross- +# compiling with autotools 2.52+ without slowing down normal builds. +# Cross-compiling with autotools 2.13 is unsupported, as it needs +# other tweaks (more info at autotools-dev README.Debian) +DEB_CONFIGURE_CROSSBUILD_ARGS ?= \ + --build=$(DEB_BUILD_GNU_TYPE) \ + $(if $(cdbs_crossbuild),\ + --host=$(DEB_HOST_GNU_TYPE)) + +DEB_CONFIGURE_PREFIX ?=/usr +DEB_CONFIGURE_INCLUDEDIR ?= "\$${prefix}/include" +DEB_CONFIGURE_MANDIR ?= "\$${prefix}/share/man" +DEB_CONFIGURE_INFODIR ?= "\$${prefix}/share/info" +DEB_CONFIGURE_SYSCONFDIR ?= /etc +DEB_CONFIGURE_LOCALSTATEDIR ?= /var +DEB_CONFIGURE_LIBEXECDIR ?= "\$${prefix}/lib/$(DEB_SOURCE_PACKAGE)" +# --srcdir=. is required because otherwise configure wants to analyse +# $0 to see whether a VPATH build is needed. This tells it with +# absolute certainly that this is NOT a VPATH build. +DEB_CONFIGURE_PATH_ARGS ?= \ + --prefix=$(DEB_CONFIGURE_PREFIX) \ + --includedir=$(DEB_CONFIGURE_INCLUDEDIR) \ + --mandir=$(DEB_CONFIGURE_MANDIR) \ + --infodir=$(DEB_CONFIGURE_INFODIR) \ + --sysconfdir=$(DEB_CONFIGURE_SYSCONFDIR) \ + --localstatedir=$(DEB_CONFIGURE_LOCALSTATEDIR) \ + --libexecdir=$(DEB_CONFIGURE_LIBEXECDIR) \ + $(if $(subst $(DEB_SRCDIR),,$(cdbs_make_curbuilddir)),\ + ,\ + --srcdir=.) + +DEB_CONFIGURE_NORMAL_ARGS ?= \ + $(DEB_CONFIGURE_CROSSBUILD_ARGS) \ + $(DEB_CONFIGURE_PATH_ARGS) \ + --disable-maintainer-mode \ + --disable-dependency-tracking \ + --disable-silent-rules + +# all environment settings for autotools configure execution +# (potentially extended by other snippets) +cdbs_autotools_configure_env = $(DEB_CONFIGURE_SCRIPT_ENV) + +DEB_CONFIGURE_INVOKE ?= cd $(cdbs_make_curbuilddir) && \ + $(cdbs_autotools_configure_env) \ + $(DEB_CONFIGURE_SCRIPT) \ + $(DEB_CONFIGURE_NORMAL_ARGS) \ + $(DEB_CONFIGURE_DEBUG_ARGS) + +#DEB_CONFIGURE_EXTRA_FLAGS = + +endif + + +# END # include $(_cdbs_class_path)/autotools-vars.mk$(_cdbs_makefile_suffix) + +# Compatibility blurb, will be eventualy removed +ifneq (,$(DEB_AUTO_UPDATE_AUTOMAKE)) +ifeq (,$(DEB_AUTO_UPDATE_ACLOCAL)) +$(call cdbs_warn,DEB_AUTO_UPDATE_AUTOMAKE will eventually stop implying \ + DEB_AUTO_UPDATE_ACLOCAL. If you meant aclocal.m4 to be \ + regenerated, please use DEB_AUTO_UPDATE_ACLOCAL.) +DEB_AUTO_UPDATE_ACLOCAL ?= $(DEB_AUTO_UPDATE_AUTOMAKE) +endif +endif + +# Some update rules are useless on their own +ifeq (pre,$(DEB_AUTO_UPDATE_LIBTOOL)) +ifeq (,$(DEB_AUTO_UPDATE_ACLOCAL)) +$(call cdbs_warn,DEB_AUTO_UPDATE_LIBTOOL requires DEB_AUTO_UPDATE_ACLOCAL.) +endif +endif +ifneq (,$(DEB_AUTO_UPDATE_ACLOCAL)) +ifeq (,$(DEB_AUTO_UPDATE_AUTOCONF)) +$(call cdbs_warn,DEB_AUTO_UPDATE_ACLOCAL requires DEB_AUTO_UPDATE_AUTOCONF.) +endif +endif + +DEB_ACLOCAL_ARGS ?= $(if $(wildcard $(DEB_SRCDIR)/m4),\ + -I m4) + +# resolve make rule from autotools command version hints +# usage: $(call _cdbs_autotools_invoke,$(VERSION),$(VERSIONEDBINARY),$(BINARY),$(LEGACY)) +# * when VERSION contains comma: return "$(BINARY)" +# * else, when LEGACY exist: return $$(which "$(VERSIONEDBINARY)$(VERSION)" || which "$(BINARY)") +# * else: return "$(VERSIONEDBINARY)$(VERSION)" +# see also autotools-vars.mk +_cdbs_autotools_invoke = $(if $(findstring $(comma),$1),\ + $3,\ + $(if $4,\ + $$(which "$2$1" || which "$3"),\ + $2$1)) + +common-configure-arch common-configure-indep:: debian/stamp-autotools-files +debian/stamp-autotools-files: + $(if $(filter pre,$(DEB_AUTO_UPDATE_LIBTOOL)),\ + cd $(DEB_SRCDIR) && \ + libtoolize -c -f) + $(if $(DEB_AUTO_UPDATE_AUTOPOINT),\ + cd $(DEB_SRCDIR) && \ + $(call _cdbs_autotools_invoke,$(DEB_AUTO_UPDATE_AUTOPOINT),autopoint,autopoint) \ + $(DEB_AUTOPOINT_ARGS)) + $(if $(DEB_AUTO_UPDATE_ACLOCAL),\ + cd $(DEB_SRCDIR) && \ + $(call _cdbs_autotools_invoke,$(DEB_AUTO_UPDATE_ACLOCAL),aclocal-,aclocal) \ + $(DEB_ACLOCAL_ARGS)) + $(if $(DEB_AUTO_UPDATE_AUTOCONF),\ + $(if $(wildcard $(DEB_SRCDIR)/configure.ac $(DEB_SRCDIR)/configure.in),\ + cd $(DEB_SRCDIR) && \ + $(call _cdbs_autotools_invoke,$(DEB_AUTO_UPDATE_AUTOCONF),autoconf,autoconf,legacy) \ + $(DEB_AUTOCONF_ARGS))) + $(if $(DEB_AUTO_UPDATE_AUTOHEADER),\ + $(if $(wildcard $(DEB_SRCDIR)/configure.ac $(DEB_SRCDIR)/configure.in),\ + cd $(DEB_SRCDIR) && \ + $(call _cdbs_autotools_invoke,$(DEB_AUTO_UPDATE_AUTOHEADER),autoheader,autoheader,legacy) \ + $(DEB_AUTOHEADER_ARGS))) + $(if $(DEB_AUTO_UPDATE_AUTOMAKE),\ + $(if $(wildcard $(DEB_SRCDIR)/Makefile.am),\ + cd $(DEB_SRCDIR) && \ + $(call _cdbs_autotools_invoke,$(DEB_AUTO_UPDATE_AUTOMAKE),automake-,automake) \ + $(DEB_AUTOMAKE_ARGS))) + touch debian/stamp-autotools-files + +clean:: + rm -f debian/stamp-autotools-files + +endif + +# END # include $(_cdbs_class_path)/autotools-files.mk$(_cdbs_makefile_suffix) + + +cdbs_autotools_configure_stamps = $(if $(cdbs_make_flavors),\ + $(cdbs_make_builddir_check)$(patsubst %,debian/stamp-autotools/%,$(cdbs_make_flavors)),\ + debian/stamp-autotools) + +cdbs_configure_flags += $(DEB_CONFIGURE_FLAGS_$(cdbs_make_curflavor)) + +# Overriden from makefile-vars.mk. We pass CFLAGS and friends to +# ./configure, so no need to pass them to make. +# FIXME: Restructure to allow early override +DEB_MAKE_EXTRA_ARGS = $(DEB_MAKE_PARALLEL) + +pre-build:: + $(if $(cdbs_make_flavors),mkdir -p debian/stamp-autotools) + +common-configure-arch common-configure-indep:: common-configure-impl +common-configure-impl:: $(cdbs_autotools_configure_stamps) +$(cdbs_autotools_configure_stamps): + chmod a+x $(DEB_CONFIGURE_SCRIPT) + $(if $(call cdbs_streq,$(cdbs_make_curbuilddir),$(DEB_BUILDDIR_$(cdbs_curpkg))),\ + ,\ + mkdir -p $(cdbs_make_curbuilddir)) + $(strip $(DEB_CONFIGURE_INVOKE) \ + $(cdbs_configure_flags) \ + $(DEB_CONFIGURE_EXTRA_FLAGS) \ + $(DEB_CONFIGURE_USER_FLAGS)) + $(if $(filter post,$(DEB_AUTO_UPDATE_LIBTOOL)),\ + $(if $(wildcard $(cdbs_make_curbuilddir)/libtool),\ + cp -f /usr/bin/libtool $(cdbs_make_curbuilddir)/libtool)) + touch $@ + +makefile-clean:: + $(if $(cdbs_make_flavors),\ + -rmdir --ignore-fail-on-non-empty \ + debian/stamp-autotools,\ + rm -f debian/stamp-autotools) + +$(cdbs_make_clean_nonstamps):: + $(if $(call cdbs_streq,$(cdbs_make_curbuilddir),$(DEB_BUILDDIR_$(cdbs_curpkg))),\ + ,\ + -rmdir --ignore-fail-on-non-empty \ + $(cdbs_make_curbuilddir)) + $(if $(cdbs_make_flavors),\ + rm -f $(@:makefile-clean%=debian/stamp-autotools%)) + +endif diff --git a/scripts/obs/debian.rules b/scripts/obs/debian.rules index 020f397914..fab75fc0f1 100755 --- a/scripts/obs/debian.rules +++ b/scripts/obs/debian.rules @@ -1,7 +1,26 @@ #!/usr/bin/make -f include /usr/share/cdbs/1/rules/debhelper.mk --include /usr/share/cdbs/1/class/autotools.mk + +ifneq (,$(shell ls -1 /usr/share/cdbs/1/class/autotools.mk || true)) +include /usr/share/cdbs/1/class/autotools.mk +else +# In 2026, Debian obsoletes and removes CDBS and its scripts +# Stashing https://salsa.debian.org/debian/cdbs/-/blob/a110afb99997b94de6acb1e0758210cdfd8ec3dd/1/class/autotools.mk.in +# and neighbors +ifneq (,$(shell ls -1 debian/cdbs-autotools.mk || true)) +include debian/cdbs-autotools.mk +else +ifneq (,$(shell ls -1 debian.cdbs-autotools.mk || true)) +include debian.cdbs-autotools.mk +else +ifneq (,$(shell ls -1 cdbs-autotools.mk || true)) +include cdbs-autotools.mk +endif +endif +endif +endif + -include /usr/share/cdbs/1/class/python-module.mk -include /usr/share/cdbs/1/rules/autoreconf.mk From 0c71ca89af987e35fb1743e26b73ed3bd90f84bb Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 3 Feb 2026 13:58:10 +0100 Subject: [PATCH 103/198] configure.ac: simplify checks for UPower driver and nut-scanner support [#3293] Signed-off-by: Jim Klimov --- configure.ac | 36 +++++++++++------------------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/configure.ac b/configure.ac index ee36725c23..e7bc787c86 100644 --- a/configure.ac +++ b/configure.ac @@ -2854,7 +2854,7 @@ dnl Platform-dependent drivers, currently their detection code is directly dnl spelled out in configure.ac NUT_ARG_WITH([macosx_ups], [build and install Mac OS X Power Sources meta-driver], [auto]) NUT_ARG_WITH([linux_i2c], [build and install i2c drivers], [auto]) -NUT_ARG_WITH([upower], [build and install UPower driver (requires GLib/GIO)], [auto]) +NUT_ARG_WITH([upower], [build and install UPower driver and nut-scanner support (requires GLib/GIO)], [auto]) NUT_CHECK_LIBGLIB dnl A Python GUI client application for the sysadmin desktop @@ -3005,22 +3005,6 @@ NUT_REPORT_FEATURE([enable Avahi support], [${nut_with_avahi}], [], [WITH_AVAHI], [Define to enable Avahi support]) dnl ---------------------------------------------------------------------- -dnl checks related to --with-upower - -dnl ${nut_with_upower}: any value except "yes" or "no" is treated as "auto". -if test "${nut_with_upower}" = "yes" -a "${nut_have_libglib}" != "yes"; then - AC_MSG_ERROR([GLib/GIO libraries not found, required for UPower support]) -fi - -if test "${nut_with_upower}" != "no"; then - nut_with_upower="${nut_have_libglib}" -fi - -NUT_REPORT_FEATURE([enable UPower support], [${nut_with_upower}], [], - [WITH_UPOWER], [Define to enable UPower support]) - -dnl ---------------------------------------------------------------------- - dnl checks related to --with-powerman dnl ${nut_with_powerman}: any value except "yes" or "no" is treated as "auto". @@ -3163,27 +3147,29 @@ NUT_REPORT_DRIVER([build Mac OS X meta-driver], [WITH_MACOSX], [Define to enable Mac OS X meta-driver]) dnl ---------------------------------------------------------------------- -dnl Check if we have detected libGLib / libGIO above (Required for UPower driver) +dnl checks related to --with-upower +dnl Check if we have detected libGLib / libGIO above (Required for the +dnl nut-upower driver and/or nut-scanner UPower support) dnl NOTE: Do not confuse libglib{2} (GNOME) with glibc (part of compiler) dnl ---------------------------------------------------------------------- -AC_MSG_CHECKING([whether to build nut-upower driver]) -nut_with_upower=no +AC_MSG_CHECKING([whether to build nut-upower driver and nut-scanner support]) AS_IF([test "${nut_have_libglib}${nut_have_libgio}" = "yesyes"], [ - AS_CASE(["${with_upower}"], + AS_CASE(["${nut_with_upower}"], [yes|auto], [nut_with_upower=yes] ) ], [ - AS_CASE(["${with_upower}"], + AS_CASE(["${nut_with_upower}"], [yes], [AC_MSG_ERROR([GLib/GIO not found but requested via --with-upower])], - [auto],[AC_MSG_WARN([GLib/GIO not found. The 'upower' driver will not be built.])] + [auto],[AC_MSG_WARN([GLib/GIO not found. The 'nut-upower' driver will not be built.])] ) + nut_with_upower=no ]) AC_MSG_RESULT(${nut_with_upower}) -NUT_REPORT_DRIVER([build UPower driver], +NUT_REPORT_DRIVER([build UPower driver and nut-scanner support], [${nut_with_upower}], [], - [WITH_UPOWER], [Define to build UPower driver]) + [WITH_UPOWER], [Define to build UPower driver and nut-scanner support]) dnl ---------------------------------------------------------------------- dnl checks related to --with_linux_i2c From 329b208baa01fe4e281841eb604dea94f6146967 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 3 Feb 2026 15:07:03 +0100 Subject: [PATCH 104/198] drivers/vertiv-psi5-mib.{c,h}: fix markup and (C) headers, include "main.h" missed before [#3299] Signed-off-by: Jim Klimov --- drivers/vertiv-psi5-mib.c | 182 +++++++++++++++++++++----------------- drivers/vertiv-psi5-mib.h | 59 ++++++------ 2 files changed, 132 insertions(+), 109 deletions(-) diff --git a/drivers/vertiv-psi5-mib.c b/drivers/vertiv-psi5-mib.c index 3332ca96e0..e3d4066d3f 100644 --- a/drivers/vertiv-psi5-mib.c +++ b/drivers/vertiv-psi5-mib.c @@ -1,80 +1,102 @@ -/* drivers/vertiv-psi5-mib.c */ -#include "vertiv-psi5-mib.h" - -/* Vertiv PSI5-750MT120 Mapping - Monitoring: Based on integer branch at .1.3.6.1.4.1.476.1.42.3.9.30... - Control: Based on standard Liebert Environmental MIB at .1.3.6.1.4.1.476.1.42.3.3.5... */ - -static snmp_info_t vertiv_psi5_mib[] = { - /* Load and Temperature */ - { "ups.load", 0, SU_INFOTYPE_INT, NULL, - ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.5861", - NULL, NULL }, - { "ups.temperature", 0, SU_INFOTYPE_INT, NULL, - ".1.3.6.1.4.1.476.1.42.3.9.30.1.10.1.2.1.4291", - NULL, NULL }, - - /* Battery */ - { "battery.charge", 0, SU_INFOTYPE_INT, NULL, - ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4153", - NULL, NULL }, - { "battery.runtime", 0, SU_INFOTYPE_INT, NULL, - ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4150", - NULL, NULL }, /* Raw value is minutes */ - { "battery.voltage", 0, SU_INFOTYPE_INT, NULL, - ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4148", - NULL, NULL }, - - /* Input */ - { "input.voltage", 0, SU_INFOTYPE_INT, NULL, - ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4096", - SU_FLAG_OK, NULL }, /* Scale: 0.1 */ - { "input.frequency", 0, SU_INFOTYPE_INT, NULL, - ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4105", - SU_FLAG_OK, NULL }, /* Scale: 0.1 */ - - /* Output */ - { "output.voltage", 0, SU_INFOTYPE_INT, NULL, - ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4385", - SU_FLAG_OK, NULL }, /* Scale: 0.1 */ - { "output.current", 0, SU_INFOTYPE_INT, NULL, - ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4204", - SU_FLAG_OK, NULL }, /* Scale: 0.1 */ - { "output.power", 0, SU_INFOTYPE_INT, NULL, - ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4208", - SU_FLAG_OK, NULL }, - - /* Shutdown / Restart Control - Derived from lgpEnvControl (LIEBERT-GP-ENVIRONMENTAL-MIB) */ - { "ups.delay.shutdown", 0, SU_INFOTYPE_INT, - ".1.3.6.1.4.1.476.1.42.3.3.5.1.0", - SU_FLAG_RW | SU_FLAG_OK, NULL }, - { "ups.delay.start", 0, SU_INFOTYPE_INT, - ".1.3.6.1.4.1.476.1.42.3.3.5.2.0", - SU_FLAG_RW | SU_FLAG_OK, NULL }, - - /* Status Flags */ - { "ups.alarm", 0, SU_INFOTYPE_INT, NULL, - ".1.3.6.1.4.1.476.1.42.3.9.20.1.20.1.2.100.6182", - NULL, NULL }, /* Replace Battery */ - { "ups.alarm", 0, SU_INFOTYPE_INT, NULL, - ".1.3.6.1.4.1.476.1.42.3.9.20.1.20.1.2.100.4233", - NULL, NULL }, /* Inverter Failure */ - { "ups.alarm", 0, SU_INFOTYPE_INT, NULL, - ".1.3.6.1.4.1.476.1.42.3.9.20.1.20.1.2.100.5806", - NULL, NULL }, /* Overload */ - - /* End of list */ - { NULL, 0, 0, NULL, NULL, NULL, NULL } -}; - -snmp_subdriver_t vertiv_psi5_subdriver = { - "vertiv-psi5", - "1.0", - ".1.3.6.1.4.1.476.1.42", /* SysOID for Vertiv/Liebert */ - vertiv_psi5_mib, - NULL, - NULL, - NULL, - NULL -}; +/* vertiv-psi5-mib.h - Driver for Vertiv Liebert PSI5 UPS + * + * Copyright (C) + * 2026 jawz101 + Gemini + * 2026 Jim Klimov - cleanup + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* drivers/vertiv-psi5-mib.c */ +#include "vertiv-psi5-mib.h" + +/* Vertiv PSI5-750MT120 Mapping + Monitoring: Based on integer branch at .1.3.6.1.4.1.476.1.42.3.9.30... + Control: Based on standard Liebert Environmental MIB at .1.3.6.1.4.1.476.1.42.3.3.5... */ + +static snmp_info_t vertiv_psi5_mib[] = { + /* Load and Temperature */ + { "ups.load", 0, SU_INFOTYPE_INT, NULL, + ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.5861", + NULL, NULL }, + { "ups.temperature", 0, SU_INFOTYPE_INT, NULL, + ".1.3.6.1.4.1.476.1.42.3.9.30.1.10.1.2.1.4291", + NULL, NULL }, + + /* Battery */ + { "battery.charge", 0, SU_INFOTYPE_INT, NULL, + ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4153", + NULL, NULL }, + { "battery.runtime", 0, SU_INFOTYPE_INT, NULL, + ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4150", + NULL, NULL }, /* Raw value is minutes */ + { "battery.voltage", 0, SU_INFOTYPE_INT, NULL, + ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4148", + NULL, NULL }, + + /* Input */ + { "input.voltage", 0, SU_INFOTYPE_INT, NULL, + ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4096", + SU_FLAG_OK, NULL }, /* Scale: 0.1 */ + { "input.frequency", 0, SU_INFOTYPE_INT, NULL, + ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4105", + SU_FLAG_OK, NULL }, /* Scale: 0.1 */ + + /* Output */ + { "output.voltage", 0, SU_INFOTYPE_INT, NULL, + ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4385", + SU_FLAG_OK, NULL }, /* Scale: 0.1 */ + { "output.current", 0, SU_INFOTYPE_INT, NULL, + ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4204", + SU_FLAG_OK, NULL }, /* Scale: 0.1 */ + { "output.power", 0, SU_INFOTYPE_INT, NULL, + ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4208", + SU_FLAG_OK, NULL }, + + /* Shutdown / Restart Control + Derived from lgpEnvControl (LIEBERT-GP-ENVIRONMENTAL-MIB) */ + { "ups.delay.shutdown", 0, SU_INFOTYPE_INT, + ".1.3.6.1.4.1.476.1.42.3.3.5.1.0", + SU_FLAG_RW | SU_FLAG_OK, NULL }, + { "ups.delay.start", 0, SU_INFOTYPE_INT, + ".1.3.6.1.4.1.476.1.42.3.3.5.2.0", + SU_FLAG_RW | SU_FLAG_OK, NULL }, + + /* Status Flags */ + { "ups.alarm", 0, SU_INFOTYPE_INT, NULL, + ".1.3.6.1.4.1.476.1.42.3.9.20.1.20.1.2.100.6182", + NULL, NULL }, /* Replace Battery */ + { "ups.alarm", 0, SU_INFOTYPE_INT, NULL, + ".1.3.6.1.4.1.476.1.42.3.9.20.1.20.1.2.100.4233", + NULL, NULL }, /* Inverter Failure */ + { "ups.alarm", 0, SU_INFOTYPE_INT, NULL, + ".1.3.6.1.4.1.476.1.42.3.9.20.1.20.1.2.100.5806", + NULL, NULL }, /* Overload */ + + /* End of list */ + { NULL, 0, 0, NULL, NULL, NULL, NULL } +}; + +snmp_subdriver_t vertiv_psi5_subdriver = { + "vertiv-psi5", + "1.00", + ".1.3.6.1.4.1.476.1.42", /* SysOID for Vertiv/Liebert */ + vertiv_psi5_mib, + NULL, + NULL, + NULL, + NULL +}; diff --git a/drivers/vertiv-psi5-mib.h b/drivers/vertiv-psi5-mib.h index ffbeff425a..6faa46f69d 100644 --- a/drivers/vertiv-psi5-mib.h +++ b/drivers/vertiv-psi5-mib.h @@ -1,29 +1,30 @@ -/* vertiv-psi5-mib.h - Driver for Vertiv Liebert PSI5 UPS - * - * Copyright (C) - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef VERTIV_PSI5_MIB_H -#define VERTIV_PSI5_MIB_H - -#include "snmp-ups.h" - -extern snmp_subdriver_t vertiv_psi5_subdriver; - -#endif /* VERTIV_PSI5_MIB_H */ \ No newline at end of file +/* vertiv-psi5-mib.h - Driver for Vertiv Liebert PSI5 UPS + * + * Copyright (C) + * 2026 jawz101 + Gemini + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef VERTIV_PSI5_MIB_H +#define VERTIV_PSI5_MIB_H + +#include "main.h" +#include "snmp-ups.h" + +extern snmp_subdriver_t vertiv_psi5_subdriver; + +#endif /* VERTIV_PSI5_MIB_H */ From 92556b217e1ff825d1f0ff94683c2294076ea01b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 3 Feb 2026 16:08:18 +0100 Subject: [PATCH 105/198] m4/ax_realpath_lib.m4: refactor with LIBRARY_PATH; clean up after ourselves [#2431] Signed-off-by: Jim Klimov --- m4/ax_realpath_lib.m4 | 60 ++++++++++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/m4/ax_realpath_lib.m4 b/m4/ax_realpath_lib.m4 index 8ed8775a48..66b63e5c62 100644 --- a/m4/ax_realpath_lib.m4 +++ b/m4/ax_realpath_lib.m4 @@ -75,6 +75,26 @@ AC_DEFUN([AX_REALPATH_LIB], ], [myLIBNAME_LD="-l$myLIBNAME"] dnl best-effort... ) + # Colon-separated search path for libraries specified + # in compiler/linker flags we have discovered; used by + # gcc at least in linker mode + myLIBRARY_PATH="" + for TOKEN in $CFLAGS $LDFLAGS $LIBS ; do + D="" + case "$TOKEN" in + -R*|-L*) D="`echo \"$TOKEN\" | sed 's,^-@<:@RL@:>@,,'`" ;; + -Wl,-R*) D="`echo \"$TOKEN\" | sed 's,^-Wl\,-R,,'`" ;; + -Wl,-rpath,*) D="`echo \"$TOKEN\" | sed 's,^-Wl\,-rpath\,,,'`" ;; + esac + if test -z "$D" || test ! -d "$D" ; then continue ; fi + case "${myLIBRARY_PATH}" in + "") myLIBRARY_PATH="$D" ;; + "$D"|*":$D"|*":$D:"*|"$D:"*) ;; + *) myLIBRARY_PATH="${myLIBRARY_PATH}:${D}" ;; + esac + done + unset D + AC_MSG_CHECKING([for real path to $1 (re-parsed as ${myLIBNAME} likely file name / ${myLIBNAME_LD} linker arg)]) myLIBPATH="" AS_CASE(["${target_os}"], @@ -112,7 +132,7 @@ AC_DEFUN([AX_REALPATH_LIB], "${MSYSTEM_PREFIX}/lib" \ "${MINGW_PREFIX}/bin" \ "${MINGW_PREFIX}/lib" \ - `${CC} --print-search-dirs 2>/dev/null | ${GREP} libraries: | sed 's,^@<:@^=@:>@*=,:,' | sed 's,\(@<:@:;@:>@\)\(@<:@A-Z@:>@\):/,:/\2/,g' | tr ':' '\n'` \ + `LIBRARY_PATH="${myLIBRARY_PATH}" ${CC} --print-search-dirs 2>/dev/null | ${GREP} libraries: | sed 's,^@<:@^=@:>@*=,:,' | sed 's,\(@<:@:;@:>@\)\(@<:@A-Z@:>@\):/,:/\2/,g' | tr ':' '\n'` \ ; do dnl NOTE: Here we check myLIBPATH detected above, dnl in fallback below we would retry with a myLIBNAME @@ -126,22 +146,15 @@ AC_DEFUN([AX_REALPATH_LIB], ) ]) ], [ dnl # POSIX/MacOS builds - { myLIBPATH="`${CC} --print-file-name=\"$myLIBNAME\"`" && test -n "$myLIBPATH" && test -s "$myLIBPATH" ; } \ - || { myLIBPATH="`${CC} $CFLAGS --print-file-name=\"$myLIBNAME\"`" && test -n "$myLIBPATH" && test -s "$myLIBPATH" ; } \ - || { myLIBPATH="`${CC} $CFLAGS $LDFLAGS $LIBS --print-file-name=\"$myLIBNAME\"`" && test -n "$myLIBPATH" && test -s "$myLIBPATH" ; } \ + { myLIBPATH="`LIBRARY_PATH=\"${myLIBRARY_PATH}\" ${CC} --print-file-name=\"$myLIBNAME\"`" && test -n "$myLIBPATH" && test -s "$myLIBPATH" ; } \ + || { myLIBPATH="`LIBRARY_PATH=\"${myLIBRARY_PATH}\" ${CC} $CFLAGS --print-file-name=\"$myLIBNAME\"`" && test -n "$myLIBPATH" && test -s "$myLIBPATH" ; } \ + || { myLIBPATH="`LIBRARY_PATH=\"${myLIBRARY_PATH}\" ${CC} $CFLAGS $LDFLAGS $LIBS --print-file-name=\"$myLIBNAME\"`" && test -n "$myLIBPATH" && test -s "$myLIBPATH" ; } \ || myLIBPATH="" ] ) - AS_IF([test -z "${myLIBPATH}"], [ - for TOKEN in $CFLAGS $LDFLAGS $LIBS ; do - D="" - case "$TOKEN" in - -R*|-L*) D="`echo \"$TOKEN\" | sed 's,^-[RL],,'`" ;; - -Wl,-R*) D="`echo \"$TOKEN\" | sed 's,^-Wl\,-R,,'`" ;; - -Wl,-rpath,*) D="`echo \"$TOKEN\" | sed 's,^-Wl\,-rpath\,,,'`" ;; - esac - if test -z "$D" || test ! -d "$D" ; then continue ; fi + AS_IF([test -z "${myLIBPATH}" -a -n "${myLIBRARY_PATH}"], [ + for D in `echo "${myLIBRARY_PATH}" | tr ':' ' '` ; do if test -s "$D/${myLIBNAME}" 2>/dev/null ; then myLIBPATH="$D/${myLIBNAME}" break @@ -154,7 +167,7 @@ AC_DEFUN([AX_REALPATH_LIB], for D in \ "/usr/${target}/bin" \ "/usr/${target}/lib" \ - `${CC} --print-search-dirs 2>/dev/null | ${GREP} libraries: | sed 's,^@<:@^=@:>@*=,:,' | sed 's,\(@<:@:;@:>@\)\(@<:@A-Z@:>@\):/,:/\2/,g' | tr ':' '\n'` \ + `LIBRARY_PATH="${myLIBRARY_PATH}" ${CC} --print-search-dirs 2>/dev/null | ${GREP} libraries: | sed 's,^@<:@^=@:>@*=,:,' | sed 's,\(@<:@:;@:>@\)\(@<:@A-Z@:>@\):/,:/\2/,g' | tr ':' '\n'` \ ; do if test -s "$D/${myLIBNAME}" 2>/dev/null ; then myLIBPATH="$D/${myLIBNAME}" @@ -170,13 +183,13 @@ AC_DEFUN([AX_REALPATH_LIB], dnl Try MacOS-style LD as fallback; expecting strings like dnl ld: warning: /usr/local/lib/libneon.dylib, ignoring unexpected dylib file my_uname_m="`uname -m`" - { myLIBPATH="`${LD} -dynamic -r -arch \"${target_cpu}\" -search_dylibs_first \"${myLIBNAME_LD}\" 2>&1 | ${GREP} -w dylib | sed 's/^@<:@^\/@:>@*\(\/.*\.dylib\),.*$/\1/'`" && test -n "$myLIBPATH" && test -s "$myLIBPATH" ; } \ - || { myLIBPATH="`${LD} $LDFLAGS -dynamic -r -arch \"${target_cpu}\" -search_dylibs_first \"${myLIBNAME_LD}\" 2>&1 | ${GREP} -w dylib | sed 's/^@<:@^\/@:>@*\(\/.*\.dylib\),.*$/\1/'`" && test -n "$myLIBPATH" && test -s "$myLIBPATH" ; } \ - || { myLIBPATH="`${LD} $LDFLAGS $LIBS -dynamic -r -arch \"${target_cpu}\" -search_dylibs_first \"${myLIBNAME_LD}\" 2>&1 | ${GREP} -w dylib | sed 's/^@<:@^\/@:>@*\(\/.*\.dylib\),.*$/\1/'`" && test -n "$myLIBPATH" && test -s "$myLIBPATH" ; } \ + { myLIBPATH="`LIBRARY_PATH=\"${myLIBRARY_PATH}\" ${LD} -dynamic -r -arch \"${target_cpu}\" -search_dylibs_first \"${myLIBNAME_LD}\" 2>&1 | ${GREP} -w dylib | sed 's/^@<:@^\/@:>@*\(\/.*\.dylib\),.*$/\1/'`" && test -n "$myLIBPATH" && test -s "$myLIBPATH" ; } \ + || { myLIBPATH="`LIBRARY_PATH=\"${myLIBRARY_PATH}\" ${LD} $LDFLAGS -dynamic -r -arch \"${target_cpu}\" -search_dylibs_first \"${myLIBNAME_LD}\" 2>&1 | ${GREP} -w dylib | sed 's/^@<:@^\/@:>@*\(\/.*\.dylib\),.*$/\1/'`" && test -n "$myLIBPATH" && test -s "$myLIBPATH" ; } \ + || { myLIBPATH="`LIBRARY_PATH=\"${myLIBRARY_PATH}\" ${LD} $LDFLAGS $LIBS -dynamic -r -arch \"${target_cpu}\" -search_dylibs_first \"${myLIBNAME_LD}\" 2>&1 | ${GREP} -w dylib | sed 's/^@<:@^\/@:>@*\(\/.*\.dylib\),.*$/\1/'`" && test -n "$myLIBPATH" && test -s "$myLIBPATH" ; } \ || if test x"${target_cpu}" != x"${my_uname_m}" ; then - { myLIBPATH="`${LD} -dynamic -r -arch \"${my_uname_m}\" -search_dylibs_first \"${myLIBNAME_LD}\" 2>&1 | ${GREP} -w dylib | sed 's/^@<:@^\/@:>@*\(\/.*\.dylib\),.*$/\1/'`" && test -n "$myLIBPATH" && test -s "$myLIBPATH" ; } \ - || { myLIBPATH="`${LD} $LDFLAGS -dynamic -r -arch \"${my_uname_m}\" -search_dylibs_first \"${myLIBNAME_LD}\" 2>&1 | ${GREP} -w dylib | sed 's/^@<:@^\/@:>@*\(\/.*\.dylib\),.*$/\1/'`" && test -n "$myLIBPATH" && test -s "$myLIBPATH" ; } \ - || { myLIBPATH="`${LD} $LDFLAGS $LIBS -dynamic -r -arch \"${my_uname_m}\" -search_dylibs_first \"${myLIBNAME_LD}\" 2>&1 | ${GREP} -w dylib | sed 's/^@<:@^\/@:>@*\(\/.*\.dylib\),.*$/\1/'`" && test -n "$myLIBPATH" && test -s "$myLIBPATH" ; } \ + { myLIBPATH="`LIBRARY_PATH=\"${myLIBRARY_PATH}\" ${LD} -dynamic -r -arch \"${my_uname_m}\" -search_dylibs_first \"${myLIBNAME_LD}\" 2>&1 | ${GREP} -w dylib | sed 's/^@<:@^\/@:>@*\(\/.*\.dylib\),.*$/\1/'`" && test -n "$myLIBPATH" && test -s "$myLIBPATH" ; } \ + || { myLIBPATH="`LIBRARY_PATH=\"${myLIBRARY_PATH}\" ${LD} $LDFLAGS -dynamic -r -arch \"${my_uname_m}\" -search_dylibs_first \"${myLIBNAME_LD}\" 2>&1 | ${GREP} -w dylib | sed 's/^@<:@^\/@:>@*\(\/.*\.dylib\),.*$/\1/'`" && test -n "$myLIBPATH" && test -s "$myLIBPATH" ; } \ + || { myLIBPATH="`LIBRARY_PATH=\"${myLIBRARY_PATH}\" ${LD} $LDFLAGS $LIBS -dynamic -r -arch \"${my_uname_m}\" -search_dylibs_first \"${myLIBNAME_LD}\" 2>&1 | ${GREP} -w dylib | sed 's/^@<:@^\/@:>@*\(\/.*\.dylib\),.*$/\1/'`" && test -n "$myLIBPATH" && test -s "$myLIBPATH" ; } \ || myLIBPATH="" else myLIBPATH="" @@ -213,6 +226,7 @@ AC_DEFUN([AX_REALPATH_LIB], myLIBPATH_REAL="${myLIBPATH}" AX_REALPATH([${myLIBPATH}], [myLIBPATH_REAL]) ]) + unset myLIBPATH_LDSCRIPT ],[ AC_MSG_RESULT([no, seems like a normal binary]) @@ -230,6 +244,12 @@ AC_DEFUN([AX_REALPATH_LIB], AC_MSG_RESULT(${myLIBPATH_REAL}) $2="${myLIBPATH_REAL}" + + unset myLIBRARY_PATH + unset myLIBPATH_REAL + unset myLIBPATH + unset myLIBNAME + unset myLIBNAME_LD ],[ AC_MSG_RESULT([not found]) $2="$3" From 36828db3b671913cd8a5603ee3ebb4d0455b3d99 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 3 Feb 2026 16:31:35 +0100 Subject: [PATCH 106/198] m4/ax_realpath_lib.m4, NEWS.adoc, docs/nut.dict: retry by calling linker or compiler with the library paths and link name, to derive the path from error messages [#2431] Signed-off-by: Jim Klimov --- NEWS.adoc | 3 +++ docs/nut.dict | 3 ++- m4/ax_realpath_lib.m4 | 30 +++++++++++++++++++++++++++++- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index d8fe700679..6d88f0fd75 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -423,6 +423,9 @@ several `FSD` notifications into one executed action. [PR #3097] installed on every system capable of using it; this is a niche capability for users of specific devices via a cloud portal. [follow-up to PR #2813 for issue #2807] + * Fixed `m4/ax_realpath_lib.m4` up with more ways to try and gauge the + build-time library name from linker/compiler, to improve the chances + that `nut-scanner` would find them. [#3293] - Recipes, CI and helper script updates not classified above: * Fixed CI recipes for PyPI publication of PyNUT(Client) module to also diff --git a/docs/nut.dict b/docs/nut.dict index 718bab4e1a..9cbfba67ea 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3648 utf-8 +personal_ws-1.1 en 3649 utf-8 AAC AAS ABI @@ -2990,6 +2990,7 @@ rc rcctl readline readonly +realpath realpower realups rebase diff --git a/m4/ax_realpath_lib.m4 b/m4/ax_realpath_lib.m4 index 66b63e5c62..f4e2b3abb5 100644 --- a/m4/ax_realpath_lib.m4 +++ b/m4/ax_realpath_lib.m4 @@ -177,7 +177,7 @@ AC_DEFUN([AX_REALPATH_LIB], unset D ]) - AS_IF([test -z "${myLIBPATH}" && test x"${LD}" != x -a x"${LD}" != xfalse], [ + AS_IF([test -z "${myLIBPATH}" && test x"${LD}" != x -a x"${LD}" != xfalse && test -n "${myLIBNAME_LD}"], [ AS_CASE(["${target_os}"], [*darwin*], [ dnl Try MacOS-style LD as fallback; expecting strings like @@ -196,10 +196,38 @@ AC_DEFUN([AX_REALPATH_LIB], fi rm -f a.out 2>/dev/null || true unset my_uname_m + ], [ + dnl Try our luck with any linker that would complain in + dnl a way that we recognize (e.g. listing some path name + dnl including the expected name as a base part of longer + dnl filename)? + myLDFLAGS="" + if test -n "${myLIBRARY_PATH}" ; then + myLDFLAGS="`echo -L\"${myLIBRARY_PATH}\" | sed 's/:/ -L/g'`" + fi + dnl NOTE: We should not get more than one hit here; + dnl but if we do -- it is probably safer to fail + dnl existence checks below and bail out... + myLIBPATH="`LIBRARY_PATH=\"${myLIBRARY_PATH}\" ${LD} -r $myLDFLAGS \"${myLIBNAME_LD}\" -o a.out 2>&1 | tr ' ' '\n' | ${EGREP} \"@<:@/\\@:>@${myLIBNAME}\"`" + if test -n "${myLIBPATH}" && test -s "${myLIBPATH}" ; then : ; else myLIBPATH="" ; fi + rm -f a.out + unset myLDFLAGS ] ) ]) + AS_IF([test -z "${myLIBPATH}" && test x"${CC}" != x -a x"${CC}" != xfalse && test -n "${myLIBNAME_LD}"], [ + dnl Like above, but try CC instead of LD + myLDFLAGS="" + if test -n "${myLIBRARY_PATH}" ; then + myLDFLAGS="`echo -L\"${myLIBRARY_PATH}\" | sed 's/:/ -L/g'`" + fi + myLIBPATH="`LIBRARY_PATH=\"${myLIBRARY_PATH}\" ${CC} -r $myLDFLAGS \"${myLIBNAME_LD}\" -o a.out 2>&1 | tr ' ' '\n' | ${EGREP} \"@<:@/\\@:>@${myLIBNAME}\"`" + if test -n "${myLIBPATH}" && test -s "${myLIBPATH}" ; then : ; else myLIBPATH="" ; fi + rm -f a.out + unset myLDFLAGS + ]) + AS_IF([test -n "${myLIBPATH}" && test -s "${myLIBPATH}"], [ AC_MSG_RESULT([initially '${myLIBPATH}']) From 2b4936551ab3085428188f8490fd4f6bc94ea8f5 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 3 Feb 2026 17:25:01 +0100 Subject: [PATCH 107/198] drivers/vertiv-psi5-mib.{c,h}, NEWS.adoc: fix to actually compile [#3299] Signed-off-by: Jim Klimov --- NEWS.adoc | 1 + docs/nut.dict | 3 +- drivers/vertiv-psi5-mib.c | 111 ++++++++++++++++++-------------------- drivers/vertiv-psi5-mib.h | 2 +- 4 files changed, 55 insertions(+), 62 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index 5d08172d8e..e684b9eb5c 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -198,6 +198,7 @@ https://github.com/networkupstools/nut/milestone/12 mappings. Suggest how user can help improve the driver if too few data points were seen, or if the `mibs=auto` detection only found the fallback IETF mapping. [PR #3095] + * Added new vendor extension mappings for Vertiv Liebert PSI5 UPS. [#3299] - `tripplite_usb` driver updates: * Added support for Tripplite protocol 3017 (mostly ASCII). [issue #2258, diff --git a/docs/nut.dict b/docs/nut.dict index e81d1fc663..3d913811c8 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3646 utf-8 +personal_ws-1.1 en 3647 utf-8 AAC AAS ABI @@ -1473,6 +1473,7 @@ Valderen Vdc Velloso VendorID +Vertiv Viewpower Viewsonic Viktor diff --git a/drivers/vertiv-psi5-mib.c b/drivers/vertiv-psi5-mib.c index e3d4066d3f..25bee6a93f 100644 --- a/drivers/vertiv-psi5-mib.c +++ b/drivers/vertiv-psi5-mib.c @@ -1,4 +1,4 @@ -/* vertiv-psi5-mib.h - Driver for Vertiv Liebert PSI5 UPS +/* vertiv-psi5-mib.h - Driver for Vertiv Liebert PSI5 UPS (maybe other Vertiv too) * * Copyright (C) * 2026 jawz101 + Gemini @@ -20,83 +20,74 @@ * */ -/* drivers/vertiv-psi5-mib.c */ #include "vertiv-psi5-mib.h" +#define VERTIV_PSI5_MIB_VERSION "0.01" + +/* SysOID for Vertiv/Liebert */ +#define VERTIV_BASEOID ".1.3.6.1.4.1.476.1.42" +#define VERTIV_PSI5_SYSOID VERTIV_BASEOID +#define VERTIV_PSI5_OID_MODEL VERTIV_BASEOID ".2.1.4.1" +#define VERTIV_PSI5_OID_PWR VERTIV_BASEOID ".3.5.3" + /* Vertiv PSI5-750MT120 Mapping - Monitoring: Based on integer branch at .1.3.6.1.4.1.476.1.42.3.9.30... - Control: Based on standard Liebert Environmental MIB at .1.3.6.1.4.1.476.1.42.3.3.5... */ + * Monitoring: Based on integer branch at .1.3.6.1.4.1.476.1.42.3.9.30... + * Control: Based on standard Liebert Environmental MIB at .1.3.6.1.4.1.476.1.42.3.3.5... + */ static snmp_info_t vertiv_psi5_mib[] = { + /* standard MIB items */ + snmp_info_default("device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK, NULL), + snmp_info_default("device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK, NULL), + snmp_info_default("device.location", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_OK, NULL), + /* Load and Temperature */ - { "ups.load", 0, SU_INFOTYPE_INT, NULL, - ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.5861", - NULL, NULL }, - { "ups.temperature", 0, SU_INFOTYPE_INT, NULL, - ".1.3.6.1.4.1.476.1.42.3.9.30.1.10.1.2.1.4291", - NULL, NULL }, + snmp_info_default("ups.load", 0, 1, ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.5861", "", SU_OUTPUT_1, NULL), + snmp_info_default("ups.temperature", 0, 0.1, ".1.3.6.1.4.1.476.1.42.3.9.30.1.10.1.2.1.4291", NULL, 0, NULL), /* Battery */ - { "battery.charge", 0, SU_INFOTYPE_INT, NULL, - ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4153", - NULL, NULL }, - { "battery.runtime", 0, SU_INFOTYPE_INT, NULL, - ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4150", - NULL, NULL }, /* Raw value is minutes */ - { "battery.voltage", 0, SU_INFOTYPE_INT, NULL, - ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4148", - NULL, NULL }, + snmp_info_default("battery.charge", 0, 0.1, ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4153", "", SU_FLAG_OK|SU_FLAG_NEGINVALID|SU_FLAG_UNIQUE, NULL), + snmp_info_default("battery.runtime", 0, 1, ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4150", "", SU_FLAG_OK, NULL), + snmp_info_default("battery.voltage", 0, 0.1, ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4148", "", SU_FLAG_OK|SU_FLAG_NEGINVALID|SU_FLAG_UNIQUE, NULL), /* Input */ - { "input.voltage", 0, SU_INFOTYPE_INT, NULL, - ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4096", - SU_FLAG_OK, NULL }, /* Scale: 0.1 */ - { "input.frequency", 0, SU_INFOTYPE_INT, NULL, - ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4105", - SU_FLAG_OK, NULL }, /* Scale: 0.1 */ + snmp_info_default("input.voltage", 0, 0.1, ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4096", "", SU_FLAG_OK|SU_FLAG_NEGINVALID|SU_FLAG_UNIQUE, NULL), + snmp_info_default("input.frequency", 0, 0.1, ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4105", "", SU_FLAG_OK|SU_FLAG_NEGINVALID|SU_FLAG_UNIQUE, NULL), /* Output */ - { "output.voltage", 0, SU_INFOTYPE_INT, NULL, - ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4385", - SU_FLAG_OK, NULL }, /* Scale: 0.1 */ - { "output.current", 0, SU_INFOTYPE_INT, NULL, - ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4204", - SU_FLAG_OK, NULL }, /* Scale: 0.1 */ - { "output.power", 0, SU_INFOTYPE_INT, NULL, - ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4208", - SU_FLAG_OK, NULL }, + snmp_info_default("output.voltage", 0, 0.1, ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4385", "", SU_FLAG_OK|SU_FLAG_UNIQUE, NULL), + snmp_info_default("output.current", 0, 0.1, ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4204", "", SU_FLAG_OK|SU_FLAG_NEGINVALID|SU_FLAG_UNIQUE, NULL), + snmp_info_default("output.power", 0, 1, ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4208", "", SU_FLAG_OK|SU_FLAG_NEGINVALID, NULL), /* Shutdown / Restart Control - Derived from lgpEnvControl (LIEBERT-GP-ENVIRONMENTAL-MIB) */ - { "ups.delay.shutdown", 0, SU_INFOTYPE_INT, - ".1.3.6.1.4.1.476.1.42.3.3.5.1.0", - SU_FLAG_RW | SU_FLAG_OK, NULL }, - { "ups.delay.start", 0, SU_INFOTYPE_INT, - ".1.3.6.1.4.1.476.1.42.3.3.5.2.0", - SU_FLAG_RW | SU_FLAG_OK, NULL }, + * Derived from lgpEnvControl (LIEBERT-GP-ENVIRONMENTAL-MIB) + */ + snmp_info_default("ups.delay.shutdown", ST_FLAG_RW, 3, ".1.3.6.1.4.1.476.1.42.3.3.5.1.0", "", SU_TYPE_TIME | SU_FLAG_OK, NULL), + snmp_info_default("ups.delay.start", ST_FLAG_RW, 3, ".1.3.6.1.4.1.476.1.42.3.3.5.2.0", "", SU_TYPE_TIME | SU_FLAG_OK, NULL), - /* Status Flags */ - { "ups.alarm", 0, SU_INFOTYPE_INT, NULL, - ".1.3.6.1.4.1.476.1.42.3.9.20.1.20.1.2.100.6182", - NULL, NULL }, /* Replace Battery */ - { "ups.alarm", 0, SU_INFOTYPE_INT, NULL, - ".1.3.6.1.4.1.476.1.42.3.9.20.1.20.1.2.100.4233", - NULL, NULL }, /* Inverter Failure */ - { "ups.alarm", 0, SU_INFOTYPE_INT, NULL, - ".1.3.6.1.4.1.476.1.42.3.9.20.1.20.1.2.100.5806", - NULL, NULL }, /* Overload */ + /* Status Flags: TBD */ - /* End of list */ - { NULL, 0, 0, NULL, NULL, NULL, NULL } + /* end of structure. */ + snmp_info_sentinel }; -snmp_subdriver_t vertiv_psi5_subdriver = { +static alarms_info_t vertiv_psi5_alarms[] = { + /* Replace Battery */ + { ".1.3.6.1.4.1.476.1.42.3.9.20.1.20.1.2.100.6182", "RB", "Replace Battery" }, + /* Inverter Failure */ + { ".1.3.6.1.4.1.476.1.42.3.9.20.1.20.1.2.100.4233", NULL, "Inverter failure!" }, + /* Overload */ + { ".1.3.6.1.4.1.476.1.42.3.9.20.1.20.1.2.100.5806", "OVER", "Output overload!" }, +}; + +/* SysOID for Vertiv/Liebert */ + +mib2nut_info_t vertiv_psi5_subdriver = { "vertiv-psi5", - "1.00", - ".1.3.6.1.4.1.476.1.42", /* SysOID for Vertiv/Liebert */ + VERTIV_PSI5_MIB_VERSION, + VERTIV_PSI5_OID_PWR, + VERTIV_PSI5_OID_MODEL, vertiv_psi5_mib, - NULL, - NULL, - NULL, - NULL + VERTIV_PSI5_SYSOID, + vertiv_psi5_alarms }; diff --git a/drivers/vertiv-psi5-mib.h b/drivers/vertiv-psi5-mib.h index 6faa46f69d..f14c22b731 100644 --- a/drivers/vertiv-psi5-mib.h +++ b/drivers/vertiv-psi5-mib.h @@ -25,6 +25,6 @@ #include "main.h" #include "snmp-ups.h" -extern snmp_subdriver_t vertiv_psi5_subdriver; +extern mib2nut_info_t vertiv_psi5_subdriver; #endif /* VERTIV_PSI5_MIB_H */ From f1f7e8c8e94fc77bdd59c33cacb0dc94c64f2e54 Mon Sep 17 00:00:00 2001 From: jawz101 Date: Tue, 3 Feb 2026 19:31:04 -0600 Subject: [PATCH 108/198] Update Vertiv PSI5 MIB version and OIDs Updated the version number and modified SNMP OIDs for device monitoring and alarms. --- drivers/vertiv-psi5-mib.c | 100 ++++++++++++++++++++------------------ 1 file changed, 52 insertions(+), 48 deletions(-) diff --git a/drivers/vertiv-psi5-mib.c b/drivers/vertiv-psi5-mib.c index 25bee6a93f..e36737782d 100644 --- a/drivers/vertiv-psi5-mib.c +++ b/drivers/vertiv-psi5-mib.c @@ -18,76 +18,80 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * Includes support for: + * - Basic Monitoring (Voltage, Load, Temperature) + * - Battery Management (Charge, Runtime) + * - Alarms (Replace Battery, Overload, etc.) + * - Beeper Control */ +#include "main.h" +#include "snmp-ups.h" #include "vertiv-psi5-mib.h" -#define VERTIV_PSI5_MIB_VERSION "0.01" +#define VERTIV_PSI5_MIB_VERSION "0.20" -/* SysOID for Vertiv/Liebert */ -#define VERTIV_BASEOID ".1.3.6.1.4.1.476.1.42" -#define VERTIV_PSI5_SYSOID VERTIV_BASEOID -#define VERTIV_PSI5_OID_MODEL VERTIV_BASEOID ".2.1.4.1" -#define VERTIV_PSI5_OID_PWR VERTIV_BASEOID ".3.5.3" - -/* Vertiv PSI5-750MT120 Mapping - * Monitoring: Based on integer branch at .1.3.6.1.4.1.476.1.42.3.9.30... - * Control: Based on standard Liebert Environmental MIB at .1.3.6.1.4.1.476.1.42.3.3.5... - */ +/* Base OIDs from IS-UNITY-DP Card */ +#define VERTIV_BASEOID ".1.3.6.1.4.1.476.1.42" +#define VERTIV_ID_OID VERTIV_BASEOID ".2.4.2.1.4.1" +#define VERTIV_VAL_OID VERTIV_BASEOID ".3.9.30.1.20.1.2.1" +#define VERTIV_ALM_OID VERTIV_BASEOID ".3.9.20.1.10.1.2.100" static snmp_info_t vertiv_psi5_mib[] = { - /* standard MIB items */ - snmp_info_default("device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK, NULL), - snmp_info_default("device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK, NULL), - snmp_info_default("device.location", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_OK, NULL), + /* Device Identification */ + snmp_info_default("device.mfr", 0, 1.0, VERTIV_BASEOID ".2.1.1.0", NULL, SU_FLAG_OK, NULL), + snmp_info_default("device.model", 0, 1.0, VERTIV_ID_OID, NULL, SU_FLAG_OK, NULL), + snmp_info_default("device.serial", 0, 1.0, VERTIV_BASEOID ".2.4.2.1.7.1", NULL, SU_FLAG_OK, NULL), - /* Load and Temperature */ - snmp_info_default("ups.load", 0, 1, ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.5861", "", SU_OUTPUT_1, NULL), - snmp_info_default("ups.temperature", 0, 0.1, ".1.3.6.1.4.1.476.1.42.3.9.30.1.10.1.2.1.4291", NULL, 0, NULL), + /* UPS Measurements - Scaling verified via Audit */ + snmp_info_default("ups.load", 0, 1.0, VERTIV_VAL_OID ".5861", "", SU_FLAG_OK, NULL), + snmp_info_default("ups.temperature", 0, 1.0, VERTIV_BASEOID ".3.9.30.1.10.1.2.1.4291", NULL, 0, NULL), - /* Battery */ - snmp_info_default("battery.charge", 0, 0.1, ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4153", "", SU_FLAG_OK|SU_FLAG_NEGINVALID|SU_FLAG_UNIQUE, NULL), - snmp_info_default("battery.runtime", 0, 1, ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4150", "", SU_FLAG_OK, NULL), - snmp_info_default("battery.voltage", 0, 0.1, ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4148", "", SU_FLAG_OK|SU_FLAG_NEGINVALID|SU_FLAG_UNIQUE, NULL), + /* Battery Data */ + snmp_info_default("battery.charge", 0, 1.0, VERTIV_VAL_OID ".4153", "", SU_FLAG_OK, NULL), + /* Multiplier 60.0 converts UPS minutes to NUT seconds */ + snmp_info_default("battery.runtime", 0, 60.0, VERTIV_VAL_OID ".4150", "", SU_FLAG_OK, NULL), + snmp_info_default("battery.voltage", 0, 1.0, VERTIV_VAL_OID ".4148", "", SU_FLAG_OK, NULL), - /* Input */ - snmp_info_default("input.voltage", 0, 0.1, ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4096", "", SU_FLAG_OK|SU_FLAG_NEGINVALID|SU_FLAG_UNIQUE, NULL), - snmp_info_default("input.frequency", 0, 0.1, ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4105", "", SU_FLAG_OK|SU_FLAG_NEGINVALID|SU_FLAG_UNIQUE, NULL), + /* Power Quality - 0.1 multiplier for tenths of Volts/Hz */ + snmp_info_default("input.voltage", 0, 0.1, VERTIV_VAL_OID ".4096", "", SU_FLAG_OK, NULL), + snmp_info_default("input.frequency", 0, 0.1, VERTIV_VAL_OID ".4105", "", SU_FLAG_OK, NULL), + snmp_info_default("output.voltage", 0, 0.1, VERTIV_VAL_OID ".4385", "", SU_FLAG_OK, NULL), + snmp_info_default("output.current", 0, 0.1, VERTIV_VAL_OID ".4204", "", SU_FLAG_OK, NULL), + snmp_info_default("output.power", 0, 1.0, VERTIV_VAL_OID ".4208", "", SU_FLAG_OK, NULL), - /* Output */ - snmp_info_default("output.voltage", 0, 0.1, ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4385", "", SU_FLAG_OK|SU_FLAG_UNIQUE, NULL), - snmp_info_default("output.current", 0, 0.1, ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4204", "", SU_FLAG_OK|SU_FLAG_NEGINVALID|SU_FLAG_UNIQUE, NULL), - snmp_info_default("output.power", 0, 1, ".1.3.6.1.4.1.476.1.42.3.9.30.1.20.1.2.1.4208", "", SU_FLAG_OK|SU_FLAG_NEGINVALID, NULL), + /* UPS Status & Beeper */ + /* Output Source: 3=Normal(OL), 4/5=Battery(OB) */ + snmp_info_default("ups.status", 0, 1.0, VERTIV_VAL_OID ".4872", "", SU_FLAG_OK, NULL), + /* Beeper: 1=Enabled, 2=Disabled. ST_FLAG_RW makes it settable via upsrw */ + snmp_info_default("ups.beeper.status", ST_FLAG_RW, 1.0, VERTIV_VAL_OID ".6188", "", SU_FLAG_OK, NULL), - /* Shutdown / Restart Control - * Derived from lgpEnvControl (LIEBERT-GP-ENVIRONMENTAL-MIB) - */ - snmp_info_default("ups.delay.shutdown", ST_FLAG_RW, 3, ".1.3.6.1.4.1.476.1.42.3.3.5.1.0", "", SU_TYPE_TIME | SU_FLAG_OK, NULL), - snmp_info_default("ups.delay.start", ST_FLAG_RW, 3, ".1.3.6.1.4.1.476.1.42.3.3.5.2.0", "", SU_TYPE_TIME | SU_FLAG_OK, NULL), + /* Shutdown / Restart Control */ + snmp_info_default("ups.delay.shutdown", ST_FLAG_RW, 1.0, VERTIV_VAL_OID ".5814", "", SU_TYPE_TIME | SU_FLAG_OK, NULL), + snmp_info_default("ups.delay.start", ST_FLAG_RW, 1.0, VERTIV_VAL_OID ".5816", "", SU_TYPE_TIME | SU_FLAG_OK, NULL), - /* Status Flags: TBD */ - - /* end of structure. */ + /* End of monitoring structure */ snmp_info_sentinel }; static alarms_info_t vertiv_psi5_alarms[] = { - /* Replace Battery */ - { ".1.3.6.1.4.1.476.1.42.3.9.20.1.20.1.2.100.6182", "RB", "Replace Battery" }, - /* Inverter Failure */ - { ".1.3.6.1.4.1.476.1.42.3.9.20.1.20.1.2.100.4233", NULL, "Inverter failure!" }, - /* Overload */ - { ".1.3.6.1.4.1.476.1.42.3.9.20.1.20.1.2.100.5806", "OVER", "Output overload!" }, + /* Event Branch Monitoring */ + { VERTIV_ALM_OID ".4168", "OB", "Battery Discharging" }, + { VERTIV_ALM_OID ".4162", "LB", "Battery Low" }, + { VERTIV_ALM_OID ".5806", "OVER", "Output Overload" }, + { VERTIV_ALM_OID ".6182", "RB", "Replace Battery" }, + { VERTIV_ALM_OID ".4233", "FAULT", "Inverter Failure" }, + { VERTIV_ALM_OID ".4310", "OT", "Over Temperature" }, + { VERTIV_ALM_OID ".4215", "OFF", "UPS Output Off" }, + { NULL, NULL, NULL } }; -/* SysOID for Vertiv/Liebert */ - mib2nut_info_t vertiv_psi5_subdriver = { "vertiv-psi5", VERTIV_PSI5_MIB_VERSION, - VERTIV_PSI5_OID_PWR, - VERTIV_PSI5_OID_MODEL, + NULL, /* Optional Power OID */ + VERTIV_ID_OID, /* Model Name OID */ vertiv_psi5_mib, - VERTIV_PSI5_SYSOID, + VERTIV_BASEOID, /* SysOID fingerprint */ vertiv_psi5_alarms }; From 7a32f0ac520d1f2782603d08871e50b7202617b3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Feb 2026 10:39:15 +0100 Subject: [PATCH 109/198] drivers/vertiv-psi5-mib.c: reconcile new round of changes with older iteration (SU_FLAG* values, IETF identification) [#3299] Signed-off-by: Jim Klimov --- drivers/vertiv-psi5-mib.c | 49 +++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/drivers/vertiv-psi5-mib.c b/drivers/vertiv-psi5-mib.c index e36737782d..c5ce67db21 100644 --- a/drivers/vertiv-psi5-mib.c +++ b/drivers/vertiv-psi5-mib.c @@ -25,52 +25,61 @@ * - Beeper Control */ -#include "main.h" -#include "snmp-ups.h" #include "vertiv-psi5-mib.h" -#define VERTIV_PSI5_MIB_VERSION "0.20" +#define VERTIV_PSI5_MIB_VERSION "0.01" /* Base OIDs from IS-UNITY-DP Card */ #define VERTIV_BASEOID ".1.3.6.1.4.1.476.1.42" #define VERTIV_ID_OID VERTIV_BASEOID ".2.4.2.1.4.1" #define VERTIV_VAL_OID VERTIV_BASEOID ".3.9.30.1.20.1.2.1" #define VERTIV_ALM_OID VERTIV_BASEOID ".3.9.20.1.10.1.2.100" +#define VERTIV_PWRSTATUS_OID VERTIV_BASEOID ".3.5.3" static snmp_info_t vertiv_psi5_mib[] = { - /* Device Identification */ - snmp_info_default("device.mfr", 0, 1.0, VERTIV_BASEOID ".2.1.1.0", NULL, SU_FLAG_OK, NULL), - snmp_info_default("device.model", 0, 1.0, VERTIV_ID_OID, NULL, SU_FLAG_OK, NULL), - snmp_info_default("device.serial", 0, 1.0, VERTIV_BASEOID ".2.4.2.1.7.1", NULL, SU_FLAG_OK, NULL), + /* standard MIB items */ + snmp_info_default("device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK | SU_FLAG_SEMI_STATIC, NULL), + snmp_info_default("device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK | SU_FLAG_SEMI_STATIC, NULL), + snmp_info_default("device.location", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_OK | SU_FLAG_SEMI_STATIC, NULL), + + /* Device Identification from vendor MIB */ + snmp_info_default("device.mfr", 0, 1.0, VERTIV_BASEOID ".2.1.1.0", NULL, SU_FLAG_OK | SU_FLAG_STATIC, NULL), + snmp_info_default("device.model", 0, 1.0, VERTIV_ID_OID, NULL, SU_FLAG_OK | SU_FLAG_STATIC, NULL), + snmp_info_default("device.serial", 0, 1.0, VERTIV_BASEOID ".2.4.2.1.7.1", NULL, SU_FLAG_OK | SU_FLAG_STATIC, NULL), /* UPS Measurements - Scaling verified via Audit */ - snmp_info_default("ups.load", 0, 1.0, VERTIV_VAL_OID ".5861", "", SU_FLAG_OK, NULL), - snmp_info_default("ups.temperature", 0, 1.0, VERTIV_BASEOID ".3.9.30.1.10.1.2.1.4291", NULL, 0, NULL), + snmp_info_default("ups.load", 0, 1.0, VERTIV_VAL_OID ".5861", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), + snmp_info_default("ups.temperature", 0, 1.0, VERTIV_BASEOID ".3.9.30.1.10.1.2.1.4291", NULL, SU_FLAG_NEGINVALID, NULL), /* Battery Data */ - snmp_info_default("battery.charge", 0, 1.0, VERTIV_VAL_OID ".4153", "", SU_FLAG_OK, NULL), + snmp_info_default("battery.charge", 0, 1.0, VERTIV_VAL_OID ".4153", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), /* Multiplier 60.0 converts UPS minutes to NUT seconds */ - snmp_info_default("battery.runtime", 0, 60.0, VERTIV_VAL_OID ".4150", "", SU_FLAG_OK, NULL), - snmp_info_default("battery.voltage", 0, 1.0, VERTIV_VAL_OID ".4148", "", SU_FLAG_OK, NULL), + snmp_info_default("battery.runtime", 0, 60.0, VERTIV_VAL_OID ".4150", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), + snmp_info_default("battery.voltage", 0, 1.0, VERTIV_VAL_OID ".4148", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), /* Power Quality - 0.1 multiplier for tenths of Volts/Hz */ - snmp_info_default("input.voltage", 0, 0.1, VERTIV_VAL_OID ".4096", "", SU_FLAG_OK, NULL), - snmp_info_default("input.frequency", 0, 0.1, VERTIV_VAL_OID ".4105", "", SU_FLAG_OK, NULL), - snmp_info_default("output.voltage", 0, 0.1, VERTIV_VAL_OID ".4385", "", SU_FLAG_OK, NULL), - snmp_info_default("output.current", 0, 0.1, VERTIV_VAL_OID ".4204", "", SU_FLAG_OK, NULL), - snmp_info_default("output.power", 0, 1.0, VERTIV_VAL_OID ".4208", "", SU_FLAG_OK, NULL), + snmp_info_default("input.voltage", 0, 0.1, VERTIV_VAL_OID ".4096", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), + snmp_info_default("input.frequency", 0, 0.1, VERTIV_VAL_OID ".4105", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), + snmp_info_default("output.voltage", 0, 0.1, VERTIV_VAL_OID ".4385", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), + snmp_info_default("output.current", 0, 0.1, VERTIV_VAL_OID ".4204", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), + snmp_info_default("output.power", 0, 1.0, VERTIV_VAL_OID ".4208", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), /* UPS Status & Beeper */ /* Output Source: 3=Normal(OL), 4/5=Battery(OB) */ snmp_info_default("ups.status", 0, 1.0, VERTIV_VAL_OID ".4872", "", SU_FLAG_OK, NULL), + /* Beeper: 1=Enabled, 2=Disabled. ST_FLAG_RW makes it settable via upsrw */ snmp_info_default("ups.beeper.status", ST_FLAG_RW, 1.0, VERTIV_VAL_OID ".6188", "", SU_FLAG_OK, NULL), - /* Shutdown / Restart Control */ + /* Shutdown / Restart Control + * NOTE: Other sources suggest + * "ups.delay.shutdown" => VERTIV_BASEOID ".3.3.5.1.0" + * "ups.delay.start" => VERTIV_BASEOID ".3.3.5.2.0" + */ snmp_info_default("ups.delay.shutdown", ST_FLAG_RW, 1.0, VERTIV_VAL_OID ".5814", "", SU_TYPE_TIME | SU_FLAG_OK, NULL), snmp_info_default("ups.delay.start", ST_FLAG_RW, 1.0, VERTIV_VAL_OID ".5816", "", SU_TYPE_TIME | SU_FLAG_OK, NULL), - /* End of monitoring structure */ + /* end of structure. */ snmp_info_sentinel }; @@ -89,7 +98,7 @@ static alarms_info_t vertiv_psi5_alarms[] = { mib2nut_info_t vertiv_psi5_subdriver = { "vertiv-psi5", VERTIV_PSI5_MIB_VERSION, - NULL, /* Optional Power OID */ + VERTIV_PWRSTATUS_OID,/* Optional Power Status OID */ VERTIV_ID_OID, /* Model Name OID */ vertiv_psi5_mib, VERTIV_BASEOID, /* SysOID fingerprint */ From 5c19f57b0939877410a262b66d4239ca874794d6 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Feb 2026 10:45:16 +0100 Subject: [PATCH 110/198] drivers/vertiv-*: generalize to "vertiv" MIB, this is not PSI5 specific [#3299] Signed-off-by: Jim Klimov --- drivers/Makefile.am | 4 ++-- drivers/snmp-ups.c | 4 ++-- drivers/{vertiv-psi5-mib.c => vertiv-mib.c} | 20 ++++++++++---------- drivers/{vertiv-psi5-mib.h => vertiv-mib.h} | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) rename drivers/{vertiv-psi5-mib.c => vertiv-mib.c} (93%) rename drivers/{vertiv-psi5-mib.h => vertiv-mib.h} (95%) diff --git a/drivers/Makefile.am b/drivers/Makefile.am index 0fbaf1aba3..95b0dd0867 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -394,7 +394,7 @@ snmp_ups_SOURCES = snmp-ups.c snmp-ups-helpers.c \ mge-mib.c \ netvision-mib.c \ raritan-pdu-mib.c raritan-px2-mib.c \ - vertiv-psi5-mib.c \ + vertiv-mib.c \ xppc-mib.c snmp_ups_CFLAGS = $(AM_CFLAGS) snmp_ups_CFLAGS += $(LIBNETSNMP_CFLAGS) @@ -541,7 +541,7 @@ dist_noinst_HEADERS = \ nutdrv_qx_voltronic-axpert.h nutdrv_qx_voltronic-qs.h nutdrv_qx_voltronic-qs-hex.h \ nutdrv_qx_zinto.h \ upsdrvquery.h \ - xppc-mib.h huawei-mib.h eaton-ats16-nmc-mib.h eaton-ats16-nm2-mib.h apc-ats-mib.h raritan-px2-mib.h vertiv-psi5-mib.h eaton-ats30-mib.h \ + xppc-mib.h huawei-mib.h eaton-ats16-nmc-mib.h eaton-ats16-nm2-mib.h apc-ats-mib.h raritan-px2-mib.h vertiv-mib.h eaton-ats30-mib.h \ apc-pdu-mib.h apc-epdu-mib.h ecoflow-hid.h ever-hid.h eaton-pdu-genesis2-mib.h eaton-pdu-marlin-mib.h eaton-pdu-marlin-helpers.h \ eaton-pdu-pulizzi-mib.h eaton-pdu-revelation-mib.h emerson-avocent-pdu-mib.h eaton-ups-pwnm2-mib.h eaton-ups-pxg-mib.h legrand-hid.h \ hpe-pdu-mib.h hpe-pdu3-cis-mib.h powervar-hid.h delta_ups-hid.h generic_modbus.h salicru-hid.h adelsystem_cbi.h eaton-pdu-nlogic-mib.h ydn23.h diff --git a/drivers/snmp-ups.c b/drivers/snmp-ups.c index 0033eb5387..8bc97ca6b9 100644 --- a/drivers/snmp-ups.c +++ b/drivers/snmp-ups.c @@ -72,7 +72,7 @@ #include "emerson-avocent-pdu-mib.h" #include "hpe-pdu-mib.h" #include "hpe-pdu3-cis-mib.h" -#include "vertiv-psi5-mib.h" +#include "vertiv-mib.h" /* Address API change */ #if ( ! NUT_HAVE_LIBNETSNMP_usmAESPrivProtocol ) && ( ! defined usmAESPrivProtocol ) @@ -129,7 +129,7 @@ static mib2nut_info_t *mib2nut[] = { &netvision, /* This struct comes from : netvision-mib.c */ &raritan, /* This struct comes from : raritan-pdu-mib.c */ &raritan_px2, /* This struct comes from : raritan-px2-mib.c */ - &vertiv_psi5_subdriver, /* This struct comes from : vertiv-psi5-mib.c */ + &vertiv, /* This struct comes from : vertiv-mib.c */ &xppc, /* This struct comes from : xppc-mib.c */ /* * Prepend vendor specific MIB mappings before IETF, so that diff --git a/drivers/vertiv-psi5-mib.c b/drivers/vertiv-mib.c similarity index 93% rename from drivers/vertiv-psi5-mib.c rename to drivers/vertiv-mib.c index c5ce67db21..f8b058e2c1 100644 --- a/drivers/vertiv-psi5-mib.c +++ b/drivers/vertiv-mib.c @@ -1,4 +1,4 @@ -/* vertiv-psi5-mib.h - Driver for Vertiv Liebert PSI5 UPS (maybe other Vertiv too) +/* vertiv-mib.h - Driver for Vertiv Liebert PSI5 UPS (maybe other Vertiv too) * * Copyright (C) * 2026 jawz101 + Gemini @@ -25,9 +25,9 @@ * - Beeper Control */ -#include "vertiv-psi5-mib.h" +#include "vertiv-mib.h" -#define VERTIV_PSI5_MIB_VERSION "0.01" +#define VERTIV_MIB_VERSION "0.01" /* Base OIDs from IS-UNITY-DP Card */ #define VERTIV_BASEOID ".1.3.6.1.4.1.476.1.42" @@ -36,7 +36,7 @@ #define VERTIV_ALM_OID VERTIV_BASEOID ".3.9.20.1.10.1.2.100" #define VERTIV_PWRSTATUS_OID VERTIV_BASEOID ".3.5.3" -static snmp_info_t vertiv_psi5_mib[] = { +static snmp_info_t vertiv_mib[] = { /* standard MIB items */ snmp_info_default("device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK | SU_FLAG_SEMI_STATIC, NULL), snmp_info_default("device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK | SU_FLAG_SEMI_STATIC, NULL), @@ -83,7 +83,7 @@ static snmp_info_t vertiv_psi5_mib[] = { snmp_info_sentinel }; -static alarms_info_t vertiv_psi5_alarms[] = { +static alarms_info_t vertiv_alarms[] = { /* Event Branch Monitoring */ { VERTIV_ALM_OID ".4168", "OB", "Battery Discharging" }, { VERTIV_ALM_OID ".4162", "LB", "Battery Low" }, @@ -95,12 +95,12 @@ static alarms_info_t vertiv_psi5_alarms[] = { { NULL, NULL, NULL } }; -mib2nut_info_t vertiv_psi5_subdriver = { - "vertiv-psi5", - VERTIV_PSI5_MIB_VERSION, +mib2nut_info_t vertiv = { + "vertiv", + VERTIV_MIB_VERSION, VERTIV_PWRSTATUS_OID,/* Optional Power Status OID */ VERTIV_ID_OID, /* Model Name OID */ - vertiv_psi5_mib, + vertiv_mib, VERTIV_BASEOID, /* SysOID fingerprint */ - vertiv_psi5_alarms + vertiv_alarms }; diff --git a/drivers/vertiv-psi5-mib.h b/drivers/vertiv-mib.h similarity index 95% rename from drivers/vertiv-psi5-mib.h rename to drivers/vertiv-mib.h index f14c22b731..b48d293238 100644 --- a/drivers/vertiv-psi5-mib.h +++ b/drivers/vertiv-mib.h @@ -25,6 +25,6 @@ #include "main.h" #include "snmp-ups.h" -extern mib2nut_info_t vertiv_psi5_subdriver; +extern mib2nut_info_t vertiv; #endif /* VERTIV_PSI5_MIB_H */ From 09e47391eb941ec2283cbb83f2f316fb7f70bcda Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Feb 2026 10:46:31 +0100 Subject: [PATCH 111/198] NEWS.adoc, data/driver.list.in: update regarding Vertiv/Liebert MIB [#3299] Signed-off-by: Jim Klimov --- NEWS.adoc | 4 +++- data/driver.list.in | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/NEWS.adoc b/NEWS.adoc index 18c5f0b687..e7304cb841 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -206,7 +206,9 @@ https://github.com/networkupstools/nut/milestone/12 mappings. Suggest how user can help improve the driver if too few data points were seen, or if the `mibs=auto` detection only found the fallback IETF mapping. [PR #3095] - * Added new vendor extension mappings for Vertiv Liebert PSI5 UPS. [#3299] + * Added new vendor extension mappings for Vertiv Liebert UPS, tested with + PSI5-750MT120 UPS model and IS-UNITY-DP (Firmware 8.4.7.0) SNMP card. + [issue #3296, PR #3299] - `tripplite_usb` driver updates: * Added support for Tripplite protocol 3017 (mostly ASCII). [issue #2258, diff --git a/data/driver.list.in b/data/driver.list.in index 39104e0897..52888e6d16 100644 --- a/data/driver.list.in +++ b/data/driver.list.in @@ -742,6 +742,7 @@ "Liebert" "ups" "3" "PowerSure PSA500MT3-230U" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/601 "Liebert" "ups" "3" "PowerSure PSI 1440" "USB" "usbhid-ups" # http://www.emersonnetworkpower.com/en-US/Products/ACPower/Pages/LiebertPowerSurePSILineInteractiveUPS10003000VA.aspx "Liebert" "ups" "3" "PSI5-800RT120" "USB" "usbhid-ups" # https://www.vertiv.com/en-us/products-catalog/critical-power/uninterruptible-power-supplies-ups/psi5-800rt120/ +"Liebert" "ups" "3" "PSI5-750MT120 (with IS-UNITY-DP SNMP card)" "" "snmp-ups" # https://github.com/networkupstools/nut/pull/3299 "LNXI" "pdu" "1" "Icebox" "10 outlets" "powerman-pdu (experimental)" From 79389ad70e0a1e0ba70ef918c289873a8103d0a7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Feb 2026 11:01:14 +0100 Subject: [PATCH 112/198] drivers/vertiv-mib.c: refine beeper status vs. cmd [#3299] Signed-off-by: Jim Klimov --- drivers/vertiv-mib.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/drivers/vertiv-mib.c b/drivers/vertiv-mib.c index f8b058e2c1..b1ea50be42 100644 --- a/drivers/vertiv-mib.c +++ b/drivers/vertiv-mib.c @@ -35,6 +35,20 @@ #define VERTIV_VAL_OID VERTIV_BASEOID ".3.9.30.1.20.1.2.1" #define VERTIV_ALM_OID VERTIV_BASEOID ".3.9.20.1.10.1.2.100" #define VERTIV_PWRSTATUS_OID VERTIV_BASEOID ".3.5.3" +#define VERTIV_BEEPER_OID VERTIV_VAL_OID ".6188" + +static info_lkp_t ietf_beeper_status_info[] = { + info_lkp_default(1, "disabled"), + info_lkp_default(2, "enabled"), + info_lkp_default(3, "muted"), + info_lkp_sentinel +}; + +static info_lkp_t vertiv_beeper_status_info[] = { + info_lkp_default(1, "enabled"), + info_lkp_default(2, "disabled"), + info_lkp_sentinel +}; static snmp_info_t vertiv_mib[] = { /* standard MIB items */ @@ -64,12 +78,23 @@ static snmp_info_t vertiv_mib[] = { snmp_info_default("output.current", 0, 0.1, VERTIV_VAL_OID ".4204", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), snmp_info_default("output.power", 0, 1.0, VERTIV_VAL_OID ".4208", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), - /* UPS Status & Beeper */ + /* UPS Status */ /* Output Source: 3=Normal(OL), 4/5=Battery(OB) */ snmp_info_default("ups.status", 0, 1.0, VERTIV_VAL_OID ".4872", "", SU_FLAG_OK, NULL), - /* Beeper: 1=Enabled, 2=Disabled. ST_FLAG_RW makes it settable via upsrw */ - snmp_info_default("ups.beeper.status", ST_FLAG_RW, 1.0, VERTIV_VAL_OID ".6188", "", SU_FLAG_OK, NULL), + /* Beeper status and commands */ + snmp_info_default("ups.beeper.status", ST_FLAG_STRING, SU_INFOSIZE, VERTIV_BEEPER_OID, "", SU_FLAG_UNIQUE, vertiv_beeper_status_info), + + snmp_info_default("beeper.disable", 0, 1, VERTIV_BEEPER_OID, "2", SU_TYPE_CMD, NULL), + snmp_info_default("beeper.enable", 0, 1, VERTIV_BEEPER_OID, "1", SU_TYPE_CMD, NULL), + + /* IETF MIB fallback */ + snmp_info_default("ups.beeper.status", ST_FLAG_STRING, SU_INFOSIZE, "1.3.6.1.2.1.33.1.9.8.0", "", SU_FLAG_UNIQUE, ietf_beeper_status_info), +#if 0 + snmp_info_default("beeper.disable", 0, 1, "1.3.6.1.2.1.33.1.9.8.0", "1", SU_TYPE_CMD, NULL), + snmp_info_default("beeper.enable", 0, 1, "1.3.6.1.2.1.33.1.9.8.0", "2", SU_TYPE_CMD, NULL), +#endif + snmp_info_default("beeper.mute", 0, 1, "1.3.6.1.2.1.33.1.9.8.0", "3", SU_TYPE_CMD, NULL), /* Shutdown / Restart Control * NOTE: Other sources suggest From 6c08c8b498957a7f64516db26347d9518db01aac Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Feb 2026 11:15:31 +0100 Subject: [PATCH 113/198] drivers/vertiv-mib.c: refine ups.status [#3299] Signed-off-by: Jim Klimov --- drivers/vertiv-mib.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/drivers/vertiv-mib.c b/drivers/vertiv-mib.c index b1ea50be42..76b444a506 100644 --- a/drivers/vertiv-mib.c +++ b/drivers/vertiv-mib.c @@ -50,6 +50,30 @@ static info_lkp_t vertiv_beeper_status_info[] = { info_lkp_sentinel }; +/* FIXME: the below may introduce status redundancy, that needs to be + * addressed by the driver, as for usbhid-ups! */ +/* + * DESCRIPTION + * The present source of output power. The enumeration + * none(2) indicates that there is no source of output + * power (and therefore no output power), for example, + * the system has opened the output breaker. + * + * NOTE: In a single-module system, this point + * is intended to have the same behavior as + * the RFC1628 point upsOutputSource." + */ +static info_lkp_t vertiv_power_source_info[] = { + info_lkp_default(1, ""), /* other */ + info_lkp_default(2, "OFF"), /* none */ + info_lkp_default(3, "OL"), /* normal */ + info_lkp_default(4, "BYPASS"), /* bypass */ + info_lkp_default(5, "OB"), /* battery */ + info_lkp_default(6, "BOOST"), /* booster */ + info_lkp_default(7, "TRIM"), /* reducer */ + info_lkp_sentinel +}; + static snmp_info_t vertiv_mib[] = { /* standard MIB items */ snmp_info_default("device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK | SU_FLAG_SEMI_STATIC, NULL), @@ -79,8 +103,8 @@ static snmp_info_t vertiv_mib[] = { snmp_info_default("output.power", 0, 1.0, VERTIV_VAL_OID ".4208", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), /* UPS Status */ - /* Output Source: 3=Normal(OL), 4/5=Battery(OB) */ - snmp_info_default("ups.status", 0, 1.0, VERTIV_VAL_OID ".4872", "", SU_FLAG_OK, NULL), + /* Output Source: 3=Normal(OL), 4/5=Battery(OB) et al */ + snmp_info_default("ups.status", ST_FLAG_STRING, SU_INFOSIZE, VERTIV_VAL_OID ".4872", "", SU_STATUS_PWR | SU_FLAG_OK, vertiv_power_source_info), /* Beeper status and commands */ snmp_info_default("ups.beeper.status", ST_FLAG_STRING, SU_INFOSIZE, VERTIV_BEEPER_OID, "", SU_FLAG_UNIQUE, vertiv_beeper_status_info), From 8bf6565e7442f174b7c8592b84f349a5cea66786 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 31 Jan 2026 10:55:09 +0100 Subject: [PATCH 114/198] tests/NIT/nit.sh, NEWS.adoc: flip the switch to test upsdrvctl too [#2800] Signed-off-by: Jim Klimov --- NEWS.adoc | 3 +++ tests/NIT/nit.sh | 9 +++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index 6d88f0fd75..047e4801c3 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -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 diff --git a/tests/NIT/nit.sh b/tests/NIT/nit.sh index 0db5378c85..105beda2bf 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -53,7 +53,7 @@ # different value like "nobody" or "nogroup" would be defaulted for test. # # Copyright -# 2022-2025 Jim Klimov +# 2022-2026 Jim Klimov # # License: GPLv2+ @@ -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 @@ -1359,8 +1359,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" From 33921087948d3d685ce07386a4c83668251cc2d8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 1 Feb 2026 07:33:18 +0100 Subject: [PATCH 115/198] configure.ac, tests/NIT/Makefile.am: propagate possibly platform-adjusted spelling of ABS_TOP_SRCDIR and ABS_TOP_BUILDDIR so it ends up in "driverpath" correctly for WIN32 builds [#3292] Signed-off-by: Jim Klimov --- configure.ac | 5 ++++- tests/NIT/Makefile.am | 16 ++++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index e7bc787c86..ddee6dd565 100644 --- a/configure.ac +++ b/configure.ac @@ -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" diff --git a/tests/NIT/Makefile.am b/tests/NIT/Makefile.am index 8332bac658..d2b050da71 100644 --- a/tests/NIT/Makefile.am +++ b/tests/NIT/Makefile.am @@ -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 @@ -24,7 +30,8 @@ check-NIT: $(abs_srcdir)/nit.sh GREP="$(GREP)"; EGREP="$(EGREP)"; export GREP; export EGREP; \ 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_orig='$(abs_top_srcdir)' abs_top_builddir_orig='$(abs_top_builddir)' \ + abs_top_srcdir='$(ABS_TOP_SRCDIR)' abs_top_builddir='$(ABS_TOP_BUILDDIR)' \ EXEEXT='$(EXEEXT)' \ "$(abs_srcdir)/nit.sh" @@ -47,7 +54,8 @@ check-NIT-sandbox: $(abs_srcdir)/nit.sh NUT_PORT=$(NUT_PORT) NIT_CASE="$(NIT_CASE)" NUT_FOREGROUND_WITH_PID=true \ 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_orig='$(abs_top_srcdir)' abs_top_builddir_orig='$(abs_top_builddir)' \ + abs_top_srcdir='$(ABS_TOP_SRCDIR)' abs_top_builddir='$(ABS_TOP_BUILDDIR)' \ EXEEXT='$(EXEEXT)' \ "$(abs_srcdir)/nit.sh" From 96235466ca7a07617642b94b6db3e09b59718900 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 1 Feb 2026 10:52:00 +0100 Subject: [PATCH 116/198] tests/NIT/nit.sh: if we pass driverpath in WIN32 spelling, we want it not only quoted but also with escaped backslashes [#3292] Signed-off-by: Jim Klimov --- tests/NIT/nit.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/NIT/nit.sh b/tests/NIT/nit.sh index 105beda2bf..328eab6b89 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -1001,7 +1001,7 @@ 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 + echo "driverpath = \"${TOP_BUILDDIR}/drivers\"" | sed 's,\\,\\\\,g' >> "$NUT_CONFPATH/ups.conf" || exit fi if [ -n "${NUT_DEBUG_MIN-}" ] ; then echo "debug_min = ${NUT_DEBUG_MIN}" >> "$NUT_CONFPATH/ups.conf" || exit From 99e2d9b2cb5b800438c06352ee969a968279a84e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 1 Feb 2026 13:34:46 +0100 Subject: [PATCH 117/198] tests/NIT/Makefile.am, tests/NIT/nit.sh: use platform-specific ABS_TOP_BUILDDIR separately from makefile abs_top_builddir [#3294] The original hack broke the PATH parsing (added colons in WIN32 tests) Signed-off-by: Jim Klimov --- tests/NIT/Makefile.am | 8 ++++---- tests/NIT/nit.sh | 8 ++++++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/tests/NIT/Makefile.am b/tests/NIT/Makefile.am index d2b050da71..0d1aea3f2c 100644 --- a/tests/NIT/Makefile.am +++ b/tests/NIT/Makefile.am @@ -30,8 +30,8 @@ check-NIT: $(abs_srcdir)/nit.sh GREP="$(GREP)"; EGREP="$(EGREP)"; export GREP; export EGREP; \ 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_orig='$(abs_top_srcdir)' abs_top_builddir_orig='$(abs_top_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)' \ + ABS_TOP_SRCDIR='$(ABS_TOP_SRCDIR)' ABS_TOP_BUILDDIR='$(ABS_TOP_BUILDDIR)' \ EXEEXT='$(EXEEXT)' \ "$(abs_srcdir)/nit.sh" @@ -54,8 +54,8 @@ check-NIT-sandbox: $(abs_srcdir)/nit.sh NUT_PORT=$(NUT_PORT) NIT_CASE="$(NIT_CASE)" NUT_FOREGROUND_WITH_PID=true \ 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_orig='$(abs_top_srcdir)' abs_top_builddir_orig='$(abs_top_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)' \ + ABS_TOP_SRCDIR='$(ABS_TOP_SRCDIR)' ABS_TOP_BUILDDIR='$(ABS_TOP_BUILDDIR)' \ EXEEXT='$(EXEEXT)' \ "$(abs_srcdir)/nit.sh" diff --git a/tests/NIT/nit.sh b/tests/NIT/nit.sh index 328eab6b89..a51c523aaf 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -1000,8 +1000,12 @@ 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\"" | sed 's,\\,\\\\,g' >> "$NUT_CONFPATH/ups.conf" || exit + if [ x"${ABS_TOP_BUILDDIR}" != x ]; then + echo "driverpath = \"${ABS_TOP_BUILDDIR}/drivers\"" | sed 's,\\,\\\\,g' >> "$NUT_CONFPATH/ups.conf" || exit + else + if [ x"${TOP_BUILDDIR}" != x ]; then + echo "driverpath = \"${TOP_BUILDDIR}/drivers\"" | sed 's,\\,\\\\,g' >> "$NUT_CONFPATH/ups.conf" || exit + fi fi if [ -n "${NUT_DEBUG_MIN-}" ] ; then echo "debug_min = ${NUT_DEBUG_MIN}" >> "$NUT_CONFPATH/ups.conf" || exit From a9776270761dc05143d8388e16f5fb27d4658a23 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Feb 2026 12:44:47 +0100 Subject: [PATCH 118/198] drivers/upsdrvctl.c: use windows-style backslashes if the rest of driverpath uses them [#3294] Signed-off-by: Jim Klimov --- drivers/upsdrvctl.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index a6ba76b459..3e4be8d967 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -1237,7 +1237,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); From 660776bbf8300df8cecfaeea12e1a4c1d0dfe0f5 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Feb 2026 11:39:22 +0100 Subject: [PATCH 119/198] docs/config-prereqs.txt: update instructions for NetBSD 11.0 (Beta) Signed-off-by: Jim Klimov --- docs/config-prereqs.txt | 50 +++++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/docs/config-prereqs.txt b/docs/config-prereqs.txt index 59d8b4eae7..1333939aed 100644 --- a/docs/config-prereqs.txt +++ b/docs/config-prereqs.txt @@ -1118,8 +1118,8 @@ or `pkgconf` (so guessing of flags is left to administrator -- TBD in NUT Note the lack of `pkg-config` also precludes `libcppunit` tests, although they also tend to mis-compile/mis-link with GCC (while CLANG seems okay). -NetBSD 9.2 -~~~~~~~~~~ +NetBSD 9.2, 11.0 (Beta) +~~~~~~~~~~~~~~~~~~~~~~~ Instructions below assume that `pkgin` tool (pkg-src component to "install binary packages") is present on the system. Text below @@ -1171,6 +1171,11 @@ using the older tooling: :; pkg_add pkgin ---- +If you are using a test version that identifies like `11.0_BETA`, the +`PKG_PATH` definition above may include that but the package repository +might not serve the URL spelled as such. Trim it down to `11.0` manually +then. + For more details, see https://www.pkgsrc.org/#index1h1 and https://www.librebyte.net/en/cli-en/pkgin-a-netbsd-package-manager/ (the latter also provides a nice cheat-sheet about `pkgin` operations). @@ -1178,7 +1183,7 @@ https://www.librebyte.net/en/cli-en/pkgin-a-netbsd-package-manager/ [NOTE] ====== -On NetBSD 9.2 the `openpimi` and `net-snmp` packages complain that +On NetBSD 9.2 and 11 the `openpimi` and `net-snmp` packages complain that they require either OS ABI 9.0, or that `CHECK_OSABI=no` is set in a `pkg_install.conf`. Such file was not found in the test system, but can be created in `/etc/` and is honoured by `pkgin`: @@ -1189,6 +1194,10 @@ but can be created in `/etc/` and is honoured by `pkgin`: ---- ====== +Some packages include the software version in the name (so several +variants may be installed side by side), so instructions below vary +slightly depending on the OS distribution version: + ------ :; pkgin install \ git perl curl \ @@ -1196,12 +1205,26 @@ but can be created in `/etc/` and is honoured by `pkgin`: bmake gmake autoconf automake libltdl libtool \ cppcheck \ pkgconf \ - gcc7 gcc14 clang + clang + +# NOTE: ccache is installed and links configured for it below + +# NetBSD 9.2: +:; pkgin install \ + gcc7 gcc14 + +# NetBSD 11: +:; pkgin install \ + gcc15 # See comments below, python version and package naming depends on distro +# NetBSD 9.2: :; pkgin install \ python27 python39 python312 python313 +# NetBSD 11 (to cover the max testing scope with both python generations): +:; pkgin install python27 python314 + :; ( cd /usr/pkg/bin && ( ln -fs python2.7 python2 ; ln -fs python3.13 python3 ) ) # You can find a list of what is (pre-)installed with: # :; pkgin list | grep -Ei 'perl|python' @@ -1214,8 +1237,10 @@ but can be created in `/etc/` and is honoured by `pkgin`: # For Python2: # :; pkgin install py27-gtk2 # For Python3: +# * NetBSD 9.2: # :; pkgin install py312-qt5 py313-qt5 -# FIXME: Consider qt6 since 2025 +# * NetBSD 11: +# :; pkgin install py314-qt6 # For spell-checking, highly recommended if you would propose pull requests: :; pkgin install \ @@ -1269,21 +1294,22 @@ It still seems to not work for NUT's expectations of FreeIPMI Recommended: For compatibility with common setups on other operating systems, can add dash-number suffixed symlinks to compiler tools (e.g. `gcc-7` beside the `gcc` installed by package) near the original -binaries and into `/usr/lib/ccache`: +binaries and into `/usr/lib/ccache`; use the numbers according to +what you do have installed: ------ :; ( cd /usr/pkg/bin && for TOOL in cpp gcc g++ ; do \ for VER in "7" "14" ; do \ - ln -fs "../gcc$VER/bin/$TOOL" "${TOOL}-${VER}" ; \ + ln -fs "../gcc${VER}/bin/${TOOL}" "${TOOL}-${VER}" ; \ done ; \ done ) # Note that the one delivered binary is `clang-13` (in originally described -# installation; `clang-18` after an update in 2025 which auto-removed the -# older version) and many (unnumbered) symlinks to it. For NUT CI style of +# NetBSD 9.x installation; `clang-18` after an update in 2025 which auto-removed +# the older version) and many (unnumbered) symlinks to it. For NUT CI style of # support for builds with many compilers, complete the known numbers: :; ( cd /usr/pkg/bin && for TOOL in clang-cpp clang++ ; do \ for VER in "-18" ; do \ - ln -s clang-18 "$TOOL$VER" ; \ + ln -s clang"${VER}" "${TOOL}${VER}" ; \ done ; \ done ) @@ -1291,12 +1317,12 @@ binaries and into `/usr/lib/ccache`: :; ( mkdir -p /usr/lib/ccache && cd /usr/lib/ccache && \ for TOOL in cpp gcc g++ clang ; do \ for VER in "" "-7" "-14" ; do \ - ln -s ../../pkg/bin/ccache "$TOOL$VER" ; \ + ln -s ../../pkg/bin/ccache "${TOOL}${VER}" ; \ done ; \ done ; \ for TOOL in clang clang++ clang-cpp ; do \ for VER in "" "-18" ; do \ - ln -s ../../pkg/bin/ccache "$TOOL$VER" ; \ + ln -s ../../pkg/bin/ccache "${TOOL}${VER}" ; \ done ; \ done ; \ ) From afe33f05f4cc1fe36f708a02370da9a06bbc8fb9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Feb 2026 12:00:04 +0000 Subject: [PATCH 120/198] configure.ac: refine reporting of GPIO_VERSION when there is none Signed-off-by: Jim Klimov --- configure.ac | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index e7bc787c86..17a99d59b9 100644 --- a/configure.ac +++ b/configure.ac @@ -3122,8 +3122,14 @@ if test "${nut_with_gpio}" != "no"; then fi dnl NOTE: m4 scriptlet also defines WITH_LIBGPIO_VERSION like 0x00020000 in config.h -NUT_REPORT_DRIVER([build GPIO driver (library v${GPIO_VERSION})], [${nut_with_gpio}], [${nut_gpio_lib}], +AS_IF([test x"${GPIO_VERSION}" = xnone], [ + REPORT_GPIO_VERSION="library version not detected" +],[ + REPORT_GPIO_VERSION="library v${GPIO_VERSION}" +]) +NUT_REPORT_DRIVER([build GPIO driver (${REPORT_GPIO_VERSION})], [${nut_with_gpio}], [${nut_gpio_lib}], [WITH_GPIO], [Define to enable GPIO support]) +unset REPORT_GPIO_VERSION dnl ---------------------------------------------------------------------- dnl The Mac OS X meta-driver looks at IOKit Power Sources keys managed by From 0d9c8e1c015bf064f343c773ff23c0ed4ab501c9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Feb 2026 12:45:05 +0100 Subject: [PATCH 121/198] tests/NIT/nit.sh: use windows-style backslashes if the rest of driverpath uses them [#3294] Signed-off-by: Jim Klimov --- tests/NIT/nit.sh | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/tests/NIT/nit.sh b/tests/NIT/nit.sh index a51c523aaf..43df6e47fc 100755 --- a/tests/NIT/nit.sh +++ b/tests/NIT/nit.sh @@ -1001,12 +1001,23 @@ generatecfg_ups_trivial() { # Populate the configs for the run ( echo 'maxretry = 3' > "$NUT_CONFPATH/ups.conf" || exit if [ x"${ABS_TOP_BUILDDIR}" != x ]; then - echo "driverpath = \"${ABS_TOP_BUILDDIR}/drivers\"" | sed 's,\\,\\\\,g' >> "$NUT_CONFPATH/ups.conf" || exit + # 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 - echo "driverpath = \"${TOP_BUILDDIR}/drivers\"" | sed 's,\\,\\\\,g' >> "$NUT_CONFPATH/ups.conf" || exit + 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 From d8573898f7a9e6455cb4068e565c128a7242c291 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Feb 2026 14:02:24 +0100 Subject: [PATCH 122/198] drivers/upsdrvctl.c: forkexec() WIN32: refine ability to CreateProcess() for the driver in build workspace, not only in final installation [#3294] Signed-off-by: Jim Klimov --- drivers/upsdrvctl.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index 3e4be8d967..475d4a6d49 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -943,7 +943,7 @@ 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; @@ -951,15 +951,30 @@ static void forkexec(char *const argv[], const ups_t *ups) 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, From 192b6a2c4e7876b0d0083b4f31524644da625727 Mon Sep 17 00:00:00 2001 From: jawz101 Date: Wed, 4 Feb 2026 18:44:45 -0600 Subject: [PATCH 123/198] vertiv-mib: fix ID strings and implement high-precision OIDs for PSI5 --- drivers/vertiv-mib.c | 187 +++++++++++++++++++------------------------ 1 file changed, 83 insertions(+), 104 deletions(-) diff --git a/drivers/vertiv-mib.c b/drivers/vertiv-mib.c index 76b444a506..58af7b2e8c 100644 --- a/drivers/vertiv-mib.c +++ b/drivers/vertiv-mib.c @@ -27,129 +27,108 @@ #include "vertiv-mib.h" -#define VERTIV_MIB_VERSION "0.01" +#define VERTIV_MIB_VERSION "0.04" /* Base OIDs from IS-UNITY-DP Card */ #define VERTIV_BASEOID ".1.3.6.1.4.1.476.1.42" -#define VERTIV_ID_OID VERTIV_BASEOID ".2.4.2.1.4.1" +#define VERTIV_ID_OID VERTIV_BASEOID ".2.4.2.1.4.1" #define VERTIV_VAL_OID VERTIV_BASEOID ".3.9.30.1.20.1.2.1" #define VERTIV_ALM_OID VERTIV_BASEOID ".3.9.20.1.10.1.2.100" #define VERTIV_PWRSTATUS_OID VERTIV_BASEOID ".3.5.3" #define VERTIV_BEEPER_OID VERTIV_VAL_OID ".6188" -static info_lkp_t ietf_beeper_status_info[] = { - info_lkp_default(1, "disabled"), - info_lkp_default(2, "enabled"), - info_lkp_default(3, "muted"), - info_lkp_sentinel -}; - static info_lkp_t vertiv_beeper_status_info[] = { - info_lkp_default(1, "enabled"), - info_lkp_default(2, "disabled"), - info_lkp_sentinel + info_lkp_default(1, "enabled"), + info_lkp_default(2, "disabled"), + info_lkp_sentinel }; -/* FIXME: the below may introduce status redundancy, that needs to be - * addressed by the driver, as for usbhid-ups! */ -/* - * DESCRIPTION - * The present source of output power. The enumeration - * none(2) indicates that there is no source of output - * power (and therefore no output power), for example, - * the system has opened the output breaker. - * - * NOTE: In a single-module system, this point - * is intended to have the same behavior as - * the RFC1628 point upsOutputSource." - */ static info_lkp_t vertiv_power_source_info[] = { - info_lkp_default(1, ""), /* other */ - info_lkp_default(2, "OFF"), /* none */ - info_lkp_default(3, "OL"), /* normal */ - info_lkp_default(4, "BYPASS"), /* bypass */ - info_lkp_default(5, "OB"), /* battery */ - info_lkp_default(6, "BOOST"), /* booster */ - info_lkp_default(7, "TRIM"), /* reducer */ - info_lkp_sentinel + info_lkp_default(1, "other"), + info_lkp_default(2, "OFF"), + info_lkp_default(3, "OL"), + info_lkp_default(4, "BYPASS"), + info_lkp_default(5, "OB"), + info_lkp_default(6, "BOOST"), + info_lkp_default(7, "TRIM"), + info_lkp_sentinel }; static snmp_info_t vertiv_mib[] = { - /* standard MIB items */ - snmp_info_default("device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK | SU_FLAG_SEMI_STATIC, NULL), - snmp_info_default("device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK | SU_FLAG_SEMI_STATIC, NULL), - snmp_info_default("device.location", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_OK | SU_FLAG_SEMI_STATIC, NULL), - - /* Device Identification from vendor MIB */ - snmp_info_default("device.mfr", 0, 1.0, VERTIV_BASEOID ".2.1.1.0", NULL, SU_FLAG_OK | SU_FLAG_STATIC, NULL), - snmp_info_default("device.model", 0, 1.0, VERTIV_ID_OID, NULL, SU_FLAG_OK | SU_FLAG_STATIC, NULL), - snmp_info_default("device.serial", 0, 1.0, VERTIV_BASEOID ".2.4.2.1.7.1", NULL, SU_FLAG_OK | SU_FLAG_STATIC, NULL), - - /* UPS Measurements - Scaling verified via Audit */ - snmp_info_default("ups.load", 0, 1.0, VERTIV_VAL_OID ".5861", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), - snmp_info_default("ups.temperature", 0, 1.0, VERTIV_BASEOID ".3.9.30.1.10.1.2.1.4291", NULL, SU_FLAG_NEGINVALID, NULL), - - /* Battery Data */ - snmp_info_default("battery.charge", 0, 1.0, VERTIV_VAL_OID ".4153", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), - /* Multiplier 60.0 converts UPS minutes to NUT seconds */ - snmp_info_default("battery.runtime", 0, 60.0, VERTIV_VAL_OID ".4150", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), - snmp_info_default("battery.voltage", 0, 1.0, VERTIV_VAL_OID ".4148", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), - - /* Power Quality - 0.1 multiplier for tenths of Volts/Hz */ - snmp_info_default("input.voltage", 0, 0.1, VERTIV_VAL_OID ".4096", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), - snmp_info_default("input.frequency", 0, 0.1, VERTIV_VAL_OID ".4105", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), - snmp_info_default("output.voltage", 0, 0.1, VERTIV_VAL_OID ".4385", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), - snmp_info_default("output.current", 0, 0.1, VERTIV_VAL_OID ".4204", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), - snmp_info_default("output.power", 0, 1.0, VERTIV_VAL_OID ".4208", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), - - /* UPS Status */ - /* Output Source: 3=Normal(OL), 4/5=Battery(OB) et al */ - snmp_info_default("ups.status", ST_FLAG_STRING, SU_INFOSIZE, VERTIV_VAL_OID ".4872", "", SU_STATUS_PWR | SU_FLAG_OK, vertiv_power_source_info), - - /* Beeper status and commands */ - snmp_info_default("ups.beeper.status", ST_FLAG_STRING, SU_INFOSIZE, VERTIV_BEEPER_OID, "", SU_FLAG_UNIQUE, vertiv_beeper_status_info), - - snmp_info_default("beeper.disable", 0, 1, VERTIV_BEEPER_OID, "2", SU_TYPE_CMD, NULL), - snmp_info_default("beeper.enable", 0, 1, VERTIV_BEEPER_OID, "1", SU_TYPE_CMD, NULL), - - /* IETF MIB fallback */ - snmp_info_default("ups.beeper.status", ST_FLAG_STRING, SU_INFOSIZE, "1.3.6.1.2.1.33.1.9.8.0", "", SU_FLAG_UNIQUE, ietf_beeper_status_info), -#if 0 - snmp_info_default("beeper.disable", 0, 1, "1.3.6.1.2.1.33.1.9.8.0", "1", SU_TYPE_CMD, NULL), - snmp_info_default("beeper.enable", 0, 1, "1.3.6.1.2.1.33.1.9.8.0", "2", SU_TYPE_CMD, NULL), -#endif - snmp_info_default("beeper.mute", 0, 1, "1.3.6.1.2.1.33.1.9.8.0", "3", SU_TYPE_CMD, NULL), - - /* Shutdown / Restart Control - * NOTE: Other sources suggest - * "ups.delay.shutdown" => VERTIV_BASEOID ".3.3.5.1.0" - * "ups.delay.start" => VERTIV_BASEOID ".3.3.5.2.0" - */ - snmp_info_default("ups.delay.shutdown", ST_FLAG_RW, 1.0, VERTIV_VAL_OID ".5814", "", SU_TYPE_TIME | SU_FLAG_OK, NULL), - snmp_info_default("ups.delay.start", ST_FLAG_RW, 1.0, VERTIV_VAL_OID ".5816", "", SU_TYPE_TIME | SU_FLAG_OK, NULL), - - /* end of structure. */ - snmp_info_sentinel + /* Standard MIB items */ + snmp_info_default("device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK | SU_FLAG_SEMI_STATIC, NULL), + snmp_info_default("device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK | SU_FLAG_SEMI_STATIC, NULL), + snmp_info_default("device.location", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_OK | SU_FLAG_SEMI_STATIC, NULL), + + /* Device Identification */ + snmp_info_default("device.mfr", ST_FLAG_STRING, 1.0, VERTIV_BASEOID ".2.1.1.0", NULL, SU_FLAG_OK | SU_FLAG_STATIC, NULL), + snmp_info_default("device.model", ST_FLAG_STRING, 1.0, VERTIV_BASEOID ".2.4.2.1.4.1", NULL, SU_FLAG_OK | SU_FLAG_STATIC, NULL), + snmp_info_default("device.serial", ST_FLAG_STRING, 1.0, VERTIV_BASEOID ".2.4.2.1.7.1", NULL, SU_FLAG_OK | SU_FLAG_STATIC, NULL), + snmp_info_default("ups.firmware", ST_FLAG_STRING, 1.0, VERTIV_BASEOID ".2.4.2.1.5.1", NULL, SU_FLAG_OK | SU_FLAG_STATIC, NULL), + + /* Extended Identification */ + snmp_info_default("device.type", ST_FLAG_STRING, 1.0, VERTIV_BASEOID ".3.9.20.1.20.1.2.1.4553", NULL, SU_FLAG_OK | SU_FLAG_STATIC, NULL), + snmp_info_default("ups.mfr", ST_FLAG_STRING, 1.0, VERTIV_BASEOID ".3.9.20.1.20.1.2.1.4333", NULL, SU_FLAG_OK | SU_FLAG_STATIC, NULL), + snmp_info_default("ups.model", ST_FLAG_STRING, 1.0, VERTIV_BASEOID ".3.9.20.1.20.1.2.1.4240", NULL, SU_FLAG_OK | SU_FLAG_STATIC, NULL), + + /* UPS Measurements & Topology (High-precision) */ + snmp_info_default("ups.load", 0, 1.0, VERTIV_VAL_OID ".5861", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), + snmp_info_default("ups.temperature", 0, 1.0, VERTIV_BASEOID ".3.9.30.1.10.1.2.1.4291", NULL, SU_FLAG_NEGINVALID, NULL), + snmp_info_default("ups.type", ST_FLAG_STRING, 1.0, VERTIV_BASEOID ".3.9.20.1.20.1.2.1.6199", NULL, SU_FLAG_OK | SU_FLAG_STATIC, NULL), + + /* Battery Data */ + snmp_info_default("battery.charge", 0, 1.0, VERTIV_VAL_OID ".4153", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), + snmp_info_default("battery.runtime", 0, 60.0, VERTIV_VAL_OID ".4150", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), + snmp_info_default("battery.voltage", 0, 1.0, VERTIV_VAL_OID ".4148", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), + snmp_info_default("battery.voltage.nominal", 0, 1.0, VERTIV_VAL_OID ".6189", "", SU_FLAG_OK | SU_FLAG_STATIC, NULL), + + /* Power Quality - Scaled (0.1) for high precision decimal values */ + snmp_info_default("input.voltage", 0, 0.1, VERTIV_VAL_OID ".4096", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), + snmp_info_default("input.current", 0, 0.1, VERTIV_VAL_OID ".4113", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), + snmp_info_default("input.frequency", 0, 0.1, VERTIV_VAL_OID ".4105", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), + snmp_info_default("input.voltage.nominal", 0, 1.0, VERTIV_VAL_OID ".4102", "", SU_FLAG_OK | SU_FLAG_STATIC, NULL), + snmp_info_default("input.current.nominal", 0, 1.0, VERTIV_VAL_OID ".4104", "", SU_FLAG_OK | SU_FLAG_STATIC, NULL), + snmp_info_default("input.frequency.nominal", 0, 1.0, VERTIV_VAL_OID ".4103", "", SU_FLAG_OK | SU_FLAG_STATIC, NULL), + snmp_info_default("output.voltage", 0, 0.1, VERTIV_VAL_OID ".4385", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), + snmp_info_default("output.current", 0, 0.1, VERTIV_VAL_OID ".4204", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), + snmp_info_default("output.frequency", 0, 0.1, VERTIV_VAL_OID ".4207", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), + snmp_info_default("output.power", 0, 1.0, VERTIV_VAL_OID ".4208", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), + snmp_info_default("output.power.apparent", 0, 1.0, VERTIV_VAL_OID ".4209", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), + snmp_info_default("output.voltage.nominal", 0, 1.0, VERTIV_VAL_OID ".4260", "", SU_FLAG_OK | SU_FLAG_STATIC, NULL), + snmp_info_default("output.power.nominal", 0, 1.0, VERTIV_VAL_OID ".4264", "", SU_FLAG_OK | SU_FLAG_STATIC, NULL), + + /* UPS Status & Beeper */ + snmp_info_default("ups.status", ST_FLAG_STRING, SU_INFOSIZE, VERTIV_VAL_OID ".4872", "", SU_STATUS_PWR | SU_FLAG_OK, vertiv_power_source_info), + snmp_info_default("ups.beeper.status", ST_FLAG_STRING, SU_INFOSIZE, VERTIV_BEEPER_OID, "", SU_FLAG_OK, vertiv_beeper_status_info), + + /* Instant Commands */ + snmp_info_default("beeper.disable", 0, 1, VERTIV_BEEPER_OID, "2", SU_TYPE_CMD, NULL), + snmp_info_default("beeper.enable", 0, 1, VERTIV_BEEPER_OID, "1", SU_TYPE_CMD, NULL), + + /* Shutdown & Restart */ + snmp_info_default("ups.delay.shutdown", ST_FLAG_RW, 1.0, VERTIV_VAL_OID ".5814", "", SU_TYPE_TIME | SU_FLAG_OK, NULL), + snmp_info_default("ups.delay.start", ST_FLAG_RW, 1.0, VERTIV_VAL_OID ".5816", "", SU_TYPE_TIME | SU_FLAG_OK, NULL), + + snmp_info_sentinel }; static alarms_info_t vertiv_alarms[] = { - /* Event Branch Monitoring */ - { VERTIV_ALM_OID ".4168", "OB", "Battery Discharging" }, - { VERTIV_ALM_OID ".4162", "LB", "Battery Low" }, - { VERTIV_ALM_OID ".5806", "OVER", "Output Overload" }, - { VERTIV_ALM_OID ".6182", "RB", "Replace Battery" }, - { VERTIV_ALM_OID ".4233", "FAULT", "Inverter Failure" }, - { VERTIV_ALM_OID ".4310", "OT", "Over Temperature" }, - { VERTIV_ALM_OID ".4215", "OFF", "UPS Output Off" }, - { NULL, NULL, NULL } + { VERTIV_ALM_OID ".4168", "OB", "Battery Discharging" }, + { VERTIV_ALM_OID ".4162", "LB", "Battery Low" }, + { VERTIV_ALM_OID ".5806", "OVER", "Output Overload" }, + { VERTIV_ALM_OID ".6182", "RB", "Replace Battery" }, + { VERTIV_ALM_OID ".4233", "FAULT", "Inverter Failure" }, + { VERTIV_ALM_OID ".4310", "OT", "Over Temperature" }, + { VERTIV_ALM_OID ".4215", "OFF", "UPS Output Off" }, + { NULL, NULL, NULL } }; mib2nut_info_t vertiv = { - "vertiv", - VERTIV_MIB_VERSION, - VERTIV_PWRSTATUS_OID,/* Optional Power Status OID */ - VERTIV_ID_OID, /* Model Name OID */ - vertiv_mib, - VERTIV_BASEOID, /* SysOID fingerprint */ - vertiv_alarms + "vertiv", + VERTIV_MIB_VERSION, + VERTIV_PWRSTATUS_OID, + VERTIV_ID_OID, + vertiv_mib, + VERTIV_BASEOID, + vertiv_alarms }; From f436906859d3e00680726b9e5f160e1c3f0e0ed0 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Feb 2026 13:46:56 +0000 Subject: [PATCH 124/198] scripts/augeas/gen-nutupsconf-aug.py.in, scripts/python/module/setup.py.in: fix codecs.open() deprecation warning (3.14+) [#3256] Signed-off-by: Jim Klimov Co-Authored-by: Paul Donald --- scripts/augeas/gen-nutupsconf-aug.py.in | 44 +++++++++++++++++++++---- scripts/python/module/setup.py.in | 30 +++++++++++++++-- 2 files changed, 65 insertions(+), 9 deletions(-) diff --git a/scripts/augeas/gen-nutupsconf-aug.py.in b/scripts/augeas/gen-nutupsconf-aug.py.in index 07374ac940..29fa19c15d 100755 --- a/scripts/augeas/gen-nutupsconf-aug.py.in +++ b/scripts/augeas/gen-nutupsconf-aug.py.in @@ -1,7 +1,7 @@ #!@PYTHON_DEFAULT@ # Copyright (C) # 2010 - Arnaud Quette -# 2020 - 2024 Jim Klimov +# 2020 - 2026 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 @@ -23,9 +23,29 @@ from __future__ import print_function import sys +import os import re import glob -import codecs + +try: + # NOTE: Deprecated as of python3.14 + import codecs + HAVE_CODECS = True + fd = None + try: + # Open self to test that it works + fd = codecs.open(os.path.abspath(__file__), mode="r", encoding='utf-8') + USE_CODECS = True + # sys.stderr.write("INFO: import codecs went well, and codecs.open() did not raise exceptions\n") + except DeprecationWarning as x: + USE_CODECS = False + # sys.stderr.write("WARNING: import codecs went well, but codecs.open() failed: %s\n" % str(x)) + if fd is not None: + fd.close() +except Exception as x: + # sys.stderr.write("WARNING: import codecs failed: %s\n" % str(x)) + HAVE_CODECS = False + USE_CODECS = False # Return a sorted list of unique entries, based on the input 'list' def sortUnique(list): @@ -80,7 +100,10 @@ if __name__ == '__main__': for filename in glob.glob('../../drivers/*.c'): # 1.2/ Exclude main.c, which defines addvar() and skel.c (example driver) if filename not in Exceptionlist: - fd = codecs.open(filename, encoding='utf-8') + if USE_CODECS: + fd = codecs.open(filename, encoding='utf-8') + else: + fd = open(filename, encoding='utf-8') # 1.3/ Grep for the "addvar(..." pattern matchResults = grep (r'.*addvar[\ ]*\(.*(VAR_FLAG|VAR_VALUE)*,.*', fd) @@ -95,7 +118,10 @@ if __name__ == '__main__': # Let's grep in .ch related files if (row[1].find('"') == -1): for defFilename in glob.glob(filename.replace('.c', '.[ch]')): - defFd = codecs.open(defFilename, encoding='utf-8') + if USE_CODECS: + defFd = codecs.open(defFilename, encoding='utf-8') + else: + defFd = open(defFilename, encoding='utf-8') matchString = '^#define.*' + row[1].replace('"', '').lstrip() + '.*' matchResult = grep (matchString, defFd) for varDefine in matchResult: @@ -115,12 +141,18 @@ if __name__ == '__main__': specificVars += " | \"%s\"\n" %(name) # 2/ Load the template lens - tplFd = codecs.open(dirPrefix + templateFilename, encoding='utf-8') + if USE_CODECS: + tplFd = codecs.open(dirPrefix + templateFilename, encoding='utf-8') + else: + tplFd = open(dirPrefix + templateFilename, encoding='utf-8') # 2.1/ Search for the pattern to replace outputText = tplFd.read() outputText = outputText.replace('@SPECIFIC_DRV_VARS@', specificVars) # 3/ Output final lens - outFd = codecs.open(outputFilename, mode='w', encoding='utf-8') + if USE_CODECS: + outFd = codecs.open(outputFilename, mode='w', encoding='utf-8') + else: + outFd = open(outputFilename, mode='w', encoding='utf-8') outFd.write(outputText) diff --git a/scripts/python/module/setup.py.in b/scripts/python/module/setup.py.in index d520c960f9..098e2d43b4 100644 --- a/scripts/python/module/setup.py.in +++ b/scripts/python/module/setup.py.in @@ -5,14 +5,38 @@ The setup.py file for PyNUTClient # See also .github/workflows/PyNUTClient.yml for active packaging steps from setuptools import setup, find_packages -import codecs import os +import sys here = os.path.abspath(os.path.dirname(__file__)) +try: + # NOTE: Deprecated as of python3.14 + import codecs + HAVE_CODECS = True + fd = None + try: + # Open self to test that it works + fd = codecs.open(os.path.abspath(__file__), mode="r", encoding='utf-8') + USE_CODECS = True + # sys.stderr.write("INFO: import codecs went well, and codecs.open() did not raise exceptions\n") + except DeprecationWarning as x: + USE_CODECS = False + # sys.stderr.write("WARNING: import codecs went well, but codecs.open() failed: %s\n" % str(x)) + if fd is not None: + fd.close() +except Exception as x: + # sys.stderr.write("WARNING: import codecs failed: %s\n" % str(x)) + HAVE_CODECS = False + USE_CODECS = False + # README.txt appears from README.adoc during package or CI build -with codecs.open(os.path.join(here, "README.txt"), encoding="utf-8") as fh: - long_description = "\n" + fh.read() +if USE_CODECS: + with codecs.open(os.path.join(here, "README.txt"), encoding="utf-8") as fh: + long_description = "\n" + fh.read() +else: + with open(os.path.join(here, "README.txt"), encoding="utf-8") as fh: + long_description = "\n" + fh.read() setup( name = "pynutclient", ### "PyNUTClient" lower-cased due to PEP-0625 From 14d59dae8c0a56100c260cd8553cf3c604799b76 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Feb 2026 16:05:31 +0100 Subject: [PATCH 125/198] Makefile.am: SET_PARMAKES_OPT snippet should not have started with "+@" (was a goal body before) Signed-off-by: Jim Klimov --- Makefile.am | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index c168279be4..704d8b329d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -751,8 +751,8 @@ spellcheck spellcheck-interactive: # Auto-parallel recipe (if current 'make' implementation supports the "-j N" # syntax; the optional MAXPARMAKES may be set in NUT CI farm style builds): SET_PARMAKES_OPT = \ - +@PARMAKES_OPT=""; \ - case " $(MAKEFLAGS) $(AM_MAKEFLAGS)" in \ + PARMAKES_OPT=""; \ + case " $(MAKEFLAGS) $(AM_MAKEFLAGS)" in \ *"j"*) ;; \ *) \ if [ "$${MAXPARMAKES-}" -gt 1 ] 2>/dev/null ; then \ @@ -760,7 +760,7 @@ SET_PARMAKES_OPT = \ fi ; \ PARMAKES_OPT="-j $${MAXPARMAKES}" ; \ ;; \ - esac + esac spellcheck-quick: +@$(SET_PARMAKES_OPT); \ From 77a81259bd552a930a60222157eb4d8ab5b5e83f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Feb 2026 16:06:07 +0100 Subject: [PATCH 126/198] Makefile.am: package: should not depend on "dist" to package up "all" the already-built artefacts Thanks to Lee Damon for the heads-up Signed-off-by: Jim Klimov --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 704d8b329d..5b691be959 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1475,7 +1475,7 @@ MAINTAINERCLEANFILES_PACKAGES += *.p5p MAINTAINERCLEANFILES += $(MAINTAINERCLEANFILES_DISTBALL) MAINTAINERCLEANFILES += $(MAINTAINERCLEANFILES_PACKAGES) -package: dist +package: all +DESTDIR="$(abs_builddir)/_install_pkgprotodir" ; export DESTDIR; \ rm -rf "$$DESTDIR"; \ case "`uname -s`" in \ From 9c2751cf05d9e7493eceeac6bbeb28a6bc0c5939 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Feb 2026 17:33:49 +0000 Subject: [PATCH 127/198] scripts/python/module/Makefile.am: better indent multi-line rules Signed-off-by: Jim Klimov --- scripts/python/module/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/python/module/Makefile.am b/scripts/python/module/Makefile.am index b8f1553dc9..22bd7f7ba6 100644 --- a/scripts/python/module/Makefile.am +++ b/scripts/python/module/Makefile.am @@ -124,8 +124,8 @@ upload publish: # Using pypa/setuptools .pypi-dist: .pypi-src +@$(MAKE) $(AM_MAKEFLAGS) .pypi-dist-pip-build || \ - $(MAKE) $(AM_MAKEFLAGS) .pypi-dist-obsolete || \ - $(MAKE) $(AM_MAKEFLAGS) .pypi-dist-pip-wheel + $(MAKE) $(AM_MAKEFLAGS) .pypi-dist-obsolete || \ + $(MAKE) $(AM_MAKEFLAGS) .pypi-dist-pip-wheel @touch '$@' # The most modern approach as of 2023 From eb3a409cf47967ce5b6f2dfca27fb71e0dabe496 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Feb 2026 14:50:51 +0000 Subject: [PATCH 128/198] configure.ac, Makefile.am, NEWS.adoc: mark goals which expand SUBDIR_TGT_RULE with explicit .MAKE pseudo-target [#3300] The BSD make as of NetBSD 11 (Beta) updates gets confused about sub-calls to $(MAKE) with respective $(MAKEFLAGS) passed to it with our parallel build scripting, despite the standard "+" prefix to commands in the caller. An explicit pseudo-target seems to help quiesce the warnings (and hopefully rectify the practical handling). Co-authored-by: Greg Troxel Signed-off-by: Jim Klimov --- Makefile.am | 138 +++++++++++++++--------------- NEWS.adoc | 8 ++ clients/Makefile.am | 4 +- common/Makefile.am | 2 +- conf/Makefile.am | 8 +- configure.ac | 23 ++++- data/Makefile.am | 6 +- data/htmlcgi/Makefile.am | 8 +- docs/Makefile.am | 36 ++++---- docs/man/Makefile.am | 8 +- drivers/Makefile.am | 4 +- scripts/Makefile.am | 8 +- scripts/Solaris/Makefile.am | 8 +- scripts/Windows/Makefile.am | 12 +-- scripts/devd/Makefile.am | 8 +- scripts/external_apis/Makefile.am | 8 +- scripts/hotplug/Makefile.am | 8 +- scripts/installer/Makefile.am | 8 +- scripts/obs/Makefile.am | 8 +- scripts/python/Makefile.am | 8 +- scripts/python/module/Makefile.am | 4 +- scripts/systemd/Makefile.am | 8 +- scripts/udev/Makefile.am | 8 +- scripts/upsdrvsvcctl/Makefile.am | 8 +- server/Makefile.am | 4 +- tests/Makefile.am | 6 +- tests/NIT/Makefile.am | 12 +-- tools/nut-scanner/Makefile.am | 8 +- tools/nutconf/Makefile.am | 4 +- 29 files changed, 206 insertions(+), 177 deletions(-) diff --git a/Makefile.am b/Makefile.am index 5b691be959..bb569d602d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -97,7 +97,7 @@ SUBDIR_MAKE_VERBOSE = default # Run the standard build if going sequential (or with unknown MAKEFLAGS), # or fanout if parallel (presuming GNU/BSD/Sun make at least): -all-fanout-maybe: +all-fanout-maybe: @dotMAKE@ +@if [ x"$(NUT_MAKE_SKIP_FANOUT)" = xtrue ] ; then \ if [ x"$(SUBDIR_MAKE_VERBOSE)" != x0 ] ; then \ echo " SUBDIR-MAKE $@: skip optimization for parallel make - NUT_MAKE_SKIP_FANOUT is set" ; \ @@ -129,7 +129,7 @@ all-fanout-maybe: # FIXME: Alas, we still tend to step on our toes when making everything at # once from scratch, so still do benefit from pre-making the libraries: -all-fanout-staged: +all-fanout-staged: @dotMAKE@ +$(MAKE) $(AM_MAKEFLAGS) NUT_VERSION_H_GENERATED=false all/include +$(MAKE) $(AM_MAKEFLAGS) NUT_VERSION_H_GENERATED=true all/common +$(MAKE) $(AM_MAKEFLAGS) NUT_VERSION_H_GENERATED=true all-fanout-libs @@ -139,7 +139,7 @@ all-fanout-subdirs: $(SUBDIRS_ALL_RECURSIVE) all-fanout-libs all-libs-local: $(SUBDIRS_ALL_LIBS_LOCAL) -#all all-am-local all-local: +#all all-am-local all-local: @dotMAKE@ # +@cd common && $(MAKE) $(AM_MAKEFLAGS) all # +@$(MAKE) $(AM_MAKEFLAGS) all-recursive # +@$(MAKE) $(AM_MAKEFLAGS) doc @@ -213,7 +213,7 @@ SUBDIR_TGT_RULE = ( \ # git grep -E '(LTLIBRARIES|\.la([ :'"`printf '\t'`"']|$))' '*.am' ### Delivers: nut_version.h -all-libs-local/include: +all-libs-local/include: @dotMAKE@ +@NUT_VERSION_H_GENERATED=false; export NUT_VERSION_H_GENERATED; \ $(SUBDIR_TGT_RULE) @@ -224,7 +224,7 @@ all-libs-local/include: ### May deliver: libnutprivate-$(SEMVER)-common-all.la and libnutprivate-$(SEMVER)-common-client.la for dynamic shared-object linking, libcommonversion-private.la (dependency for the above) ### Requires-ext: include/nut_version.h ### Requires-int: libparseconf.la libcommonclient.la -all-libs-local/common: all-libs-local/include +all-libs-local/common: all-libs-local/include @dotMAKE@ +@NUT_VERSION_H_GENERATED=true; export NUT_VERSION_H_GENERATED; \ $(SUBDIR_TGT_RULE) @@ -236,7 +236,7 @@ all-libs-local/common: all-libs-local/include ### Requires-ext: common/libparseconf.la ### For dynamic builds, alternately LIB-Requires-ext and Requires-ext: libnutprivate-$(SEMVER)-common*.la ### Requires-int: libupsclient.la -all-libs-local/clients: all-libs-local/common +all-libs-local/clients: all-libs-local/common @dotMAKE@ +@NUT_VERSION_H_GENERATED=true; export NUT_VERSION_H_GENERATED; \ $(SUBDIR_TGT_RULE) @@ -249,7 +249,7 @@ all-libs-local/clients: all-libs-local/common ### Requires-int: libdummy_serial.la ### For dynamic builds, alternately LIB-Requires-ext and Requires-ext: libnutprivate-$(SEMVER)-common*.la ### and may deliver: libnutprivate-$(SEMVER)-drivers-common.la and libnutprivate-$(SEMVER)-drivers-serial.la -all-libs-local/drivers: all-libs-local/common +all-libs-local/drivers: all-libs-local/common @dotMAKE@ +@NUT_VERSION_H_GENERATED=true; export NUT_VERSION_H_GENERATED; \ $(SUBDIR_TGT_RULE) @@ -259,14 +259,14 @@ all-libs-local/drivers: all-libs-local/common ### Requires-ext: clients/libnutclient.la clients/libnutclientstub.la ### Requires-ext: drivers/libdummy_mockdrv.la ### Requires-int: libdriverstubusb.la -all-libs-local/tests: all-libs-local/common +all-libs-local/tests: all-libs-local/common @dotMAKE@ +@NUT_VERSION_H_GENERATED=true; export NUT_VERSION_H_GENERATED; \ $(SUBDIR_TGT_RULE) ### Delivers: generated sources and/or headers for nut-scanner ### No dependencies: actually runs as part of autogen.sh but may be ### re-run during development when USB or SNMP driver sources change. -all-libs-local/tools: +all-libs-local/tools: @dotMAKE@ +@$(SUBDIR_TGT_RULE) ### Delivers: libnutscan.la @@ -281,7 +281,7 @@ all-libs-local/tools: ### Note: indirectly (ltdl) may use installed libupsclient.so ### however does directly use libupsclient-version.h ### for hints to find it at run-time -all-libs-local/tools/nut-scanner: all-libs-local/drivers all-libs-local/common all-libs-local/clients all-libs-local/tools +all-libs-local/tools/nut-scanner: all-libs-local/drivers all-libs-local/common all-libs-local/clients all-libs-local/tools @dotMAKE@ +@NUT_VERSION_H_GENERATED=true; export NUT_VERSION_H_GENERATED; \ $(SUBDIR_TGT_RULE) @@ -296,22 +296,22 @@ all/conf \ all/lib \ .ChangeLog.adoc-parsed.latest/docs \ ChangeLog.adoc-parsed/docs \ -all-recursive/data: +all-recursive/data: @dotMAKE@ +@$(SUBDIR_TGT_RULE) -all/include: all-libs-local/include +all/include: all-libs-local/include @dotMAKE@ +@NUT_VERSION_H_GENERATED=true; export NUT_VERSION_H_GENERATED; \ $(SUBDIR_TGT_RULE) -prep-src-docs/docs/man: +prep-src-docs/docs/man: @dotMAKE@ +@SUBDIR_TGT_MAKEFLAGS='MAINTAINER_DOCS_PREP_MAN_DELAY=3'; export SUBDIR_TGT_MAKEFLAGS; \ $(SUBDIR_TGT_RULE) -prep-src-docs/docs: +prep-src-docs/docs: @dotMAKE@ +@DOCS_NO_MAN=true; export DOCS_NO_MAN; \ $(SUBDIR_TGT_RULE) -all/docs/man: prep-src-docs/docs/man +all/docs/man: prep-src-docs/docs/man @dotMAKE@ +@$(SUBDIR_TGT_RULE) # Note: we optionally sort of depend on ChangeLog.adoc so it is pre-made and @@ -320,7 +320,7 @@ all/docs/man: prep-src-docs/docs/man # BUT we do not want to (re-)build ChangeLog if no (relevant) DOC_BUILD_LIST # types are enabled. MAINTAINER_ASCIIDOCS_CHANGELOG_DELAY = 0 -all/docs: prep-src-docs/docs/man +all/docs: prep-src-docs/docs/man @dotMAKE@ +@case "@DOC_BUILD_LIST@" in \ *pdf*|*html-single*|*html-chunked*) \ echo " DOC-CHANGELOG-ASCIIDOC Pre-generate ChangeLog artifacts before the bulk of $@ ..." ; \ @@ -334,7 +334,7 @@ all/docs: prep-src-docs/docs/man +@$(MAKE) $(AM_MAKEFLAGS) prep-src-docs/docs +@DOCS_NO_MAN=true; export DOCS_NO_MAN; $(SUBDIR_TGT_RULE) -all-recursive/docs: all/docs all/docs/man +all-recursive/docs: all/docs all/docs/man @dotMAKE@ +@$(SUBDIR_TGT_RULE) # Dependencies below are dictated by who needs whose library from another dir @@ -345,7 +345,7 @@ all-recursive/docs: all/docs all/docs/man # that the top-level make completes needed (all-libs*) targets before drilling. ### Requires-int: libparseconf.la libcommonclient.la -all/common: all/include all-libs-local/common +all/common: all/include all-libs-local/common @dotMAKE@ +@NUT_VERSION_H_GENERATED=true; export NUT_VERSION_H_GENERATED; \ $(SUBDIR_TGT_RULE) @@ -354,7 +354,7 @@ all/common: all/include all-libs-local/common ### Requires-ext: common/libcommonversion.la ### Requires-ext: common/libcommonstrjson.la ### Requires-int: libupsclient.la -all/clients: all/common all-libs-local/clients +all/clients: all/common all-libs-local/clients @dotMAKE@ +@NUT_VERSION_H_GENERATED=true; export NUT_VERSION_H_GENERATED; \ $(SUBDIR_TGT_RULE) @@ -378,7 +378,7 @@ if SOME_DRIVERS # build whichever drivers are enabled (no idea if dummy-ups is # in the default list - FIXME: configure.ac could tell us, so # we could provide it for tests/NIT anyway...) -all/drivers: all-libs-local/clients all-libs-local/common all-libs-local/drivers +all/drivers: all-libs-local/clients all-libs-local/common all-libs-local/drivers @dotMAKE@ +@NUT_VERSION_H_GENERATED=true; export NUT_VERSION_H_GENERATED; \ $(SUBDIR_TGT_RULE) @@ -391,21 +391,21 @@ else !SOME_DRIVERS # separate target with separate dependency trail, then "all-drivers" # should depend on both "dummy-ups" and the rest in so constrained # "all/drivers". This allows to ultimately not order one after another. -dummy-ups$(EXEEXT)/drivers: all-libs-local/clients all-libs-local/common all-libs-local/drivers +dummy-ups$(EXEEXT)/drivers: all-libs-local/clients all-libs-local/common all-libs-local/drivers @dotMAKE@ +@NUT_VERSION_H_GENERATED=true; export NUT_VERSION_H_GENERATED; \ $(SUBDIR_TGT_RULE) -all/drivers: all/common all-libs-local/drivers +all/drivers: all/common all-libs-local/drivers @dotMAKE@ +@NUT_VERSION_H_GENERATED=true; export NUT_VERSION_H_GENERATED; \ SUBDIR_TGT_MAKEFLAGS='NUTSW_DRIVERLIST_DUMMY_UPS=dummy'; export SUBDIR_TGT_MAKEFLAGS; \ $(SUBDIR_TGT_RULE) -all-drivers: dummy-ups$(EXEEXT)/drivers all/drivers +all-drivers: dummy-ups$(EXEEXT)/drivers all/drivers @dotMAKE@ endif !SOME_DRIVERS ### Requires-ext: common/libcommon.la common/libparseconf.la ### Requires-ext: common/libcommonversion.la -all/server: all-libs-local/common +all/server: all-libs-local/common @dotMAKE@ +@NUT_VERSION_H_GENERATED=true; export NUT_VERSION_H_GENERATED; \ $(SUBDIR_TGT_RULE) @@ -416,7 +416,7 @@ all/server: all-libs-local/common ### Requires-int: libnutscan.la all/tools/nut-scanner: all-libs-local/include all-libs-local/common \ all-libs-local/drivers all-libs-local/clients \ - all-libs-local/tools/nut-scanner + all-libs-local/tools/nut-scanner @dotMAKE@ +@NUT_VERSION_H_GENERATED=true; export NUT_VERSION_H_GENERATED; \ $(SUBDIR_TGT_RULE) @@ -425,11 +425,11 @@ all/tools/nut-scanner: all-libs-local/include all-libs-local/common \ ### Requires-ext: common/libcommon.la common/libnutconf.la ### Requires-ext: common/libcommonversion.la ### Requires-ext: tools/nut-scanner/libnutscan.la -all/tools/nutconf: all-libs-local/tools/nut-scanner all-libs-local/common +all/tools/nutconf: all-libs-local/tools/nut-scanner all-libs-local/common @dotMAKE@ +@NUT_VERSION_H_GENERATED=true; export NUT_VERSION_H_GENERATED; \ $(SUBDIR_TGT_RULE) -all-recursive/tools: all/tools/nutconf all/tools/nut-scanner +all-recursive/tools: all/tools/nutconf all/tools/nut-scanner @dotMAKE@ +@NUT_VERSION_H_GENERATED=true; export NUT_VERSION_H_GENERATED; \ $(SUBDIR_TGT_RULE) @@ -440,7 +440,7 @@ all-recursive/tools: all/tools/nutconf all/tools/nut-scanner # if it is not enabled among SOME_DRIVERS, things can get funny... # But then we should also consider what is enabled by configure and what is not. # Maybe we are doing a quick build not to be tested at all? :-/ -all/tests/NIT: all/clients all/server all-drivers all-recursive/tools all-recursive/data +all/tests/NIT: all/clients all/server all-drivers all-recursive/tools all-recursive/data @dotMAKE@ +@NUT_VERSION_H_GENERATED=true; export NUT_VERSION_H_GENERATED; \ $(SUBDIR_TGT_RULE) @@ -449,11 +449,11 @@ all/tests/NIT: all/clients all/server all-drivers all-recursive/tools all-recurs ### Requires-ext: clients/libnutclient.la clients/libnutclientstub.la ### Requires-ext: drivers/libdummy_mockdrv.la ### Requires-int: libdriverstubusb.la -all/tests: all-libs-local/tests all-libs-local/drivers all-libs-local/common all-libs-local/clients +all/tests: all-libs-local/tests all-libs-local/drivers all-libs-local/common all-libs-local/clients @dotMAKE@ +@NUT_VERSION_H_GENERATED=true; export NUT_VERSION_H_GENERATED; \ $(SUBDIR_TGT_RULE) -all-recursive/tests: all/tests/NIT all/tests +all-recursive/tests: all/tests/NIT all/tests @dotMAKE@ +@NUT_VERSION_H_GENERATED=true; export NUT_VERSION_H_GENERATED; \ $(SUBDIR_TGT_RULE) @@ -461,21 +461,21 @@ if HAVE_MINGW_RESGEN if HAVE_WINDOWS ### Requires-ext: common/libcommon.la ### Requires-ext: common/libcommonversion.la -all/scripts/Windows: all-libs-local/common +all/scripts/Windows: all-libs-local/common @dotMAKE@ +@NUT_VERSION_H_GENERATED=true; export NUT_VERSION_H_GENERATED; \ $(SUBDIR_TGT_RULE) else !HAVE_WINDOWS -all/scripts/Windows: +all/scripts/Windows: @dotMAKE@ +@NUT_VERSION_H_GENERATED=true; export NUT_VERSION_H_GENERATED; \ $(SUBDIR_TGT_RULE) endif !HAVE_WINDOWS else !HAVE_MINGW_RESGEN -all/scripts/Windows: +all/scripts/Windows: @dotMAKE@ +@NUT_VERSION_H_GENERATED=true; export NUT_VERSION_H_GENERATED; \ $(SUBDIR_TGT_RULE) endif !HAVE_MINGW_RESGEN -all-recursive/scripts: all/scripts/Windows +all-recursive/scripts: all/scripts/Windows @dotMAKE@ +@NUT_VERSION_H_GENERATED=true; export NUT_VERSION_H_GENERATED; \ $(SUBDIR_TGT_RULE) @@ -548,7 +548,7 @@ endif !KNOWN_UNABLE_MANS # Helper for a number of recipes below that explicitly agree to not require # always real man pages (but require them to dist => distcheck-something) # for CI or developer iterations on environments with incomplete tool kits: -distcheck-light-DIST_ALL_PAGES: +distcheck-light-DIST_ALL_PAGES: @dotMAKE@ @echo "Starting $@" >&2 +@cd "$(abs_builddir)/docs/man" && $(MAKE) $(AM_MAKEFLAGS) all +@cd "$(abs_builddir)/docs/man" && $(MAKE) $(AM_MAKEFLAGS) distcheck-light-DIST_ALL_PAGES @@ -557,7 +557,7 @@ distcheck-light-DIST_ALL_PAGES: # In some recipes we `configure --with-docs=skip`, so "make dist" should not # hiccup on lack of the page files (nor try to make them); not using simple # distcheck-light-DIST_ALL_PAGES step due to custom logic! -distcheck-light-DIST_ALL_PAGES-docs-skipped: +distcheck-light-DIST_ALL_PAGES-docs-skipped: @dotMAKE@ @echo "Starting $@" >&2 +@cd $(abs_builddir)/docs/man && $(MAKE) $(AM_MAKEFLAGS) prep-src-docs +@cd $(abs_builddir)/docs/man && $(MAKE) $(AM_MAKEFLAGS) FAKE_PAGES_BUMP_SRC=false distcheck-light-DIST_ALL_PAGES @@ -566,7 +566,7 @@ distcheck-light-DIST_ALL_PAGES-docs-skipped: # Here we generate man pages (if absent) or fake them # Require other dependencies as usual distcheck does; # be sure to pass through caller's DISTCHECK_FLAGS (if any) -distcheck-fake-man: distcheck-light-DIST_ALL_PAGES +distcheck-fake-man: distcheck-light-DIST_ALL_PAGES @dotMAKE@ @echo "Starting $@" >&2 +prefix='$${prefix}'; if test x"$(DISTCHECK_FLAGS)" = x ; then \ $(MAKE) $(AM_MAKEFLAGS) distcheck ; \ @@ -575,7 +575,7 @@ distcheck-fake-man: distcheck-light-DIST_ALL_PAGES fi @echo "Completed $@: strict distcheck, but with possibly faked pre-built man pages" >&2 -dist-fake-man: distcheck-light-DIST_ALL_PAGES +dist-fake-man: distcheck-light-DIST_ALL_PAGES @dotMAKE@ @echo "Starting $@" >&2 +prefix='$${prefix}'; $(MAKE) $(AM_MAKEFLAGS) dist @echo "Completed $@: strict dist, but with possibly faked pre-built man pages" >&2 @@ -583,21 +583,21 @@ dist-fake-man: distcheck-light-DIST_ALL_PAGES # Here we allow to skip docs if tools are absent, so "make dist" # should not hiccup on lack of the page files (but MAY make them # if it can); be relaxed toward other dependencies. -distcheck-light: distcheck-light-DIST_ALL_PAGES +distcheck-light: distcheck-light-DIST_ALL_PAGES @dotMAKE@ @echo "Starting $@" >&2 +prefix='$${prefix}'; $(MAKE) $(AM_MAKEFLAGS) DISTCHECK_FLAGS="$(DISTCHECK_LIGHT_FLAGS)" distcheck @echo "Completed $@: relaxed distcheck, with possibly faked pre-built man pages" >&2 # Require man pages to be built (or fail trying), but not other docs; # be relaxed toward other dependencies. -distcheck-light-man: +distcheck-light-man: @dotMAKE@ @echo "Starting $@" >&2 +prefix='$${prefix}'; $(MAKE) $(AM_MAKEFLAGS) DISTCHECK_FLAGS="$(DISTCHECK_LIGHT_MAN_FLAGS)" distcheck @echo "Completed $@: relaxed distcheck, with real man pages" >&2 if HAVE_VALGRIND # Make the check in current build, if possible -memcheck: +memcheck: @dotMAKE@ @echo "Starting $@" >&2 @echo "See also scripts/valgrind in NUT sources for a helper tool" +@cd $(builddir)/tests && $(MAKE) $(AM_MAKEFLAGS) -s $@ @@ -606,7 +606,7 @@ memcheck: # Here we skip docs so "make dist" should not hiccup on lack of the page files # (nor try to make them); not using simple distcheck-light-DIST_ALL_PAGES step # due to custom logic! -distcheck-valgrind: distcheck-light-DIST_ALL_PAGES-docs-skipped +distcheck-valgrind: distcheck-light-DIST_ALL_PAGES-docs-skipped @dotMAKE@ @echo "Starting $@" >&2 @echo "See also scripts/valgrind in NUT sources for a helper tool" +prefix='$${prefix}'; $(MAKE) $(AM_MAKEFLAGS) DISTCHECK_FLAGS="$(DISTCHECK_VALGRIND_FLAGS)" distcheck @@ -663,7 +663,7 @@ maintainer-clean-local: # are included by generated Makefiles from other subdirectories, so they # should be available during their clean-up). Just in case, we make sure # here that their sub-distcleans complete first. -distclean-local: +distclean-local: @dotMAKE@ +@for DIR in $(SUBDIRS) ; do \ if test -f "$${DIR}/Makefile" ; then \ echo " DISTCLEAN in $${DIR}" >&2 ; \ @@ -702,10 +702,10 @@ SPELLCHECK_DIRS_LAST = spellcheck/tests/NIT SPELLCHECK_DIRS = $(SPELLCHECK_DIRS_MOST) $(SPELLCHECK_DIRS_LAST) -$(SPELLCHECK_DIRS_MOST): prep-src-docs/docs/man prep-src-docs/docs +$(SPELLCHECK_DIRS_MOST): prep-src-docs/docs/man prep-src-docs/docs @dotMAKE@ +@TGT="$(SPELLCHECK_TGT)"; export TGT; $(SUBDIR_TGT_RULE) -$(SPELLCHECK_DIRS_LAST): prep-src-docs/docs/man prep-src-docs/docs $(SPELLCHECK_DIRS_MOST) +$(SPELLCHECK_DIRS_LAST): prep-src-docs/docs/man prep-src-docs/docs $(SPELLCHECK_DIRS_MOST) @dotMAKE@ +@SUBDIR_TGT_MAKEFLAGS="SPELLCHECK_REPORT_MAYBE_UPDATED_DICT=yes"; \ export SUBDIR_TGT_MAKEFLAGS; \ TGT="$(SPELLCHECK_TGT)"; export TGT; \ @@ -716,7 +716,7 @@ $(SPELLCHECK_DIRS_LAST): prep-src-docs/docs/man prep-src-docs/docs $(SPELLCHECK_ # but using the correct make target for this goal: # FIXME: fanned-out recipes tend to fail early despite "make -ks", so for # now we retry with a not-fanned-out attempt to cover most touch-files -spellcheck spellcheck-interactive: +spellcheck spellcheck-interactive: @dotMAKE@ +@SUBDIR_TGT_MAKEFLAGS="$${SUBDIR_TGT_MAKEFLAGS-} -k -s " ; export SUBDIR_TGT_MAKEFLAGS ; \ if [ x"$(NUT_MAKE_SKIP_FANOUT)" = xtrue ] ; then \ RES=0 ; \ @@ -762,12 +762,12 @@ SET_PARMAKES_OPT = \ ;; \ esac -spellcheck-quick: +spellcheck-quick: @dotMAKE@ +@$(SET_PARMAKES_OPT); \ $(MAKE) $(AM_MAKEFLAGS) -k -s ${PARMAKES_OPT} spellcheck # Run auto-parallel recipe, and if something fails - re-run interactively: -spellcheck-interactive-quick: +spellcheck-interactive-quick: @dotMAKE@ +@$(MAKE) $(AM_MAKEFLAGS) -k -s spellcheck-quick && exit ; \ echo "WARNING: in $@: make spellcheck-quick failed, retrying with spellcheck-interactive" >&2 ; \ if [ x"$(SUBDIR_MAKE_VERBOSE)" = xdefault ] ; then \ @@ -782,12 +782,12 @@ spellcheck-interactive-quick: # texts, man pages and HTML rendering of man pages, as enabled by tools. doc spellcheck-sortdict spellcheck-report-dict-usage \ all-docs check-docs \ -man all-man man-man check-man check-man-man html-man all-html: +man all-man man-man check-man check-man-man html-man all-html: @dotMAKE@ +cd $(abs_top_builddir)/docs && $(MAKE) $(AM_MAKEFLAGS) -s $(abs_top_builddir)/docs/.prep-src-docs +cd $(abs_top_builddir)/docs/man && $(MAKE) $(AM_MAKEFLAGS) -s $(abs_top_builddir)/docs/man/.prep-src-docs +cd $(abs_top_builddir)/docs && $(MAKE) $(AM_MAKEFLAGS) $@ -INSTALL.nut UPGRADING NEWS README: +INSTALL.nut UPGRADING NEWS README: @dotMAKE@ +cd $(abs_top_builddir)/docs && $(MAKE) $(AM_MAKEFLAGS) ../$(@F).adoc-parsed && cp -f ../$(@F).adoc-parsed ../$(@F) # Workarounds for https://github.com/github/markup/issues/1095 @@ -850,7 +850,7 @@ maintainer-asciidocs: fi; \ ) -check-NIT check-NIT-devel check-NIT-sandbox check-NIT-sandbox-devel: +check-NIT check-NIT-devel check-NIT-sandbox check-NIT-sandbox-devel: @dotMAKE@ +cd $(builddir)/tests/NIT && $(MAKE) $(AM_MAKEFLAGS) $@ VERSION_DEFAULT: dummy-stamp @@ -909,7 +909,7 @@ shellcheck-disclaimer: # Note: currently not part of shellcheck target, because the script below # can test the logic with numerous SHELL_PROGS in a CI setting, and because # check-scripts-syntax probably has checked the basic syntax above already. -nut-driver-enumerator.sh/scripts/upsdrvsvcctl: +nut-driver-enumerator.sh/scripts/upsdrvsvcctl: @dotMAKE@ +@$(SUBDIR_TGT_RULE) shellcheck-nde: nut-driver-enumerator.sh/scripts/upsdrvsvcctl @@ -951,7 +951,7 @@ cppcheck: @echo "CPPCHECK analysis not available since 'cppcheck' was not found." endif !HAVE_CPPCHECK -sockdebug: +sockdebug: @dotMAKE@ +cd $(builddir)/server && $(MAKE) $(AM_MAKEFLAGS) sockdebug$(EXEEXT) # ---------------------------------------------------------------------- @@ -975,7 +975,7 @@ GITLOG_END_POINT=@GITLOG_END_POINT@ # the current dir, and defaults to generate a "ChangeLog" in the current dir. # The script itself is generated from a template, so resides in builddir. dummy-stamp: -ChangeLog: dummy-stamp +ChangeLog: dummy-stamp @dotMAKE@ +@$(MAKE) $(AM_MAKEFLAGS) $(abs_top_builddir)/ChangeLog if WITH_PDF_NONASCII_TITLES @@ -1044,21 +1044,21 @@ $(abs_top_builddir)/ChangeLog: tools/gitlog2changelog.py dummy-stamp fi ; \ fi -ChangeLog.adoc: ChangeLog +ChangeLog.adoc: ChangeLog @dotMAKE@ +cd $(abs_top_builddir)/docs && $(MAKE) $(AM_MAKEFLAGS) ../ChangeLog.adoc -nut_version.h include/nut_version.h: +nut_version.h include/nut_version.h: @dotMAKE@ +cd $(abs_top_builddir)/include && $(MAKE) $(AM_MAKEFLAGS) nut_version.h # May involve (re-)build of libupsclient.la -libupsclient-version.h clients/libupsclient-version.h: +libupsclient-version.h clients/libupsclient-version.h: @dotMAKE@ +cd $(abs_top_builddir)/include && $(MAKE) $(AM_MAKEFLAGS) libupsclient-version.h -tools/gitlog2changelog.py: tools/gitlog2changelog.py.in +tools/gitlog2changelog.py: tools/gitlog2changelog.py.in @dotMAKE@ +cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) -s $(@F) # Partially snatched from automake generated code -distcheck-completeness: dist +distcheck-completeness: dist @dotMAKE@ @chmod -R +w $(distdir) $(distdir)-orig-* $(distdir)-derived-* || true @rm -rf $(distdir) $(distdir)-orig-* $(distdir)-derived-* || true @case '$(DIST_ARCHIVES)' in \ @@ -1187,12 +1187,12 @@ dist-docs: all-docs WARN="----------------------------------------------------------------------" -build: +build: @dotMAKE@ @echo $(WARN) @echo "Warning: 'make build' is deprecated. Use 'make all' instead." @echo $(WARN) +$(MAKE) $(AM_MAKEFLAGS) all -install-bin: +install-bin: @dotMAKE@ @echo $(WARN) @echo "Warning: 'make install-bin' is deprecated." @echo "Use 'make install-exec' instead for a similar effect." @@ -1201,20 +1201,20 @@ install-bin: +cd drivers; $(MAKE) $(AM_MAKEFLAGS) install +cd server; $(MAKE) $(AM_MAKEFLAGS) install +cd clients; $(MAKE) $(AM_MAKEFLAGS) install -install-man: install-data-recursive +install-man: install-data-recursive @dotMAKE@ @echo $(WARN) @echo "Warning: 'make install-man' is deprecated." @echo "Use 'cd docs/man; make install' instead." @echo $(WARN) +cd docs/man; $(MAKE) $(AM_MAKEFLAGS) install -install-conf: +install-conf: @dotMAKE@ @echo $(WARN) @echo "Warning: 'make install-conf' is deprecated." @echo "Use 'cd conf; make install' instead." @echo $(WARN) +cd conf; $(MAKE) $(AM_MAKEFLAGS) install # The target install-data already has a standardized meaning under automake -install-dirs: +install-dirs: @dotMAKE@ @echo $(WARN) @echo "Warning: 'make install-dirs' is deprecated." @echo "Use 'make installdirs' instead." @@ -1302,7 +1302,7 @@ endif !WITH_SOLARIS_INIT # using OS-specific `useradd`/`groupadd`, etc. # Note that as we stop services, we may be dealing with (older) # distros that do not follow current naming in NUT code base. -install-as-root: +install-as-root: @dotMAKE@ @+echo "$@: starting (no-op if not root)" >&2 ; \ case "$(target_os)" in *mingw*) echo "$@: SKIP: not supported for this target_os='$(target_os)'" >&2 ; exit 0;; esac ; \ if [ x"$(host_os)" != x"$(build_os)" ]; then echo "$@: SKIP: build_os='$(build_os)' is not host_os='$(host_os)'" >&2 ; exit 0 ; fi ; \ @@ -1475,7 +1475,7 @@ MAINTAINERCLEANFILES_PACKAGES += *.p5p MAINTAINERCLEANFILES += $(MAINTAINERCLEANFILES_DISTBALL) MAINTAINERCLEANFILES += $(MAINTAINERCLEANFILES_PACKAGES) -package: all +package: all @dotMAKE@ +DESTDIR="$(abs_builddir)/_install_pkgprotodir" ; export DESTDIR; \ rm -rf "$$DESTDIR"; \ case "`uname -s`" in \ @@ -1515,12 +1515,12 @@ if HAVE_WINDOWS # some NUT build without drivers/tools/daemons). Subject to change if needed. # Currently this is handled by a CHECKING... step that should fail if it hits # anything. -install-win-bundle: all +install-win-bundle: all @dotMAKE@ @if test -z "$(DESTDIR)" ; then echo "ERROR: '$@': Bundle may only be installed to some DESTDIR prototype area'" >&2 ; exit 1; fi +$(MAKE) $(AM_MAKEFLAGS) DESTDIR='$(DESTDIR)' install +$(MAKE) $(AM_MAKEFLAGS) DESTDIR='$(DESTDIR)' install-win-bundle-thirdparty -install-win-bundle-thirdparty: +install-win-bundle-thirdparty: @dotMAKE@ @if test -z "$(DESTDIR)" ; then echo "ERROR: '$@': Bundle may only be installed to some DESTDIR prototype area'" >&2 ; exit 1; fi @echo "Searching which DLLs need to be bundled with NUT for Windows..." >&2 @if test -z "$$ARCH" ; then \ @@ -1656,7 +1656,7 @@ CHECK_PARALLEL_BUILDS_REGEN = true # the `./config.status` line -- and fails there. Hence the `cd top_builddir`. # Auto-parallel recipe (if current 'make' implementation supports the "-j N" # syntax; the optional MAXPARMAKES may be set in NUT CI farm style builds): -check-parallel-builds: +check-parallel-builds: @dotMAKE@ if [ x"$(CHECK_PARALLEL_BUILDS_REGEN)" = xtrue ] ; then cd '$(top_srcdir)' && $(AUTOMAKE) -f ; fi if [ x"$(CHECK_PARALLEL_BUILDS_REGEN)" = xtrue ] ; then cd '$(top_builddir)' && ./config.status ; fi +@$(SET_PARMAKES_OPT); \ diff --git a/NEWS.adoc b/NEWS.adoc index 6d88f0fd75..71175c70b2 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -431,6 +431,14 @@ several `FSD` notifications into one executed action. [PR #3097] * Fixed CI recipes for PyPI publication of PyNUT(Client) module to also include the source distribution (was posted for NUT v2.8.1 and v2.8.2 tagged releases, but absent for v2.8.3 and v2.8.4). [#3056] + * A new version of BSD `make` in NetBSD 11 (Beta) aka `bmake` in some other + operating systems, complains about some of our sub-`$(MAKE)` calls despite + the explicit `+` prefix in corresponding lines, possibly because that call + happens not directly in a rule definition, but in a substituted shell code + snippet. The recommended workaround was to add a "Special Source" called + `.MAKE` to let the tool know that we expect sub-makes in that recipe. + However, *other* `make` implementations do not know about this token, + so its support is tried and detected at `configure` time. [PR #3300] * Updated `make spellcheck` to help avoid asciidoc admonition blocks with visually invalid sentences (after rendering as a box in HTML or PDF). [#3077] diff --git a/clients/Makefile.am b/clients/Makefile.am index 7d14c5e8ce..f2ca5a3d27 100644 --- a/clients/Makefile.am +++ b/clients/Makefile.am @@ -23,7 +23,7 @@ $(top_builddir)/common/libcommon.la \ $(top_builddir)/common/libcommonclient.la \ $(top_builddir)/common/libcommonversion.la \ $(top_builddir)/common/libcommonstrjson.la \ -$(top_builddir)/common/libparseconf.la: dummy +$(top_builddir)/common/libparseconf.la: dummy @dotMAKE@ +@cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F) # Builds from root dir arrange stuff decently. Make sure parallel builds @@ -39,7 +39,7 @@ LDADD_CLIENT = if ENABLE_SHARED_PRIVATE_LIBS $(top_builddir)/common/libcommonversion-private.la \ $(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-all.la \ -$(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-client.la: dummy +$(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-client.la: dummy @dotMAKE@ +@cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F) $(top_builddir)/common/libcommonversion-private.la: $(top_builddir)/include/nut_version.h diff --git a/common/Makefile.am b/common/Makefile.am index 153e852972..a39d452017 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -92,7 +92,7 @@ else !BUILDING_IN_TREE BUILT_SOURCES = common-nut_version.c endif !BUILDING_IN_TREE -$(top_builddir)/include/nut_version.h: +$(top_builddir)/include/nut_version.h: @dotMAKE@ +@if [ -s '$@' ] && ( [ x"$(NUT_VERSION_H_GENERATED)" = xtrue ] || [ x"$${NUT_VERSION_H_GENERATED}" = xtrue ] ) ; then \ if [ x"$(MAINTAINER_GENERATE_HEADER_DEBUG)" = xyes ] ; then \ echo "=== SKIP (common) $@ (NUT_VERSION_H_GENERATED makevar=$(NUT_VERSION_H_GENERATED) shellvar=$${NUT_VERSION_H_GENERATED})" >&2; \ diff --git a/conf/Makefile.am b/conf/Makefile.am index 235059cc66..0bd66744b7 100644 --- a/conf/Makefile.am +++ b/conf/Makefile.am @@ -37,20 +37,20 @@ SPELLCHECK_SRC = $(dist_sysconf_DATA) \ # We also have to export some variables that may be tainted by relative # paths when parsing the other makefile (e.g. MKDIR_P that may be defined # via expanded $(top_builddir)/install-sh): -#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) +#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) @dotMAKE@ # +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ # NOTE: Portable suffix rules do not allow prerequisites, so we shim them here # by a wildcard target in case the make implementation can put the two together. *-spellchecked: Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) -.sample.sample-spellchecked: +.sample.sample-spellchecked: @dotMAKE@ +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -.in.in-spellchecked: +.in.in-spellchecked: @dotMAKE@ +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -spellcheck spellcheck-interactive spellcheck-sortdict: +spellcheck spellcheck-interactive spellcheck-sortdict: @dotMAKE@ +$(MAKE) -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC="$(SPELLCHECK_SRC)" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ diff --git a/configure.ac b/configure.ac index 17a99d59b9..6eb4b54ce7 100644 --- a/configure.ac +++ b/configure.ac @@ -317,7 +317,7 @@ NUT_ARG_WITH_EXPAND_DEFAULT_HELP_SINGLEQUOTE([confdir-examples], [DIRPATH], [Com dnl --------------------------------------------------------------------- dnl GNU and BSD make are okay with the syntax, but Sun make/dmake are not: -AC_MSG_CHECKING([whether this make implementation supports export VAR=VAL syntax]) +AC_MSG_CHECKING([whether this make implementation supports 'export VAR=VAL' syntax]) dnl # using printf formatting for some funniner shells out there nut_am_output="`printf 'export VAR=VAL\ntest:\n\t@echo \"VAR=%s%sVAR%s\"\n' '\$' '(' ')' | ${MAKE-make} -f - test`" nut_am_result="$?" @@ -330,6 +330,24 @@ AS_IF([test x"${nut_am_result}" = x0 -a x"${nut_am_output}" = x"VAR=VAL"], [ ]) AC_SUBST(NUT_AM_MAKE_CAN_EXPORT) +dnl --------------------------------------------------------------------- +dnl Some versions of BSD make (e.g. in NetBSD 11) may require this syntax +dnl in lieu of the more standard "+" prefix, but at least GNU make exploded +dnl with it, so we can not use it everywhere: +AC_MSG_CHECKING([whether this make implementation supports a .MAKE special source (pseudo-goal for sub-makes)]) +dnl # using printf formatting for some funniner shells out there +nut_am_output="`printf 'sub: .MAKE\n\t@printf \\\"test:\\\\n\\\\t@echo %s\\\\n\\\" | $(MAKE) -f - test\n' '\\\\\\\"Hello world\\\\\\\"' | ${MAKE-make} -f - sub`" +nut_am_result="$?" +AS_IF([test x"${nut_am_result}" = x0 -a x"${nut_am_output}" = x"Hello world"], [ + dotMAKE=".MAKE" + AC_MSG_RESULT(yes) +], [ + dotMAKE="" + AC_MSG_RESULT(no: got '${nut_am_output}') +]) +AC_SUBST(dotMAKE) + +dnl --------------------------------------------------------------------- dnl Some systems have older autotools without direct macro support for PKG_CONF* NUT_CHECK_PKGCONFIG @@ -7210,4 +7228,7 @@ AS_IF([test x"${theMAKE}" = x], [theMAKE="make"]) AC_MSG_NOTICE([==========================================================]) AC_MSG_NOTICE([Configuration complete: Run '$theMAKE' to build ${NUT_SOURCE_VERSION_REPORT} now.]) AC_MSG_NOTICE([You may use parallelism if supported by your hardware and 'make' implementation, e.g. '$theMAKE -j 8']) +AS_IF([test x"${dotMAKE}" = x.MAKE], [ +AC_MSG_NOTICE([WARNING: do not use (parallel) GNU make with this build configuration!]) +]) AC_MSG_NOTICE([==========================================================]) diff --git a/data/Makefile.am b/data/Makefile.am index b4e82af77e..7f79e1c9a4 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -18,13 +18,13 @@ check-local: # We also have to export some variables that may be tainted by relative # paths when parsing the other makefile (e.g. MKDIR_P that may be defined # via expanded $(top_builddir)/install-sh): -#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) +#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) @dotMAKE@ # +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -cmdvartab-spellchecked: cmdvartab Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) +cmdvartab-spellchecked: cmdvartab Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) @dotMAKE@ +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -spellcheck spellcheck-interactive spellcheck-sortdict: +spellcheck spellcheck-interactive spellcheck-sortdict: @dotMAKE@ +$(MAKE) -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC="cmdvartab" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ MAINTAINERCLEANFILES = Makefile.in .dirstamp diff --git a/data/htmlcgi/Makefile.am b/data/htmlcgi/Makefile.am index 072b8f1c43..29649c404a 100644 --- a/data/htmlcgi/Makefile.am +++ b/data/htmlcgi/Makefile.am @@ -17,20 +17,20 @@ SPELLCHECK_SRC = README.adoc # We also have to export some variables that may be tainted by relative # paths when parsing the other makefile (e.g. MKDIR_P that may be defined # via expanded $(top_builddir)/install-sh): -#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) +#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) @dotMAKE@ # +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ # NOTE: Portable suffix rules do not allow prerequisites, so we shim them here # by a wildcard target in case the make implementation can put the two together. *-spellchecked: Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) -.sample.sample-spellchecked: +.sample.sample-spellchecked: @dotMAKE@ +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -.in.in-spellchecked: +.in.in-spellchecked: @dotMAKE@ +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -spellcheck spellcheck-interactive spellcheck-sortdict: +spellcheck spellcheck-interactive spellcheck-sortdict: @dotMAKE@ +$(MAKE) -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC="$(SPELLCHECK_SRC)" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ CLEANFILES = *-spellchecked diff --git a/docs/Makefile.am b/docs/Makefile.am index d3f103fcab..ee725f8c58 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -31,7 +31,7 @@ EXTRA_DIST = # generated once (can take a looong while), settled into place, and only then # we revisit them for html/pdf rendering (another long while) without randomly # confusing the system with new timestamps and needless regenerations later on. -all: +all: @dotMAKE@ @echo " DOC-FOLLOW-UP Basic 'make $@' in `pwd` is done, following up with 'make doc' to ensure complex document types" +@$(MAKE) $(AM_MAKEFLAGS) doc @@ -218,7 +218,7 @@ CHECK_LOCAL_TARGETS = @DOC_CHECK_LIST@ if WITH_SPELLCHECK CHECK_LOCAL_TARGETS += spellcheck endif WITH_SPELLCHECK -check-local: $(CHECK_LOCAL_TARGETS) +check-local: $(CHECK_LOCAL_TARGETS) @dotMAKE@ +@cd $(builddir)/man && $(MAKE) $(AM_MAKEFLAGS) check # Make sure sources are there for out-of-tree builds: @@ -226,7 +226,7 @@ all-local all-am-local \ $(DOC_BUILD_CHANGELOG_TEXT) $(DOC_BUILD_CHANGELOG_ADOC) \ @DOC_BUILD_LIST@ $(ASCIIDOC_PDF) $(ASCIIDOC_HTML_SINGLE) $(ASCIIDOC_HTML_CHUNKED): $(abs_top_builddir)/docs/.prep-src-docs -all-local: +all-local: @dotMAKE@ +@cd $(builddir)/man && $(MAKE) $(AM_MAKEFLAGS) all-optional # This list is defined by configure script choices and options: @@ -371,7 +371,7 @@ ChangeLog.html-contentchecked: exit 1 check-html-single: .check-html-single -.check-html-single: $(ASCIIDOC_HTML_SINGLE) Makefile +.check-html-single: $(ASCIIDOC_HTML_SINGLE) Makefile @dotMAKE@ +@FAILED=""; LANG=C; LC_ALL=C; export LANG; export LC_ALL; \ for F in $(ASCIIDOC_HTML_SINGLE) ; do \ test -s "$$F" && { file "$$F" | $(EGREP) -i '(XML|HTML.*document)' > /dev/null ; } || FAILED="$$FAILED $$F" ; \ @@ -408,11 +408,11 @@ check-html-chunked: .check-html-chunked # NOTE; we rig it up with a DOCS_NO_MAN option to simplify parallel work # from top-level Makefile, while allowing legacy "cd docs && make" to # still do the right thing by default :) -check-man check-man-man all-man man-man all-html html-man: +check-man check-man-man all-man man-man all-html html-man: @dotMAKE@ +@if [ x"$(DOCS_NO_MAN)" = xtrue ] ; then echo " DOC-NOT-MAN SKIP: $@ called in docs/Makefile" ; exit 0 ; fi ; \ cd $(abs_top_builddir)/docs/man/ && $(MAKE) $(AM_MAKEFLAGS) -f Makefile $@ -man: +man: @dotMAKE@ +@if [ x"$(DOCS_NO_MAN)" = xtrue ] ; then echo " DOC-NOT-MAN SKIP: $@ called in docs/Makefile" ; exit 0 ; fi ; \ cd $(abs_top_builddir)/docs/man/ && $(MAKE) $(AM_MAKEFLAGS) -f Makefile all @@ -434,7 +434,7 @@ MAINTAINER_ASCIIDOCS_CHANGELOG_DEBUG = no # Work around some documents that have originally included # the asciidoc markup (use double-hash to avoid conversion). # The $< is okay here, it is used in a suffix rule below -.adoc.adoc-parsed: +.adoc.adoc-parsed: @dotMAKE@ +@if [ ! -s '$<' ] ; then \ echo " DOC-ASCIIDOC-GITHUB-LINKS STRANGE: input $< does not exist or is empty" >&2 ; \ $(MAKE) $(AM_MAKEFLAGS) '$<' ; \ @@ -478,7 +478,7 @@ $(top_builddir)/ChangeLog.adoc-parsed: $(top_builddir)/ChangeLog.adoc CLEANFILES += .ChangeLog.adoc-parsed.latest dummy: -$(top_builddir)/ChangeLog: dummy +$(top_builddir)/ChangeLog: dummy @dotMAKE@ @+echo " DOC-CHANGELOG-GENERATE-WRAPPER $@ : call parent Makefile to decide if (re-)generation is needed" \ && cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) $(@F) @@ -581,7 +581,7 @@ solaris-usb.html solaris-usb.chunked solaris-usb.pdf: solaris-usb.txt asciidoc.c # to look at is cause to run a recipe always). We define recipes outside # the suffix-based handling and require *them* for default target builds. ChangeLog.html ChangeLog.chunked ChangeLog.pdf: ChangeLog.txt .ChangeLog.adoc-parsed.latest asciidoc.conf -$(top_builddir)/docs/ChangeLog.html $(top_builddir)/docs/ChangeLog.chunked $(top_builddir)/docs/ChangeLog.pdf: ChangeLog.txt $(top_builddir)/ChangeLog.adoc-parsed asciidoc.conf +$(top_builddir)/docs/ChangeLog.html $(top_builddir)/docs/ChangeLog.chunked $(top_builddir)/docs/ChangeLog.pdf: ChangeLog.txt $(top_builddir)/ChangeLog.adoc-parsed asciidoc.conf @dotMAKE@ @+if [ -s '$(@F)' ] && [ x"`find '$(@F)' -newer '$(top_builddir)/ChangeLog.adoc-parsed'`" != x ] ; then \ echo " DOC-CHANGELOG-RENDER-WRAPPER SKIP: `pwd`/$(@F) already exists and is newer than ChangeLog.adoc-parsed" ; \ if [ x"$(MAINTAINER_ASCIIDOCS_CHANGELOG_DEBUG)" != xno ] ; then \ @@ -766,9 +766,9 @@ GENERATE_HTML_SINGLE = ( \ ) *.html: common.xsl xhtml.xsl -.txt-prepped.html: +.txt-prepped.html: @dotMAKE@ +@$(GENERATE_HTML_SINGLE) -.adoc-prepped.html: +.adoc-prepped.html: @dotMAKE@ +@$(GENERATE_HTML_SINGLE) # Note: extra age check here because *.chunked is a directory and not all @@ -965,22 +965,22 @@ SPELLCHECK_AUTO_ONE = ( \ || { RES=$$? ; touch '$@'.failed; exit $$RES; } \ ) -.txt.txt-spellchecked-auto: +.txt.txt-spellchecked-auto: @dotMAKE@ +@$(SPELLCHECK_AUTO_ONE) -.adoc.adoc-spellchecked-auto: +.adoc.adoc-spellchecked-auto: @dotMAKE@ +@$(SPELLCHECK_AUTO_ONE) -.in.in-spellchecked-auto: +.in.in-spellchecked-auto: @dotMAKE@ +@$(SPELLCHECK_AUTO_ONE) -.sample.sample-spellchecked-auto: +.sample.sample-spellchecked-auto: @dotMAKE@ +@$(SPELLCHECK_AUTO_ONE) -.conf.conf-spellchecked-auto: +.conf.conf-spellchecked-auto: @dotMAKE@ +@$(SPELLCHECK_AUTO_ONE) -spellcheck: +spellcheck: @dotMAKE@ @if test "$(SPELLCHECK_ENV_DEBUG)" = detailed ; then \ echo "ASPELL DEBUG : information about the setup follows:"; \ LANG=$(ASPELL_ENV_LANG); LC_ALL=$(ASPELL_ENV_LANG); export LANG; export LC_ALL; \ @@ -1069,7 +1069,7 @@ DISTCLEANFILES += $(NUT_SPELL_DICT).bak-pre-sorting $(NUT_SPELL_DICT).bak-pre-in # that their dictionary was updated and may need a Git recommit - either # if it did change, or if caller's SPELLCHECK_REPORT_MAYBE_UPDATED_DICT=yes. SPELLCHECK_REPORT_MAYBE_UPDATED_DICT = no -spellcheck-interactive: +spellcheck-interactive: @dotMAKE@ @rm -f $(abs_builddir)/$(NUT_SPELL_DICT).bak-pre-interactive || true @cp -pf $(abs_srcdir)/$(NUT_SPELL_DICT) $(abs_builddir)/$(NUT_SPELL_DICT).bak-pre-interactive +@FAILED="" ; for docsrc in $(SPELLCHECK_SRC); do \ diff --git a/docs/man/Makefile.am b/docs/man/Makefile.am index 8ad5c11ac0..444710adfe 100644 --- a/docs/man/Makefile.am +++ b/docs/man/Makefile.am @@ -113,7 +113,7 @@ BUILT_SOURCES = $(abs_top_builddir)/docs/man/.prep-src-docs all-optional # been provided by automake, since we want to do nothing in certain cases. # Ideally it would refuse "make all" in certain cases, but we can't override # the automake-generated rules in each make implementation we care for. -all-optional: $(abs_top_builddir)/docs/man/.prep-src-docs +all-optional: $(abs_top_builddir)/docs/man/.prep-src-docs @dotMAKE@ +@case "$(ALL_TGT)" in \ ""|" "|" "|" ") echo " DOCS_NO_MAN SKIP: $@ called in docs/man/Makefile: No format of man page rendering is enabled" ; exit 0 ;; \ *all-*) \ @@ -2051,16 +2051,16 @@ endif !HAVE_ASCIIDOC # We also have to export some variables that may be tainted by relative # paths when parsing the other makefile (e.g. MKDIR_P that may be defined # via expanded $(top_builddir)/install-sh): -#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) +#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) @dotMAKE@ # +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE='$<' SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ # NOTE: Portable suffix rules do not allow prerequisites, so we shim them here # by a wildcard target in case the make implementation can put the two together. *.txt-spellchecked: Makefile.am $(abs_top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) -.txt.txt-spellchecked: +.txt.txt-spellchecked: @dotMAKE@ +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE='$<' SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -spellcheck spellcheck-interactive spellcheck-sortdict: +spellcheck spellcheck-interactive spellcheck-sortdict: @dotMAKE@ +$(MAKE) -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC="$(SRC_ALL_PAGES)" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ # When building out-of-tree, be sure to have all asciidoc resources diff --git a/drivers/Makefile.am b/drivers/Makefile.am index ac6cd671db..2e80c494c3 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -14,7 +14,7 @@ $(top_builddir)/include/nut_version.h \ $(top_builddir)/common/libcommon.la \ $(top_builddir)/common/libcommonversion.la \ $(top_builddir)/common/libparseconf.la \ -$(top_builddir)/clients/libupsclient.la: dummy +$(top_builddir)/clients/libupsclient.la: dummy @dotMAKE@ +@cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F) # Builds from root dir arrange stuff decently. Make sure parallel builds @@ -29,7 +29,7 @@ $(top_builddir)/common/libcommonversion.la: $(top_builddir)/include/nut_version. if ENABLE_SHARED_PRIVATE_LIBS $(top_builddir)/common/libcommonversion-private.la \ $(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-all.la \ -$(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-client.la: dummy +$(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-client.la: dummy @dotMAKE@ +@cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F) $(top_builddir)/common/libcommonversion-private.la: $(top_builddir)/include/nut_version.h diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 0c60ce9a77..d24c20adb7 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -38,20 +38,20 @@ SPELLCHECK_SRC = README.adoc RedHat/README.adoc usb_resetter/README.adoc valgrin # We also have to export some variables that may be tainted by relative # paths when parsing the other makefile (e.g. MKDIR_P that may be defined # via expanded $(top_builddir)/install-sh): -#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) +#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) @dotMAKE@ # +$(MAKE) $(AM_MAKEFLAGS) -s -f $(top_builddir)/docs/Makefile MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ # NOTE: Portable suffix rules do not allow prerequisites, so we shim them here # by a wildcard target in case the make implementation can put the two together. *-spellchecked: Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) -.sample.sample-spellchecked: +.sample.sample-spellchecked: @dotMAKE@ +$(MAKE) $(AM_MAKEFLAGS) -s -f $(top_builddir)/docs/Makefile MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -.in.in-spellchecked: +.in.in-spellchecked: @dotMAKE@ +$(MAKE) $(AM_MAKEFLAGS) -s -f $(top_builddir)/docs/Makefile MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -spellcheck spellcheck-interactive spellcheck-sortdict: +spellcheck spellcheck-interactive spellcheck-sortdict: @dotMAKE@ +$(MAKE) $(AM_MAKEFLAGS) -f $(top_builddir)/docs/Makefile MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC="$(SPELLCHECK_SRC)" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ CLEANFILES = *-spellchecked RedHat/*-spellchecked usb_resetter/*-spellchecked diff --git a/scripts/Solaris/Makefile.am b/scripts/Solaris/Makefile.am index e789c4b4ec..01c69ad864 100644 --- a/scripts/Solaris/Makefile.am +++ b/scripts/Solaris/Makefile.am @@ -119,20 +119,20 @@ SPELLCHECK_SRC = README.adoc # We also have to export some variables that may be tainted by relative # paths when parsing the other makefile (e.g. MKDIR_P that may be defined # via expanded $(top_builddir)/install-sh): -#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) +#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) @dotMAKE@ # +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ # NOTE: Portable suffix rules do not allow prerequisites, so we shim them here # by a wildcard target in case the make implementation can put the two together. *-spellchecked: Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) -.sample.sample-spellchecked: +.sample.sample-spellchecked: @dotMAKE@ +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -.in.in-spellchecked: +.in.in-spellchecked: @dotMAKE@ +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -spellcheck spellcheck-interactive spellcheck-sortdict: +spellcheck spellcheck-interactive spellcheck-sortdict: @dotMAKE@ +$(MAKE) -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC="$(SPELLCHECK_SRC)" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ CLEANFILES = *-spellchecked diff --git a/scripts/Windows/Makefile.am b/scripts/Windows/Makefile.am index 3eff7e6783..263a684876 100644 --- a/scripts/Windows/Makefile.am +++ b/scripts/Windows/Makefile.am @@ -4,7 +4,7 @@ AM_CFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include $(top_builddir)/include/nut_version.h \ $(top_builddir)/common/libcommonversion.la \ -$(top_builddir)/common/libcommon.la: FORCE +$(top_builddir)/common/libcommon.la: FORCE @dotMAKE@ +@cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F) $(top_builddir)/common/libcommonversion.la: $(top_builddir)/include/nut_version.h @@ -12,7 +12,7 @@ $(top_builddir)/common/libcommonversion.la: $(top_builddir)/include/nut_version. if ENABLE_SHARED_PRIVATE_LIBS $(top_builddir)/common/libcommonversion-private.la \ $(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-all.la \ -$(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-client.la: FORCE +$(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-client.la: FORCE @dotMAKE@ +@cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F) $(top_builddir)/common/libcommonversion-private.la: $(top_builddir)/include/nut_version.h @@ -105,20 +105,20 @@ SPELLCHECK_SRC = README.adoc DriverInstaller/README.adoc Installer/README.adoc # We also have to export some variables that may be tainted by relative # paths when parsing the other makefile (e.g. MKDIR_P that may be defined # via expanded $(top_builddir)/install-sh): -#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) +#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) @dotMAKE@ # +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ # NOTE: Portable suffix rules do not allow prerequisites, so we shim them here # by a wildcard target in case the make implementation can put the two together. *-spellchecked: Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) -.sample.sample-spellchecked: +.sample.sample-spellchecked: @dotMAKE@ +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -.in.in-spellchecked: +.in.in-spellchecked: @dotMAKE@ +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -spellcheck spellcheck-interactive spellcheck-sortdict: +spellcheck spellcheck-interactive spellcheck-sortdict: @dotMAKE@ +$(MAKE) -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC="$(SPELLCHECK_SRC)" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ MAINTAINERCLEANFILES = Makefile.in .dirstamp diff --git a/scripts/devd/Makefile.am b/scripts/devd/Makefile.am index b9d9401ad3..47c437c851 100644 --- a/scripts/devd/Makefile.am +++ b/scripts/devd/Makefile.am @@ -37,20 +37,20 @@ SPELLCHECK_SRC = README.adoc # We also have to export some variables that may be tainted by relative # paths when parsing the other makefile (e.g. MKDIR_P that may be defined # via expanded $(top_builddir)/install-sh): -#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) +#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) @dotMAKE@ # +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ # NOTE: Portable suffix rules do not allow prerequisites, so we shim them here # by a wildcard target in case the make implementation can put the two together. *-spellchecked: Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) -.sample.sample-spellchecked: +.sample.sample-spellchecked: @dotMAKE@ +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -.in.in-spellchecked: +.in.in-spellchecked: @dotMAKE@ +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -spellcheck spellcheck-interactive spellcheck-sortdict: +spellcheck spellcheck-interactive spellcheck-sortdict: @dotMAKE@ +$(MAKE) -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC="$(SPELLCHECK_SRC)" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ CLEANFILES = *-spellchecked diff --git a/scripts/external_apis/Makefile.am b/scripts/external_apis/Makefile.am index 1647190d28..c4b412a6de 100644 --- a/scripts/external_apis/Makefile.am +++ b/scripts/external_apis/Makefile.am @@ -30,20 +30,20 @@ endif ENABLE_EXTAPI_ENPHASE # We also have to export some variables that may be tainted by relative # paths when parsing the other makefile (e.g. MKDIR_P that may be defined # via expanded $(top_builddir)/install-sh): -#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) +#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) @dotMAKE@ # +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ # NOTE: Portable suffix rules do not allow prerequisites, so we shim them here # by a wildcard target in case the make implementation can put the two together. *-spellchecked: Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) -.sample.sample-spellchecked: +.sample.sample-spellchecked: @dotMAKE@ +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -.in.in-spellchecked: +.in.in-spellchecked: @dotMAKE@ +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -spellcheck spellcheck-interactive spellcheck-sortdict: +spellcheck spellcheck-interactive spellcheck-sortdict: @dotMAKE@ +$(MAKE) -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC="$(SPELLCHECK_SRC)" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ CLEANFILES = *-spellchecked enphase/*-spellchecked diff --git a/scripts/hotplug/Makefile.am b/scripts/hotplug/Makefile.am index 5fa7809f86..4a6490ec39 100644 --- a/scripts/hotplug/Makefile.am +++ b/scripts/hotplug/Makefile.am @@ -29,20 +29,20 @@ SPELLCHECK_SRC = README.adoc # We also have to export some variables that may be tainted by relative # paths when parsing the other makefile (e.g. MKDIR_P that may be defined # via expanded $(top_builddir)/install-sh): -#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) +#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) @dotMAKE@ # +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ # NOTE: Portable suffix rules do not allow prerequisites, so we shim them here # by a wildcard target in case the make implementation can put the two together. *-spellchecked: Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) -.sample.sample-spellchecked: +.sample.sample-spellchecked: @dotMAKE@ +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -.in.in-spellchecked: +.in.in-spellchecked: @dotMAKE@ +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -spellcheck spellcheck-interactive spellcheck-sortdict: +spellcheck spellcheck-interactive spellcheck-sortdict: @dotMAKE@ +$(MAKE) -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC="$(SPELLCHECK_SRC)" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ CLEANFILES = *-spellchecked diff --git a/scripts/installer/Makefile.am b/scripts/installer/Makefile.am index 134ba00ecd..2ce880e2d2 100644 --- a/scripts/installer/Makefile.am +++ b/scripts/installer/Makefile.am @@ -46,20 +46,20 @@ nut: # We also have to export some variables that may be tainted by relative # paths when parsing the other makefile (e.g. MKDIR_P that may be defined # via expanded $(top_builddir)/install-sh): -#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) +#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) @dotMAKE@ # +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ # NOTE: Portable suffix rules do not allow prerequisites, so we shim them here # by a wildcard target in case the make implementation can put the two together. *-spellchecked: Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) -.sample.sample-spellchecked: +.sample.sample-spellchecked: @dotMAKE@ +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -.in.in-spellchecked: +.in.in-spellchecked: @dotMAKE@ +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -spellcheck spellcheck-interactive spellcheck-sortdict: +spellcheck spellcheck-interactive spellcheck-sortdict: @dotMAKE@ +$(MAKE) -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC="$(SPELLCHECK_SRC)" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ CLEANFILES = *-spellchecked */*-spellchecked common_EN/license.txt diff --git a/scripts/obs/Makefile.am b/scripts/obs/Makefile.am index 208d723f4f..f4e86e6258 100644 --- a/scripts/obs/Makefile.am +++ b/scripts/obs/Makefile.am @@ -154,20 +154,20 @@ _preinstallimage: nut.spec nut.dsc Makefile # We also have to export some variables that may be tainted by relative # paths when parsing the other makefile (e.g. MKDIR_P that may be defined # via expanded $(top_builddir)/install-sh): -#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) +#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) @dotMAKE@ # +$(MAKE) $(AM_MAKEFLAGS) -s -f $(top_builddir)/docs/Makefile MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ # NOTE: Portable suffix rules do not allow prerequisites, so we shim them here # by a wildcard target in case the make implementation can put the two together. *-spellchecked: Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) -.sample.sample-spellchecked: +.sample.sample-spellchecked: @dotMAKE@ +$(MAKE) $(AM_MAKEFLAGS) -s -f $(top_builddir)/docs/Makefile MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -.in.in-spellchecked: +.in.in-spellchecked: @dotMAKE@ +$(MAKE) $(AM_MAKEFLAGS) -s -f $(top_builddir)/docs/Makefile MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -spellcheck spellcheck-interactive spellcheck-sortdict: +spellcheck spellcheck-interactive spellcheck-sortdict: @dotMAKE@ +$(MAKE) $(AM_MAKEFLAGS) -f $(top_builddir)/docs/Makefile MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC="$(SPELLCHECK_SRC)" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ CLEANFILES = *-spellchecked diff --git a/scripts/python/Makefile.am b/scripts/python/Makefile.am index e70abffd34..40a0d8e04d 100644 --- a/scripts/python/Makefile.am +++ b/scripts/python/Makefile.am @@ -281,20 +281,20 @@ SPELLCHECK_SRC = \ # We also have to export some variables that may be tainted by relative # paths when parsing the other makefile (e.g. MKDIR_P that may be defined # via expanded $(top_builddir)/install-sh): -#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) +#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) @dotMAKE@ # +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE='$<' SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ # NOTE: Portable suffix rules do not allow prerequisites, so we shim them here # by a wildcard target in case the make implementation can put the two together. *-spellchecked: Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) -.sample.sample-spellchecked: +.sample.sample-spellchecked: @dotMAKE@ +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE='$<' SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -.in.in-spellchecked: +.in.in-spellchecked: @dotMAKE@ +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE='$<' SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -spellcheck spellcheck-interactive spellcheck-sortdict: +spellcheck spellcheck-interactive spellcheck-sortdict: @dotMAKE@ +$(MAKE) -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC="$(SPELLCHECK_SRC)" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ CLEANFILES = *-spellchecked */*-spellchecked diff --git a/scripts/python/module/Makefile.am b/scripts/python/module/Makefile.am index 22bd7f7ba6..b01ab00672 100644 --- a/scripts/python/module/Makefile.am +++ b/scripts/python/module/Makefile.am @@ -60,7 +60,7 @@ MAINTAINERCLEANFILES = Makefile.in .dirstamp .pypi-tools* PyNUTClient: .pypi-src # Tagged releases should only have three blocks of digits separated by dots -upload publish: +upload publish: @dotMAKE@ +@echo " PYPI Checking upload type for module version '$(NUT_SOURCE_GITREV_NUMERIC)'" ; \ case x"`echo '$(NUT_SOURCE_GITREV_NUMERIC)' | tr -d '[0-9]'`" in \ x..) echo " PYPI ...release"; $(MAKE) $(AM_MAKEFLAGS) upload-pypi ;; \ @@ -122,7 +122,7 @@ upload publish: @touch '$@' # Using pypa/setuptools -.pypi-dist: .pypi-src +.pypi-dist: .pypi-src @dotMAKE@ +@$(MAKE) $(AM_MAKEFLAGS) .pypi-dist-pip-build || \ $(MAKE) $(AM_MAKEFLAGS) .pypi-dist-obsolete || \ $(MAKE) $(AM_MAKEFLAGS) .pypi-dist-pip-wheel diff --git a/scripts/systemd/Makefile.am b/scripts/systemd/Makefile.am index ee9ef9f3f7..f648e5ce58 100644 --- a/scripts/systemd/Makefile.am +++ b/scripts/systemd/Makefile.am @@ -62,20 +62,20 @@ SPELLCHECK_SRC = README.adoc # We also have to export some variables that may be tainted by relative # paths when parsing the other makefile (e.g. MKDIR_P that may be defined # via expanded $(top_builddir)/install-sh): -#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) +#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) @dotMAKE@ # +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ # NOTE: Portable suffix rules do not allow prerequisites, so we shim them here # by a wildcard target in case the make implementation can put the two together. *-spellchecked: Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) -.sample.sample-spellchecked: +.sample.sample-spellchecked: @dotMAKE@ +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -.in.in-spellchecked: +.in.in-spellchecked: @dotMAKE@ +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -spellcheck spellcheck-interactive spellcheck-sortdict: +spellcheck spellcheck-interactive spellcheck-sortdict: @dotMAKE@ +$(MAKE) -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC="$(SPELLCHECK_SRC)" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ CLEANFILES = *-spellchecked diff --git a/scripts/udev/Makefile.am b/scripts/udev/Makefile.am index a63107d980..a876e83f78 100644 --- a/scripts/udev/Makefile.am +++ b/scripts/udev/Makefile.am @@ -42,20 +42,20 @@ SPELLCHECK_SRC = README.adoc # We also have to export some variables that may be tainted by relative # paths when parsing the other makefile (e.g. MKDIR_P that may be defined # via expanded $(top_builddir)/install-sh): -#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) +#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) @dotMAKE@ # +$(MAKE) $(AM_MAKEFLAGS) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFILE) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ # NOTE: Portable suffix rules do not allow prerequisites, so we shim them here # by a wildcard target in case the make implementation can put the two together. *-spellchecked: Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) -.sample.sample-spellchecked: +.sample.sample-spellchecked: @dotMAKE@ +$(MAKE) $(AM_MAKEFLAGS) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFILE) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -.in.in-spellchecked: +.in.in-spellchecked: @dotMAKE@ +$(MAKE) $(AM_MAKEFLAGS) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFILE) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -spellcheck spellcheck-interactive spellcheck-sortdict: +spellcheck spellcheck-interactive spellcheck-sortdict: @dotMAKE@ +$(MAKE) $(AM_MAKEFLAGS) -f $(top_builddir)/docs/Makefile $(AM_MAKEFILE) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC="$(SPELLCHECK_SRC)" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ CLEANFILES += *-spellchecked diff --git a/scripts/upsdrvsvcctl/Makefile.am b/scripts/upsdrvsvcctl/Makefile.am index 03adf8e1c4..ca9c4cafb6 100644 --- a/scripts/upsdrvsvcctl/Makefile.am +++ b/scripts/upsdrvsvcctl/Makefile.am @@ -18,20 +18,20 @@ SPELLCHECK_SRC = README.adoc # We also have to export some variables that may be tainted by relative # paths when parsing the other makefile (e.g. MKDIR_P that may be defined # via expanded $(top_builddir)/install-sh): -#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) +#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) @dotMAKE@ # +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ # NOTE: Portable suffix rules do not allow prerequisites, so we shim them here # by a wildcard target in case the make implementation can put the two together. *-spellchecked: Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) -.sample.sample-spellchecked: +.sample.sample-spellchecked: @dotMAKE@ +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -.in.in-spellchecked: +.in.in-spellchecked: @dotMAKE@ +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -spellcheck spellcheck-interactive spellcheck-sortdict: +spellcheck spellcheck-interactive spellcheck-sortdict: @dotMAKE@ +$(MAKE) -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC="$(SPELLCHECK_SRC)" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ CLEANFILES = *-spellchecked diff --git a/server/Makefile.am b/server/Makefile.am index e7c7b7272b..2b8ff838e9 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -13,7 +13,7 @@ $(top_builddir)/include/nut_version.h \ $(top_builddir)/common/libcommon.la \ $(top_builddir)/common/libcommonversion.la \ -$(top_builddir)/common/libparseconf.la: dummy +$(top_builddir)/common/libparseconf.la: dummy @dotMAKE@ +@cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F) # Builds from root dir arrange stuff decently. Make sure parallel builds @@ -25,7 +25,7 @@ $(top_builddir)/common/libcommonversion.la: $(top_builddir)/include/nut_version. if ENABLE_SHARED_PRIVATE_LIBS $(top_builddir)/common/libcommonversion-private.la \ $(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-all.la \ -$(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-client.la: dummy +$(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-client.la: dummy @dotMAKE@ +@cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F) $(top_builddir)/common/libcommonversion-private.la: $(top_builddir)/include/nut_version.h diff --git a/tests/Makefile.am b/tests/Makefile.am index 11692209df..b4b5fe5240 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -31,7 +31,7 @@ check_PROGRAMS = $(TESTS) check_SCRIPTS = # NUT Integration Testing suite -check-NIT check-NIT-devel: +check-NIT check-NIT-devel: @dotMAKE@ +cd "$(builddir)/NIT" && $(MAKE) $(AM_MAKEFLAGS) $@ # Make sure out-of-dir dependencies exist (especially when dev-building @@ -45,7 +45,7 @@ $(top_builddir)/common/libcommonclient.la \ $(top_builddir)/common/libcommon.la \ $(top_builddir)/common/libparseconf.la \ $(top_builddir)/clients/libnutclient.la \ -$(top_builddir)/clients/libnutclientstub.la: dummy +$(top_builddir)/clients/libnutclientstub.la: dummy @dotMAKE@ +@cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F) # Builds from root dir arrange stuff decently. Make sure parallel builds @@ -59,7 +59,7 @@ if ENABLE_SHARED_PRIVATE_LIBS $(top_builddir)/common/libcommonversion-private.la \ $(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-all.la \ -$(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-client.la: dummy +$(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-client.la: dummy @dotMAKE@ +@cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F) $(top_builddir)/common/libcommonversion-private.la: $(top_builddir)/include/nut_version.h diff --git a/tests/NIT/Makefile.am b/tests/NIT/Makefile.am index 8332bac658..7bb3a0d548 100644 --- a/tests/NIT/Makefile.am +++ b/tests/NIT/Makefile.am @@ -29,7 +29,7 @@ check-NIT: $(abs_srcdir)/nit.sh "$(abs_srcdir)/nit.sh" # Make sure pre-requisites for NIT are fresh as we iterate -check-NIT-devel: $(abs_srcdir)/nit.sh +check-NIT-devel: $(abs_srcdir)/nit.sh @dotMAKE@ +@cd .. && ( $(MAKE) $(AM_MAKEFLAGS) -s cppnit$(EXEEXT) || echo "OPTIONAL C++ test client test will be skipped" ) +@cd "$(top_builddir)/clients" && $(MAKE) $(AM_MAKEFLAGS) -s upsc$(EXEEXT) upscmd$(EXEEXT) upsrw$(EXEEXT) upsmon$(EXEEXT) +@cd "$(top_builddir)/server" && $(MAKE) $(AM_MAKEFLAGS) -s upsd$(EXEEXT) sockdebug$(EXEEXT) @@ -51,7 +51,7 @@ check-NIT-sandbox: $(abs_srcdir)/nit.sh EXEEXT='$(EXEEXT)' \ "$(abs_srcdir)/nit.sh" -check-NIT-sandbox-devel: $(abs_srcdir)/nit.sh +check-NIT-sandbox-devel: $(abs_srcdir)/nit.sh @dotMAKE@ +[ -n "$${DEBUG_SLEEP-}" ] && [ "$${DEBUG_SLEEP-}" -gt 0 ] || DEBUG_SLEEP=600 ; export DEBUG_SLEEP ; \ GREP="$(GREP)"; EGREP="$(EGREP)"; export GREP; export EGREP; \ LANG=C LC_ALL=C TZ=UTC \ @@ -65,20 +65,20 @@ SPELLCHECK_SRC = README.adoc # We also have to export some variables that may be tainted by relative # paths when parsing the other makefile (e.g. MKDIR_P that may be defined # via expanded $(top_builddir)/install-sh): -#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) +#%-spellchecked: % Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) @dotMAKE@ # +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ # NOTE: Portable suffix rules do not allow prerequisites, so we shim them here # by a wildcard target in case the make implementation can put the two together. *-spellchecked: Makefile.am $(top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT) -.sample.sample-spellchecked: +.sample.sample-spellchecked: @dotMAKE@ +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -.in.in-spellchecked: +.in.in-spellchecked: @dotMAKE@ +$(MAKE) -s -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC_ONE="$<" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ -spellcheck spellcheck-interactive spellcheck-sortdict: +spellcheck spellcheck-interactive spellcheck-sortdict: @dotMAKE@ +$(MAKE) -f $(top_builddir)/docs/Makefile $(AM_MAKEFLAGS) MKDIR_P="$(MKDIR_P)" builddir="$(builddir)" srcdir="$(srcdir)" top_builddir="$(top_builddir)" top_srcdir="$(top_srcdir)" SPELLCHECK_SRC="$(SPELLCHECK_SRC)" SPELLCHECK_SRCDIR="$(srcdir)" SPELLCHECK_BUILDDIR="$(builddir)" $@ CLEANFILES = *-spellchecked diff --git a/tools/nut-scanner/Makefile.am b/tools/nut-scanner/Makefile.am index 385a9f30ef..c822d02c33 100644 --- a/tools/nut-scanner/Makefile.am +++ b/tools/nut-scanner/Makefile.am @@ -29,7 +29,7 @@ nutscan-usb.h: nutscan-snmp.h # Make sure we have the freshest files (no-op if built earlier and then # no driver sources and other dependencies were edited by a developer) -$(NUT_SCANNER_DEPS): dummy +$(NUT_SCANNER_DEPS): dummy @dotMAKE@ +@cd .. && $(MAKE) $(AM_MAKEFLAGS) nut-scanner-deps # Make sure out-of-dir dependencies exist (especially when dev-building parts): @@ -39,10 +39,10 @@ $(top_builddir)/common/libnutwincompat.la \ $(top_builddir)/drivers/libserial-nutscan.la \ $(top_builddir)/common/libcommonstr.la \ $(top_builddir)/common/libcommonversion.la \ -$(top_builddir)/common/libcommon.la: dummy +$(top_builddir)/common/libcommon.la: dummy @dotMAKE@ +@cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F) -$(top_builddir)/include/nut_version.h: +$(top_builddir)/include/nut_version.h: @dotMAKE@ +@if [ -s '$@' ] && ( [ x"$(NUT_VERSION_H_GENERATED)" = xtrue ] || [ x"$${NUT_VERSION_H_GENERATED}" = xtrue ] ) ; then \ if [ x"$(MAINTAINER_GENERATE_HEADER_DEBUG)" = xyes ] ; then \ echo "=== SKIP (nut-scanner) $@ (NUT_VERSION_H_GENERATED makevar=$(NUT_VERSION_H_GENERATED) shellvar=$${NUT_VERSION_H_GENERATED})" >&2; \ @@ -75,7 +75,7 @@ if ENABLE_SHARED_PRIVATE_LIBS $(top_builddir)/common/libcommonversion-private.la \ $(top_builddir)/common/libcommonclient.la \ $(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-all.la \ -$(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-client.la: dummy +$(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-client.la: dummy @dotMAKE@ +@cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F) $(top_builddir)/common/libcommonversion-private.la: $(top_builddir)/include/nut_version.h diff --git a/tools/nutconf/Makefile.am b/tools/nutconf/Makefile.am index a02f32b286..784ee16ae5 100644 --- a/tools/nutconf/Makefile.am +++ b/tools/nutconf/Makefile.am @@ -21,7 +21,7 @@ $(top_builddir)/common/libcommon.la \ $(top_builddir)/common/libcommonstr.la \ $(top_builddir)/common/libcommonversion.la \ $(top_builddir)/common/libnutconf.la \ -$(top_builddir)/tools/nut-scanner/libnutscan.la: dummy +$(top_builddir)/tools/nut-scanner/libnutscan.la: dummy @dotMAKE@ +@cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F) # Builds from root dir arrange stuff decently. Make sure parallel builds @@ -35,7 +35,7 @@ $(top_builddir)/clients/libupsclient.la: $(top_builddir)/common/libcommonclient. if ENABLE_SHARED_PRIVATE_LIBS $(top_builddir)/common/libcommonversion-private.la \ $(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-all.la \ -$(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-client.la: dummy +$(top_builddir)/common/libnutprivate-@NUT_SOURCE_GITREV_SEMVER_UNDERSCORES@-common-client.la: dummy @dotMAKE@ +@cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F) $(top_builddir)/common/libcommonversion-private.la: $(top_builddir)/include/nut_version.h From 5ca18a2127c0346e04037751b685c328cc013591 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 4 Feb 2026 17:45:54 +0000 Subject: [PATCH 129/198] GitIgnore "tags" files left over by (probably) bmake Signed-off-by: Jim Klimov --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2d32fbb90d..de8f6c43df 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ /_install_pkgprotodir/ Makefile Makefile.in +tags ## Parent directory only /aclocal.m4 From d8d5dfe4bc1f56ea7afe1a2e558dc95eefcbb0b9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 5 Feb 2026 11:36:29 +0100 Subject: [PATCH 130/198] drivers/vertiv-mib.c: refine code markup after another round of AI changes [#3299] Signed-off-by: Jim Klimov --- drivers/vertiv-mib.c | 216 +++++++++++++++++++++++++------------------ 1 file changed, 128 insertions(+), 88 deletions(-) diff --git a/drivers/vertiv-mib.c b/drivers/vertiv-mib.c index 58af7b2e8c..f83cc46faa 100644 --- a/drivers/vertiv-mib.c +++ b/drivers/vertiv-mib.c @@ -27,108 +27,148 @@ #include "vertiv-mib.h" -#define VERTIV_MIB_VERSION "0.04" +#define VERTIV_MIB_VERSION "0.01" /* Base OIDs from IS-UNITY-DP Card */ -#define VERTIV_BASEOID ".1.3.6.1.4.1.476.1.42" -#define VERTIV_ID_OID VERTIV_BASEOID ".2.4.2.1.4.1" -#define VERTIV_VAL_OID VERTIV_BASEOID ".3.9.30.1.20.1.2.1" -#define VERTIV_ALM_OID VERTIV_BASEOID ".3.9.20.1.10.1.2.100" -#define VERTIV_PWRSTATUS_OID VERTIV_BASEOID ".3.5.3" -#define VERTIV_BEEPER_OID VERTIV_VAL_OID ".6188" +#define VERTIV_BASEOID ".1.3.6.1.4.1.476.1.42" +#define VERTIV_ID_OID VERTIV_BASEOID ".2.4.2.1.4.1" +#define VERTIV_VAL_OID VERTIV_BASEOID ".3.9.30.1.20.1.2.1" +#define VERTIV_ALM_OID VERTIV_BASEOID ".3.9.20.1.10.1.2.100" +#define VERTIV_PWRSTATUS_OID VERTIV_BASEOID ".3.5.3" +#define VERTIV_BEEPER_OID VERTIV_VAL_OID ".6188" + +#ifdef VERTIV_WITH_IETF_BEEPER_FALLBACK +/* May be defined in experimental builds */ +static info_lkp_t ietf_beeper_status_info[] = { + info_lkp_default(1, "disabled"), + info_lkp_default(2, "enabled"), + info_lkp_default(3, "muted"), + info_lkp_sentinel +}; +#endif /* VERTIV_WITH_IETF_BEEPER_FALLBACK */ static info_lkp_t vertiv_beeper_status_info[] = { - info_lkp_default(1, "enabled"), - info_lkp_default(2, "disabled"), - info_lkp_sentinel + info_lkp_default(1, "enabled"), + info_lkp_default(2, "disabled"), + info_lkp_sentinel }; +/* FIXME: the below may introduce status redundancy, that needs to be + * addressed by the driver, as for usbhid-ups! */ +/* + * DESCRIPTION + * The present source of output power. The enumeration + * none(2) indicates that there is no source of output + * power (and therefore no output power), for example, + * the system has opened the output breaker. + * + * NOTE: In a single-module system, this point + * is intended to have the same behavior as + * the RFC1628 point upsOutputSource." + */ static info_lkp_t vertiv_power_source_info[] = { - info_lkp_default(1, "other"), - info_lkp_default(2, "OFF"), - info_lkp_default(3, "OL"), - info_lkp_default(4, "BYPASS"), - info_lkp_default(5, "OB"), - info_lkp_default(6, "BOOST"), - info_lkp_default(7, "TRIM"), - info_lkp_sentinel + info_lkp_default(1, ""), /* other */ + info_lkp_default(2, "OFF"), /* none */ + info_lkp_default(3, "OL"), /* normal */ + info_lkp_default(4, "BYPASS"), /* bypass */ + info_lkp_default(5, "OB"), /* battery */ + info_lkp_default(6, "BOOST"), /* booster */ + info_lkp_default(7, "TRIM"), /* reducer */ + info_lkp_sentinel }; static snmp_info_t vertiv_mib[] = { - /* Standard MIB items */ - snmp_info_default("device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK | SU_FLAG_SEMI_STATIC, NULL), - snmp_info_default("device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK | SU_FLAG_SEMI_STATIC, NULL), - snmp_info_default("device.location", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_OK | SU_FLAG_SEMI_STATIC, NULL), - - /* Device Identification */ - snmp_info_default("device.mfr", ST_FLAG_STRING, 1.0, VERTIV_BASEOID ".2.1.1.0", NULL, SU_FLAG_OK | SU_FLAG_STATIC, NULL), - snmp_info_default("device.model", ST_FLAG_STRING, 1.0, VERTIV_BASEOID ".2.4.2.1.4.1", NULL, SU_FLAG_OK | SU_FLAG_STATIC, NULL), - snmp_info_default("device.serial", ST_FLAG_STRING, 1.0, VERTIV_BASEOID ".2.4.2.1.7.1", NULL, SU_FLAG_OK | SU_FLAG_STATIC, NULL), - snmp_info_default("ups.firmware", ST_FLAG_STRING, 1.0, VERTIV_BASEOID ".2.4.2.1.5.1", NULL, SU_FLAG_OK | SU_FLAG_STATIC, NULL), - - /* Extended Identification */ - snmp_info_default("device.type", ST_FLAG_STRING, 1.0, VERTIV_BASEOID ".3.9.20.1.20.1.2.1.4553", NULL, SU_FLAG_OK | SU_FLAG_STATIC, NULL), - snmp_info_default("ups.mfr", ST_FLAG_STRING, 1.0, VERTIV_BASEOID ".3.9.20.1.20.1.2.1.4333", NULL, SU_FLAG_OK | SU_FLAG_STATIC, NULL), - snmp_info_default("ups.model", ST_FLAG_STRING, 1.0, VERTIV_BASEOID ".3.9.20.1.20.1.2.1.4240", NULL, SU_FLAG_OK | SU_FLAG_STATIC, NULL), - - /* UPS Measurements & Topology (High-precision) */ - snmp_info_default("ups.load", 0, 1.0, VERTIV_VAL_OID ".5861", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), - snmp_info_default("ups.temperature", 0, 1.0, VERTIV_BASEOID ".3.9.30.1.10.1.2.1.4291", NULL, SU_FLAG_NEGINVALID, NULL), - snmp_info_default("ups.type", ST_FLAG_STRING, 1.0, VERTIV_BASEOID ".3.9.20.1.20.1.2.1.6199", NULL, SU_FLAG_OK | SU_FLAG_STATIC, NULL), - - /* Battery Data */ - snmp_info_default("battery.charge", 0, 1.0, VERTIV_VAL_OID ".4153", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), - snmp_info_default("battery.runtime", 0, 60.0, VERTIV_VAL_OID ".4150", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), - snmp_info_default("battery.voltage", 0, 1.0, VERTIV_VAL_OID ".4148", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), - snmp_info_default("battery.voltage.nominal", 0, 1.0, VERTIV_VAL_OID ".6189", "", SU_FLAG_OK | SU_FLAG_STATIC, NULL), - - /* Power Quality - Scaled (0.1) for high precision decimal values */ - snmp_info_default("input.voltage", 0, 0.1, VERTIV_VAL_OID ".4096", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), - snmp_info_default("input.current", 0, 0.1, VERTIV_VAL_OID ".4113", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), - snmp_info_default("input.frequency", 0, 0.1, VERTIV_VAL_OID ".4105", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), - snmp_info_default("input.voltage.nominal", 0, 1.0, VERTIV_VAL_OID ".4102", "", SU_FLAG_OK | SU_FLAG_STATIC, NULL), - snmp_info_default("input.current.nominal", 0, 1.0, VERTIV_VAL_OID ".4104", "", SU_FLAG_OK | SU_FLAG_STATIC, NULL), - snmp_info_default("input.frequency.nominal", 0, 1.0, VERTIV_VAL_OID ".4103", "", SU_FLAG_OK | SU_FLAG_STATIC, NULL), - snmp_info_default("output.voltage", 0, 0.1, VERTIV_VAL_OID ".4385", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), - snmp_info_default("output.current", 0, 0.1, VERTIV_VAL_OID ".4204", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), - snmp_info_default("output.frequency", 0, 0.1, VERTIV_VAL_OID ".4207", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), - snmp_info_default("output.power", 0, 1.0, VERTIV_VAL_OID ".4208", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), - snmp_info_default("output.power.apparent", 0, 1.0, VERTIV_VAL_OID ".4209", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), - snmp_info_default("output.voltage.nominal", 0, 1.0, VERTIV_VAL_OID ".4260", "", SU_FLAG_OK | SU_FLAG_STATIC, NULL), - snmp_info_default("output.power.nominal", 0, 1.0, VERTIV_VAL_OID ".4264", "", SU_FLAG_OK | SU_FLAG_STATIC, NULL), - - /* UPS Status & Beeper */ - snmp_info_default("ups.status", ST_FLAG_STRING, SU_INFOSIZE, VERTIV_VAL_OID ".4872", "", SU_STATUS_PWR | SU_FLAG_OK, vertiv_power_source_info), - snmp_info_default("ups.beeper.status", ST_FLAG_STRING, SU_INFOSIZE, VERTIV_BEEPER_OID, "", SU_FLAG_OK, vertiv_beeper_status_info), - - /* Instant Commands */ - snmp_info_default("beeper.disable", 0, 1, VERTIV_BEEPER_OID, "2", SU_TYPE_CMD, NULL), - snmp_info_default("beeper.enable", 0, 1, VERTIV_BEEPER_OID, "1", SU_TYPE_CMD, NULL), - - /* Shutdown & Restart */ - snmp_info_default("ups.delay.shutdown", ST_FLAG_RW, 1.0, VERTIV_VAL_OID ".5814", "", SU_TYPE_TIME | SU_FLAG_OK, NULL), - snmp_info_default("ups.delay.start", ST_FLAG_RW, 1.0, VERTIV_VAL_OID ".5816", "", SU_TYPE_TIME | SU_FLAG_OK, NULL), - - snmp_info_sentinel + /* Standard IETF MIB items */ + snmp_info_default("device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK | SU_FLAG_SEMI_STATIC, NULL), + snmp_info_default("device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK | SU_FLAG_SEMI_STATIC, NULL), + snmp_info_default("device.location", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_OK | SU_FLAG_SEMI_STATIC, NULL), + + /* Device Identification from vendor MIB */ + snmp_info_default("device.mfr", ST_FLAG_STRING, 1.0, VERTIV_BASEOID ".2.1.1.0", NULL, SU_FLAG_OK | SU_FLAG_STATIC, NULL), + snmp_info_default("device.model", ST_FLAG_STRING, 1.0, VERTIV_BASEOID ".2.4.2.1.4.1", NULL, SU_FLAG_OK | SU_FLAG_STATIC, NULL), + snmp_info_default("device.serial", ST_FLAG_STRING, 1.0, VERTIV_BASEOID ".2.4.2.1.7.1", NULL, SU_FLAG_OK | SU_FLAG_STATIC, NULL), + snmp_info_default("ups.firmware", ST_FLAG_STRING, 1.0, VERTIV_BASEOID ".2.4.2.1.5.1", NULL, SU_FLAG_OK | SU_FLAG_STATIC, NULL), + + /* Extended Identification */ + snmp_info_default("device.type", ST_FLAG_STRING, 1.0, VERTIV_BASEOID ".3.9.20.1.20.1.2.1.4553", NULL, SU_FLAG_OK | SU_FLAG_STATIC, NULL), + snmp_info_default("ups.mfr", ST_FLAG_STRING, 1.0, VERTIV_BASEOID ".3.9.20.1.20.1.2.1.4333", NULL, SU_FLAG_OK | SU_FLAG_STATIC, NULL), + snmp_info_default("ups.model", ST_FLAG_STRING, 1.0, VERTIV_BASEOID ".3.9.20.1.20.1.2.1.4240", NULL, SU_FLAG_OK | SU_FLAG_STATIC, NULL), + + /* UPS Measurements & Topology (High-precision) */ + snmp_info_default("ups.load", 0, 1.0, VERTIV_VAL_OID ".5861", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), + snmp_info_default("ups.temperature", 0, 1.0, VERTIV_BASEOID ".3.9.30.1.10.1.2.1.4291", NULL, SU_FLAG_NEGINVALID, NULL), + snmp_info_default("ups.type", ST_FLAG_STRING, 1.0, VERTIV_BASEOID ".3.9.20.1.20.1.2.1.6199", NULL, SU_FLAG_OK | SU_FLAG_STATIC, NULL), + + /* Battery Data */ + snmp_info_default("battery.charge", 0, 1.0, VERTIV_VAL_OID ".4153", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), + /* Multiplier 60.0 converts UPS minutes to NUT seconds */ + snmp_info_default("battery.runtime", 0, 60.0, VERTIV_VAL_OID ".4150", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), + snmp_info_default("battery.voltage", 0, 1.0, VERTIV_VAL_OID ".4148", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), + snmp_info_default("battery.voltage.nominal", 0, 1.0, VERTIV_VAL_OID ".6189", "", SU_FLAG_OK | SU_FLAG_STATIC, NULL), + + /* Power Quality - Scaled (0.1) for high precision decimal values (tenths of Volts/Amps/Hz) */ + snmp_info_default("input.voltage", 0, 0.1, VERTIV_VAL_OID ".4096", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), + snmp_info_default("input.current", 0, 0.1, VERTIV_VAL_OID ".4113", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), + snmp_info_default("input.frequency", 0, 0.1, VERTIV_VAL_OID ".4105", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), + snmp_info_default("input.voltage.nominal", 0, 1.0, VERTIV_VAL_OID ".4102", "", SU_FLAG_OK | SU_FLAG_STATIC, NULL), + snmp_info_default("input.current.nominal", 0, 1.0, VERTIV_VAL_OID ".4104", "", SU_FLAG_OK | SU_FLAG_STATIC, NULL), + snmp_info_default("input.frequency.nominal", 0, 1.0, VERTIV_VAL_OID ".4103", "", SU_FLAG_OK | SU_FLAG_STATIC, NULL), + snmp_info_default("output.voltage", 0, 0.1, VERTIV_VAL_OID ".4385", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), + snmp_info_default("output.current", 0, 0.1, VERTIV_VAL_OID ".4204", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), + snmp_info_default("output.frequency", 0, 0.1, VERTIV_VAL_OID ".4207", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), + snmp_info_default("output.power", 0, 1.0, VERTIV_VAL_OID ".4208", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), + snmp_info_default("output.power.apparent", 0, 1.0, VERTIV_VAL_OID ".4209", "", SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL), + snmp_info_default("output.voltage.nominal", 0, 1.0, VERTIV_VAL_OID ".4260", "", SU_FLAG_OK | SU_FLAG_STATIC, NULL), + snmp_info_default("output.power.nominal", 0, 1.0, VERTIV_VAL_OID ".4264", "", SU_FLAG_OK | SU_FLAG_STATIC, NULL), + + /* UPS Status */ + snmp_info_default("ups.status", ST_FLAG_STRING, SU_INFOSIZE, VERTIV_VAL_OID ".4872", "", SU_STATUS_PWR | SU_FLAG_OK, vertiv_power_source_info), + + /* Beeper status and commands */ + snmp_info_default("ups.beeper.status", ST_FLAG_STRING, SU_INFOSIZE, VERTIV_BEEPER_OID, "", SU_FLAG_UNIQUE, vertiv_beeper_status_info), + + snmp_info_default("beeper.disable", 0, 1, VERTIV_BEEPER_OID, "2", SU_TYPE_CMD, NULL), + snmp_info_default("beeper.enable", 0, 1, VERTIV_BEEPER_OID, "1", SU_TYPE_CMD, NULL), + +#ifdef VERTIV_WITH_IETF_BEEPER_FALLBACK + /* IETF MIB fallback */ + snmp_info_default("ups.beeper.status", ST_FLAG_STRING, SU_INFOSIZE, "1.3.6.1.2.1.33.1.9.8.0", "", SU_FLAG_UNIQUE, ietf_beeper_status_info), +#if 0 + snmp_info_default("beeper.disable", 0, 1, "1.3.6.1.2.1.33.1.9.8.0", "1", SU_TYPE_CMD, NULL), + snmp_info_default("beeper.enable", 0, 1, "1.3.6.1.2.1.33.1.9.8.0", "2", SU_TYPE_CMD, NULL), +#endif + snmp_info_default("beeper.mute", 0, 1, "1.3.6.1.2.1.33.1.9.8.0", "3", SU_TYPE_CMD, NULL), +#endif /* VERTIV_WITH_IETF_BEEPER_FALLBACK */ + + /* Shutdown / Restart Control + * NOTE: Other sources suggest + * "ups.delay.shutdown" => VERTIV_BASEOID ".3.3.5.1.0" + * "ups.delay.start" => VERTIV_BASEOID ".3.3.5.2.0" + */ + snmp_info_default("ups.delay.shutdown", ST_FLAG_RW, 1.0, VERTIV_VAL_OID ".5814", "", SU_TYPE_TIME | SU_FLAG_OK, NULL), + snmp_info_default("ups.delay.start", ST_FLAG_RW, 1.0, VERTIV_VAL_OID ".5816", "", SU_TYPE_TIME | SU_FLAG_OK, NULL), + + /* end of structure. */ + snmp_info_sentinel }; static alarms_info_t vertiv_alarms[] = { - { VERTIV_ALM_OID ".4168", "OB", "Battery Discharging" }, - { VERTIV_ALM_OID ".4162", "LB", "Battery Low" }, - { VERTIV_ALM_OID ".5806", "OVER", "Output Overload" }, - { VERTIV_ALM_OID ".6182", "RB", "Replace Battery" }, - { VERTIV_ALM_OID ".4233", "FAULT", "Inverter Failure" }, - { VERTIV_ALM_OID ".4310", "OT", "Over Temperature" }, - { VERTIV_ALM_OID ".4215", "OFF", "UPS Output Off" }, - { NULL, NULL, NULL } + { VERTIV_ALM_OID ".4168", "OB", "Battery Discharging" }, + { VERTIV_ALM_OID ".4162", "LB", "Battery Low" }, + { VERTIV_ALM_OID ".5806", "OVER", "Output Overload" }, + { VERTIV_ALM_OID ".6182", "RB", "Replace Battery" }, + { VERTIV_ALM_OID ".4233", "FAULT", "Inverter Failure" }, + { VERTIV_ALM_OID ".4310", "OT", "Over Temperature" }, + { VERTIV_ALM_OID ".4215", "OFF", "UPS Output Off" }, + { NULL, NULL, NULL } }; mib2nut_info_t vertiv = { - "vertiv", - VERTIV_MIB_VERSION, - VERTIV_PWRSTATUS_OID, - VERTIV_ID_OID, - vertiv_mib, - VERTIV_BASEOID, - vertiv_alarms + "vertiv", + VERTIV_MIB_VERSION, + VERTIV_PWRSTATUS_OID,/* Optional Power Status OID */ + VERTIV_ID_OID, /* Model Name OID */ + vertiv_mib, + VERTIV_BASEOID, /* SysOID fingerprint */ + vertiv_alarms }; From 704d7b8faa81ca8b3ace9a8a0b587d796b5d9bd0 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 5 Feb 2026 17:37:59 +0100 Subject: [PATCH 131/198] configure.ac: rectify handling of nut_with_confdir [#3131] Signed-off-by: Jim Klimov --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 6eb4b54ce7..c642b85f14 100644 --- a/configure.ac +++ b/configure.ac @@ -411,8 +411,8 @@ test "${prefix}" = "NONE" && prefix="${ac_default_prefix}" test "${exec_prefix}" = "NONE" && exec_prefix='${prefix}' AS_CASE([x"${nut_with_confdir}"], - [yes], [AC_MSG_ERROR([--with-confdir should specify a path name or expansible expression])], - [/*|?:\*|?:/*|*/*|*'\'*], [ + [xyes], [AC_MSG_ERROR([--with-confdir should specify a path name or expansible expression])], + [x/*|x?":\\"*|x?:/*|x*/*|x*'\'*], [ AC_MSG_NOTICE([A non-trivial --with-confdir path was specified (${nut_with_confdir}); any --with-confdir-suffix (${nut_with_confdir_suffix}) or --sysconfdir (${sysconfdir}) values are disregarded]) ], [ RESULT_COMMENT="" From 2f860fe2310a4c22b0334ed105562366716bd04f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 5 Feb 2026 18:04:28 +0100 Subject: [PATCH 132/198] scripts/Windows/Installer/NUT-Installer.xml.in: ensure a newline at end of file (some SEDs complain) Signed-off-by: Jim Klimov --- scripts/Windows/Installer/NUT-Installer.xml.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/Windows/Installer/NUT-Installer.xml.in b/scripts/Windows/Installer/NUT-Installer.xml.in index 7348d6ac31..04beb98298 100644 --- a/scripts/Windows/Installer/NUT-Installer.xml.in +++ b/scripts/Windows/Installer/NUT-Installer.xml.in @@ -2075,4 +2075,5 @@ Public License instead of this License. LIBUSBINSTALL=1 - \ No newline at end of file + + From b09e4d91c017c55323f2d3de054d312f444826bc Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 5 Feb 2026 17:56:48 +0100 Subject: [PATCH 133/198] configure.ac, tools/nut-scanner/nut-scan.h, tools/nut-scanner/Makefile.am, docs/configure.txt, NEWS.adoc, UPGRADING.adoc: Added an option to (primarily) `--disable-threading` [#3300] Can be useful for systems with broken libraries, as well as for CI testing of sequential implementation on build systems WITH threading support available (and until now unavoidable then). This commit also fixes problems found when trying such a build. Signed-off-by: Jim Klimov --- NEWS.adoc | 3 +++ UPGRADING.adoc | 4 ++++ configure.ac | 19 +++++++++++++++++++ docs/configure.txt | 10 ++++++++++ tools/nut-scanner/Makefile.am | 2 ++ tools/nut-scanner/nut-scan.h | 19 ++++++++++++++++++- tools/nut-scanner/nut-scanner.c | 6 ++---- tools/nut-scanner/scan_eaton_serial.c | 3 ++- 8 files changed, 60 insertions(+), 6 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index 71175c70b2..e6c5dd3790 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -426,6 +426,9 @@ several `FSD` notifications into one executed action. [PR #3097] * Fixed `m4/ax_realpath_lib.m4` up with more ways to try and gauge the build-time library name from linker/compiler, to improve the chances that `nut-scanner` would find them. [#3293] + * Added an option to (primarily) `--disable-threading` for systems with + detected but broken `libpthread` support, or to test alternate code + paths during development or in CI. [#3300] - Recipes, CI and helper script updates not classified above: * Fixed CI recipes for PyPI publication of PyNUT(Client) module to also diff --git a/UPGRADING.adoc b/UPGRADING.adoc index 1c11f27ca8..534bdf8e04 100644 --- a/UPGRADING.adoc +++ b/UPGRADING.adoc @@ -125,6 +125,10 @@ Changes from 2.8.4 to 2.8.5 updated, either to explicitly package the binding for several versions, or to not-deliver files no longer installed into the prototype area. [#1792] +- Added a `configure` script option to (primarily) `--disable-threading` + for systems with detected but broken `libpthread` support, which can + cause `nut-scanner` to crash while loading system libraries. [#3300] + - Introduced a new driver category for interaction with OS-reported UPS devices via D-Bus, with the `nut-upower` driver as the first implementation. This driver requires `glib-2.0` and `gio-2.0` development libraries to be diff --git a/configure.ac b/configure.ac index c642b85f14..6d9d899446 100644 --- a/configure.ac +++ b/configure.ac @@ -1391,6 +1391,25 @@ if (semaphore != SEM_FAILED) ) AM_CONDITIONAL(HAVE_SEMAPHORE_LIBS, test -n "${SEMLIBS}") +dnl ---------------------------------------------------------------------- +dnl Check for --with-threading request + +NUT_ARG_WITH([threading], + [If it is possible to parallelize some tools (e.g. nut-scanner), do so?], + [auto]) + +AC_MSG_CHECKING([Whether to enable support for parallelization of some tools]) +AS_CASE(["${nut_with_threading}"], + [""|yes], [AM_COND_IF([HAVE_SEMAPHORE_LIBS], [], [AC_MSG_ERROR([pthread support was required but libraries not detected])])], + [auto],[AM_COND_IF([HAVE_SEMAPHORE_LIBS], [nut_with_threading=yes], [nut_with_threading=no])], + [no], [], + [AC_MSG_ERROR([Unsupported value for --with-threading option: "${nut_with_threading}"])] +) +AC_MSG_RESULT([${nut_with_threading}]) +NUT_REPORT_FEATURE([Enable support for parallelization of some tools], [${nut_with_threading}], [${SEMLIBS}], + [WITH_THREADING], [Define to enable build with threading support]) + +dnl ---------------------------------------------------------------------- AC_CHECK_FUNCS(cfsetispeed tcsendbreak) AC_CHECK_FUNCS(seteuid setsid getpassphrase) AC_CHECK_FUNCS(on_exit setlogmask) diff --git a/docs/configure.txt b/docs/configure.txt index 595763fb5c..0b70cf5cfc 100644 --- a/docs/configure.txt +++ b/docs/configure.txt @@ -331,6 +331,16 @@ Many of the features depend on third-party libraries that are loosely linked at run-time using libltdl, and due to that, the build, delivery and use of the tool does not depend on *all* of them being available in the final deployment. + --with-threading (default: auto) + +Currently limited to linkman:nut-scanner[8] tool: require/allow build with +pthreads and/or semaphore support to parallelize the network and local port +scans, and scans of different media types. + +Some older systems' implementation of threading may be broken, so while we +can detect support, builds using it can fail in practice -- so this toggle +allows to keep building sequential-only code. + NUT Configuration tool ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tools/nut-scanner/Makefile.am b/tools/nut-scanner/Makefile.am index c822d02c33..f4295ffff6 100644 --- a/tools/nut-scanner/Makefile.am +++ b/tools/nut-scanner/Makefile.am @@ -110,10 +110,12 @@ if WITH_LIBLTDL libnutscan_la_LIBADD += $(LIBLTDL_LIBS) endif WITH_LIBLTDL +if WITH_THREADING if HAVE_SEMAPHORE_LIBS # Are additional libraries needed for semaphore support? libnutscan_la_LIBADD += $(SEMLIBS) endif HAVE_SEMAPHORE_LIBS +endif WITH_THREADING libnutscan_la_LIBADD += $(SERLIBS) diff --git a/tools/nut-scanner/nut-scan.h b/tools/nut-scanner/nut-scan.h index bf1925d919..1619325e99 100644 --- a/tools/nut-scanner/nut-scan.h +++ b/tools/nut-scanner/nut-scan.h @@ -4,7 +4,7 @@ * 2012 - 2024 Arnaud Quette * 2016 - EATON - IP addressed XML scan * 2016 - 2021 - EATON - Various threads-related improvements - * 2023 - 2024 - Jim Klimov + * 2023 - 2026 - 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 @@ -67,6 +67,23 @@ # include #endif +#ifndef WITH_THREADING +# define WITH_THREADING 0 +#endif + +#if !WITH_THREADING +/* Not detected or actively disabled in configure script */ +# ifdef HAVE_PTHREAD +# undef HAVE_PTHREAD +# endif +# ifdef HAVE_SEMAPHORE_UNNAMED +# undef HAVE_SEMAPHORE_UNNAMED +# endif +# ifdef HAVE_SEMAPHORE_NAMED +# undef HAVE_SEMAPHORE_NAMED +# endif +#endif + #ifdef HAVE_PTHREAD # include diff --git a/tools/nut-scanner/nut-scanner.c b/tools/nut-scanner/nut-scanner.c index e8b485cf6a..322afe239a 100644 --- a/tools/nut-scanner/nut-scanner.c +++ b/tools/nut-scanner/nut-scanner.c @@ -149,6 +149,7 @@ static nutscan_ip_range_list_t ip_ranges_list; #ifdef HAVE_PTHREAD static pthread_t thread[TYPE_END]; +#endif /* HAVE_PTHREAD */ static void * run_usb(void *arg) { @@ -203,7 +204,6 @@ static void * run_usb(void *arg) dev[TYPE_USB] = nutscan_scan_usb(scanopts_ptr); return NULL; } -#endif /* HAVE_PTHREAD */ static void * run_snmp(void * arg) { @@ -1732,8 +1732,7 @@ int main(int argc, char *argv[]) } #else upsdebugx(1, "USB SCAN: no pthread support, starting nutscan_scan_usb..."); - /* Not calling run_usb() here, as it re-processes the arg */ - dev[TYPE_USB] = nutscan_scan_usb(&cli_link_detail_level); + dev[TYPE_USB] = run_usb(&cli_link_detail_level); #endif /* HAVE_PTHREAD */ } else { upsdebugx(1, "USB SCAN: not requested or supported, SKIPPED"); @@ -1780,7 +1779,6 @@ int main(int argc, char *argv[]) upsdebugx(1, "XML/HTTP SCAN: no pthread support, starting nutscan_scan_xml_http_range()..."); /* dev[TYPE_XML] = nutscan_scan_xml_http_range(start_ip, end_ip, timeout, &xml_sec); */ run_xml(&xml_sec); - } #endif /* HAVE_PTHREAD */ } else { upsdebugx(1, "XML/HTTP SCAN: not requested or supported, SKIPPED"); diff --git a/tools/nut-scanner/scan_eaton_serial.c b/tools/nut-scanner/scan_eaton_serial.c index 2b1db5d27c..bd39453e25 100644 --- a/tools/nut-scanner/scan_eaton_serial.c +++ b/tools/nut-scanner/scan_eaton_serial.c @@ -417,6 +417,7 @@ nutscan_device_t * nutscan_scan_eaton_serial(const char* ports_range) char *current_port_name = NULL; char **serial_ports_list; int current_port_nb; + size_t i; #ifdef HAVE_PTHREAD # if (defined HAVE_SEMAPHORE_UNNAMED) || (defined HAVE_SEMAPHORE_NAMED) @@ -428,7 +429,7 @@ nutscan_device_t * nutscan_scan_eaton_serial(const char* ports_range) # endif /* HAVE_SEMAPHORE_UNNAMED || HAVE_SEMAPHORE_NAMED */ pthread_t thread; nutscan_thread_t * thread_array = NULL; - size_t thread_count = 0, i; + size_t thread_count = 0; pthread_mutex_init(&dev_mutex, NULL); #endif /* HAVE_PTHREAD */ From 571f744f08d67e55ce0fc72b487e021e681f94c5 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 5 Feb 2026 20:11:13 +0100 Subject: [PATCH 134/198] drivers/ydn23.h: fix printing of "%zu" with PRIuSIZE Signed-off-by: Jim Klimov --- drivers/ydn23.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/ydn23.h b/drivers/ydn23.h index 9daf07e7dd..ec6ba02a59 100644 --- a/drivers/ydn23.h +++ b/drivers/ydn23.h @@ -60,6 +60,7 @@ #define YDN23_H_SEEN 1 #include "serial.h" +#include "nut_stdint.h" #ifndef htole16 # ifdef WORDS_BIGENDIAN @@ -238,7 +239,7 @@ static inline void ydn23_frame_init( { if (dlen > YDN23_FRAME_INFO_SIZE) { upslogx(LOG_WARNING, - "frame not big enough, required %d got %zu, truncated", + "frame not big enough, required %d got %" PRIuSIZE ", truncated", YDN23_FRAME_INFO_SIZE, dlen); dlen = YDN23_FRAME_INFO_SIZE; } From 38021dae4234244e40e1eea20058247cdf3cf7e6 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 5 Feb 2026 20:53:48 +0100 Subject: [PATCH 135/198] configure.ac, include/nut_stdint.h, NEWS.adoc: actually detect support for (C99+) printf("%zu") et al It seems Solaris 8 struggles with the lack of it, so formatting strings get skewed Signed-off-by: Jim Klimov --- NEWS.adoc | 6 ++++ configure.ac | 18 ++++++++++++ include/nut_stdint.h | 69 ++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 87 insertions(+), 6 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index e6c5dd3790..a6956b35cf 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -97,6 +97,12 @@ https://github.com/networkupstools/nut/milestone/12 not normally get into those code paths with the `x*()` methods which should bail out and abort the program with a common error message when an allocation fails. [#3293] + * We have long abstracted `(s)size_t` value printing in debug logs etc. + using `PRIuSIZE` and similar macros. They fell back to `"%zu"` when not + provided otherwise, but not all platforms actually deliver these format + characters. Now it is evaluated at `configure` time (to check that the + characters may be used), and if not -- during `nut_stdint.h` parsing to + fit known `int`/`long`/`long long` types. [#3300] - NUT for Windows specific updates: * Revised detection of (relative) paths to program and configuration files diff --git a/configure.ac b/configure.ac index 6d9d899446..fb18f212ec 100644 --- a/configure.ac +++ b/configure.ac @@ -1655,6 +1655,24 @@ AS_IF([test x"${ac_cv_func_strdup}" = xyes], [AC_MSG_WARN([Required C library routine strdup not found; try adding -D_POSIX_C_SOURCE=200112L])] ) +AC_CACHE_CHECK([for %zu as PRIuSIZE], + [ac_cv_printfmt_zu], + [AX_RUN_OR_LINK_IFELSE( + [AC_LANG_PROGRAM([$CODE_STRINGINCL +#include +], + [[size_t n = 123; +char buf[64]; +snprintf(buf, sizeof(buf), "%zu", n); +return !strcmp(buf, "123"); +]])], + [ac_cv_printfmt_zu=yes], [ac_cv_printfmt_zu=no] + )]) +AS_IF([test x"${ac_cv_printfmt_zu}" = xyes], + [AC_DEFINE([HAVE_PRINTF_ZU], 1, [defined if standard library has, and C standard allows, the printf("%zu", size_t) support])], + [AC_MSG_WARN([Desired C library support for printf("%zu", size_t) not found; try adding -D_POSIX_C_SOURCE=200112L])] + ) + AC_CACHE_CHECK([for va_copy(dest,src)], [ac_cv_have_va_copy], [ diff --git a/include/nut_stdint.h b/include/nut_stdint.h index 9d64a061b4..65b5b17e3d 100644 --- a/include/nut_stdint.h +++ b/include/nut_stdint.h @@ -57,7 +57,11 @@ #define SSIZE_MAX ((ssize_t)(-1LL)) #endif -/* Printing format for size_t and ssize_t */ +/* Printing format for size_t and ssize_t + * FIXME? Historically we essentially hard-coded it for MINGW builds + * but should we, now that we detect support for printf("%zu", size_t) + * in the configure script?.. + */ #ifndef PRIuSIZE # ifdef PRIsize # define PRIuSIZE PRIsize @@ -65,17 +69,53 @@ # if defined(__MINGW32__) || defined (WIN32) # define PRIuSIZE "llu" # else -# define PRIuSIZE "zu" +# if (defined HAVE_PRINTF_ZU) && HAVE_PRINTF_ZU +# define PRIuSIZE "zu" +# else +# if (SIZE_MAX - 0 == UINT_MAX - 0) +# define PRIuSIZE "u" +# else +# if (SIZE_MAX - 0 == ULONG_MAX - 0) +# define PRIuSIZE "lu" +# else +# if (SIZE_MAX - 0 == ULLONG_MAX - 0) +# define PRIuSIZE "llu" +# else +/* Code may fail on systems where this feature is lacking + * and not considered a format string part, but hopefully + * we do not get here */ +# define PRIuSIZE "zu" +# endif +# endif +# endif +# endif # endif # endif #endif #ifndef PRIxSIZE -# if defined(__MINGW32__) || defined (WIN32) -# define PRIxSIZE "llx" -# else +# if defined(__MINGW32__) || defined (WIN32) +# define PRIxSIZE "llx" +# else +# if (defined HAVE_PRINTF_ZU) && HAVE_PRINTF_ZU # define PRIxSIZE "zx" +# else +# if (SIZE_MAX - 0 == UINT_MAX - 0) +# define PRIxSIZE "x" +# else +# if (SIZE_MAX - 0 == ULONG_MAX - 0) +# define PRIxSIZE "lx" +# else +# if (SIZE_MAX - 0 == ULLONG_MAX - 0) +# define PRIxSIZE "llx" +# else +/* See warning comment above */ +# define PRIxSIZE "zx" +# endif +# endif +# endif # endif +# endif #endif /* Note: Windows headers are known to define at least "d" values, @@ -90,7 +130,24 @@ # if defined(__MINGW32__) || defined (WIN32) # define PRIiSIZE "lld" # else -# define PRIiSIZE "zd" +# if (defined HAVE_PRINTF_ZU) && HAVE_PRINTF_ZU +# define PRIiSIZE "zd" +# else +# if (SIZE_MAX - 0 == UINT_MAX - 0) +# define PRIiSIZE "d" +# else +# if (SIZE_MAX - 0 == ULONG_MAX - 0) +# define PRIiSIZE "ld" +# else +# if (SIZE_MAX - 0 == ULLONG_MAX - 0) +# define PRIiSIZE "lld" +# else +/* See warning comment above */ +# define PRIiSIZE "zd" +# endif +# endif +# endif +# endif # endif # define PRIdSIZE PRIiSIZE # endif From 09e1775b78b2a2d7aef36de8d60d605b25ea9e57 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 5 Feb 2026 21:28:41 +0100 Subject: [PATCH 136/198] common/common.c: nut_prepare_search_paths(): debug more about progressing through the arrays Signed-off-by: Jim Klimov --- common/common.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/common/common.c b/common/common.c index 8d230a790a..c3a4995eac 100644 --- a/common/common.c +++ b/common/common.c @@ -4822,7 +4822,9 @@ void nut_prepare_search_paths(void) { /* As a starting point, allow at least as many items as before */ /* TODO: somehow extend (xrealloc?) if we mix other paths later */ - for (i = 0; search_paths_builtin[i] != NULL; i++) {} + for (i = 0; search_paths_builtin[i] != NULL; i++) { + upsdebugx(7, "counting search_paths_builtin[%d] : %s", i, search_paths_builtin[i]); + } count_builtin = i + 1; /* +1 for the NULL */ /* Bytes inside should all be zeroed... */ @@ -4834,6 +4836,8 @@ void nut_prepare_search_paths(void) { int dupe = 0; const char *dirname = search_paths_builtin[i]; + upsdebugx(7, "%s: checking search_paths_builtin[%" PRIuSIZE " of %" PRIuSIZE "] : %s", + __func__, i, count_builtin - 1, NUT_STRARG(dirname)); if ((dp = opendir(dirname)) == NULL) { upsdebugx(5, "%s: SKIP " "unreachable directory #%" PRIuSIZE " : %s", @@ -4844,12 +4848,16 @@ void nut_prepare_search_paths(void) { #if HAVE_DECL_REALPATH /* allocates the buffer we free() later */ + upsdebugx(7, "%s: call realpath()", __func__); dirname = (const char *)realpath(dirname, NULL); + upsdebug_with_errno(7, "%s: realpath() returned: %s", __func__, NUT_STRARG(dirname)); #endif /* Revise for duplicates */ /* Note: (count_filtered == 0) means first existing dir seen, no hassle */ for (j = 0; j < count_filtered; j++) { + upsdebugx(7, "%s: check for duplicates filtered_search_paths[%" PRIuSIZE " of %" PRIuSIZE "] : %s", + __func__, j, count_filtered, NUT_STRARG(filtered_search_paths[j])); if (!strcmp(filtered_search_paths[j], dirname)) { #if HAVE_DECL_REALPATH if (strcmp(search_paths_builtin[i], dirname)) { From 712a971de4c90e0c79789a41f674e996941be374 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 5 Feb 2026 21:29:01 +0100 Subject: [PATCH 137/198] common/common.c: nut_prepare_search_paths(): separate logging from index increment Signed-off-by: Jim Klimov --- common/common.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/common.c b/common/common.c index c3a4995eac..f1c1735688 100644 --- a/common/common.c +++ b/common/common.c @@ -4841,7 +4841,8 @@ void nut_prepare_search_paths(void) { if ((dp = opendir(dirname)) == NULL) { upsdebugx(5, "%s: SKIP " "unreachable directory #%" PRIuSIZE " : %s", - __func__, index++, dirname); + __func__, index, NUT_STRARG(dirname)); + index++; continue; } index++; From 04edf90426ed6cac96d6c6858ea4243fbef37870 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 5 Feb 2026 21:29:49 +0100 Subject: [PATCH 138/198] common/common.c: nut_prepare_search_paths(): some systems require non-NULL args to realpath(), provide the buffer and handle errors better Signed-off-by: Jim Klimov --- common/common.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/common/common.c b/common/common.c index f1c1735688..1c36d847b2 100644 --- a/common/common.c +++ b/common/common.c @@ -4819,6 +4819,10 @@ void nut_prepare_search_paths(void) { size_t count_builtin = 0, count_filtered = 0, i, j, index = 0; const char ** filtered_search_paths; DIR *dp; +#if HAVE_DECL_REALPATH + /* Per docs, buffer must be at least PATH_MAX bytes */ + char realpath_buf[NUT_PATH_MAX + 1] = {0}, *realpath_dirname = NULL; +#endif /* As a starting point, allow at least as many items as before */ /* TODO: somehow extend (xrealloc?) if we mix other paths later */ @@ -4850,8 +4854,14 @@ void nut_prepare_search_paths(void) { #if HAVE_DECL_REALPATH /* allocates the buffer we free() later */ upsdebugx(7, "%s: call realpath()", __func__); - dirname = (const char *)realpath(dirname, NULL); - upsdebug_with_errno(7, "%s: realpath() returned: %s", __func__, NUT_STRARG(dirname)); + errno = 0; + realpath_dirname = realpath(dirname, realpath_buf); + if (errno || !realpath_dirname) + upsdebug_with_errno(7, "%s: realpath() failed and returned: %s", __func__, NUT_STRARG(realpath_dirname)); + else + upsdebugx(7, "%s: realpath() returned: %s", __func__, NUT_STRARG(realpath_dirname)); + if (realpath_dirname) + dirname = (const char *)realpath_dirname; #endif /* Revise for duplicates */ From 26fe2a14eb417c0fe7af4c8c32ae39210e4fe9aa Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 5 Feb 2026 22:00:38 +0100 Subject: [PATCH 139/198] common/common.c: get_libname_in_*(): use NUT_STRARG() when logging strings Signed-off-by: Jim Klimov --- common/common.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/common.c b/common/common.c index 1c36d847b2..8e17f9c6c9 100644 --- a/common/common.c +++ b/common/common.c @@ -5003,7 +5003,7 @@ static char * get_libname_in_dir(const char* base_libname, size_t base_libname_l char current_test_path[NUT_PATH_MAX + 1]; upsdebugx(3, "%s('%s', %" PRIuSIZE ", '%s', %i): Entering method...", - __func__, base_libname, base_libname_length, dirname, index); + __func__, NUT_STRARG(base_libname), base_libname_length, NUT_STRARG(dirname), index); memset(current_test_path, 0, sizeof(current_test_path)); @@ -5136,7 +5136,7 @@ static char * get_libname_in_pathset(const char* base_libname, size_t base_libna /* First call to tokenization passes the string, others pass NULL */ pathset_tmp = xstrdup(pathset); upsdebugx(4, "%s: Looking for lib %s in a colon-separated path set", - __func__, base_libname); + __func__, NUT_STRARG(base_libname)); while (NULL != (onedir = strtok( (onedir ? NULL : pathset_tmp), ":" ))) { libname_path = get_libname_in_dir(base_libname, base_libname_length, onedir, (*counter)++); if (libname_path != NULL) @@ -5172,7 +5172,7 @@ char * get_libname(const char* base_libname) size_t base_libname_length = strlen(base_libname); struct stat st; - upsdebugx(3, "%s('%s'): Entering method...", __func__, base_libname); + upsdebugx(3, "%s('%s'): Entering method...", __func__, NUT_STRARG(base_libname)); /* First, check for an exact hit by absolute/relative path * if `base_libname` includes path separator character(s) */ From e4472a345bd4160653b301bb00568c8f5e137733 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 5 Feb 2026 22:20:49 +0100 Subject: [PATCH 140/198] common/common.c: vupslog(): be conservative about growing our buffer, most logs are short Signed-off-by: Jim Klimov --- common/common.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/common/common.c b/common/common.c index 8e17f9c6c9..f18c909167 100644 --- a/common/common.c +++ b/common/common.c @@ -3767,7 +3767,13 @@ char * mkstr_dynamic(const char *fmt_dynamic, const char *fmt_reference, ...) static void vupslog(int priority, const char *fmt, va_list va, int use_strerror) { int ret, errno_orig = errno; +#ifdef HAVE_VA_COPY_VARIANT + size_t bufsize = 128; +#else + /* err on the safe(r) side, as re-runs can truncate + * the output when varargs are re-used */ size_t bufsize = LARGEBUF; +#endif char *buf = (char *)xcalloc(bufsize, sizeof(char)); /* Be pedantic about our limitations */ @@ -3827,7 +3833,7 @@ static void vupslog(int priority, const char *fmt, va_list va, int use_strerror) * Based on https://stackoverflow.com/a/72981237/4715872 */ if (bufsize < SIZE_MAX/2) { - size_t newbufsize = bufsize*2; + size_t newbufsize = bufsize < LARGEBUF ? LARGEBUF : bufsize*2; if (ret > 0) { /* Be generous, we snprintfcat() some * suffixes, prefix a timestamp, etc. */ From 21bcb0576b113dc8dcfc5042423de38dc43bcdc3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 5 Feb 2026 22:19:45 +0100 Subject: [PATCH 141/198] docs/nut.dict: update the dictionary [#3300] Signed-off-by: Jim Klimov --- docs/nut.dict | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/nut.dict b/docs/nut.dict index 9cbfba67ea..224b8281b4 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3649 utf-8 +personal_ws-1.1 en 3654 utf-8 AAC AAS ABI @@ -959,6 +959,7 @@ PPDnnn PPP PR PR'ed +PRIuSIZE PROGRA PROGS PROTVER @@ -2474,6 +2475,7 @@ libnutscan libpcre libpng libpowerman +libpthread libre libregex libs @@ -2834,6 +2836,7 @@ pF pacman pacstrap parallelizable +parallelize parallelized param parsable @@ -3224,6 +3227,7 @@ startup statepath stayoff stderr +stdint stdlib stdout stdupsv @@ -3643,6 +3647,7 @@ znapzendzetup zpool zroot zsh +zu zw zwfa zzz From cd9411aaecce8e4c6fb37a8c8d28f64383e3fd68 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 5 Feb 2026 22:27:59 +0100 Subject: [PATCH 142/198] common/common.c: refine deliberate logging without PRIuSIZE in nut_prepare_search_paths() [#3300] Signed-off-by: Jim Klimov --- common/common.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/common.c b/common/common.c index f18c909167..73e08db7df 100644 --- a/common/common.c +++ b/common/common.c @@ -4833,7 +4833,8 @@ void nut_prepare_search_paths(void) { /* As a starting point, allow at least as many items as before */ /* TODO: somehow extend (xrealloc?) if we mix other paths later */ for (i = 0; search_paths_builtin[i] != NULL; i++) { - upsdebugx(7, "counting search_paths_builtin[%d] : %s", i, search_paths_builtin[i]); + /* Different way of printing with minimal crash-ability on older systems */ + upsdebugx(7, "counting search_paths_builtin[%d] : %s", (int)i, NUT_STRARG(search_paths_builtin[i])); } count_builtin = i + 1; /* +1 for the NULL */ From 2f9638c8a218d4a92a86673c26fba15bf98cb1ba Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Feb 2026 00:22:23 +0100 Subject: [PATCH 143/198] tools/nut-scanner/scan_nut_simulation.c: use "#ifdef HAVE_PTHREAD" consistently with other code [#3300] Signed-off-by: Jim Klimov --- tools/nut-scanner/scan_nut_simulation.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/nut-scanner/scan_nut_simulation.c b/tools/nut-scanner/scan_nut_simulation.c index e0b39f7c2f..8cf9b352c7 100644 --- a/tools/nut-scanner/scan_nut_simulation.c +++ b/tools/nut-scanner/scan_nut_simulation.c @@ -42,7 +42,7 @@ nutscan_device_t * nutscan_scan_nut_simulation(void) nutscan_device_t * dev = NULL; const char *dirname = confpath(); -#if HAVE_PTHREAD +#ifdef HAVE_PTHREAD pthread_mutex_init(&dev_mutex, NULL); #endif /* HAVE_PTHREAD */ @@ -85,7 +85,7 @@ nutscan_device_t * nutscan_scan_nut_simulation(void) } closedir(dp); -#if HAVE_PTHREAD +#ifdef HAVE_PTHREAD pthread_mutex_destroy(&dev_mutex); #endif /* HAVE_PTHREAD */ From 6442c0c1d1a7aca861f0cfce69f1149ef73a73f0 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Feb 2026 00:43:04 +0100 Subject: [PATCH 144/198] configure.ac: better detect HAVE_SEMAPHORE_LIBS (even if we do not need to link anything additional) [#3300] Signed-off-by: Jim Klimov --- configure.ac | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/configure.ac b/configure.ac index fb18f212ec..925bcb2313 100644 --- a/configure.ac +++ b/configure.ac @@ -1318,9 +1318,13 @@ AC_CHECK_HEADER([poll.h], [Define to 1 if you have .])]) SEMLIBS="" +nut_have_semaphore_h=no +nut_have_semaphore_unnamed=no +nut_have_semaphore_named=no AC_CHECK_HEADER([semaphore.h], [AC_DEFINE([HAVE_SEMAPHORE_H], [1], [Define to 1 if you have .]) + nut_have_semaphore_h=yes AC_LANG_PUSH([C]) myLIBS="${LIBS}" @@ -1331,11 +1335,11 @@ AC_CHECK_HEADER([semaphore.h], dnl sem_init nut_scanner-nut-scanner.o dnl (symbol belongs to implicit dependency /usr/lib/librt.so.1) AC_SEARCH_LIBS([sem_init], [pthread], [], [ - unset ac_cv_search_sem_init - AC_SEARCH_LIBS([sem_init], [pthread], [SEMLIBS_LRT=" -lrt"], [], [-lrt])]) + unset ac_cv_search_sem_init + AC_SEARCH_LIBS([sem_init], [pthread], [SEMLIBS_LRT=" -lrt"], [], [-lrt])]) AC_SEARCH_LIBS([sem_open], [pthread], [], [ - unset ac_cv_search_sem_open - AC_SEARCH_LIBS([sem_open], [pthread], [SEMLIBS_LRT=" -lrt"], [], [-lrt])]) + unset ac_cv_search_sem_open + AC_SEARCH_LIBS([sem_open], [pthread], [SEMLIBS_LRT=" -lrt"], [], [-lrt])]) AS_CASE([${ac_cv_search_sem_init}], [no*], [], [SEMLIBS="${ac_cv_search_sem_init}"]) AS_CASE([${ac_cv_search_sem_open}], [no*], [], ["${SEMLIBS}"], [], [SEMLIBS="${ac_cv_search_sem_open}"]) @@ -1357,6 +1361,7 @@ sem_destroy(&semaphore); [AC_DEFINE([HAVE_SEMAPHORE_UNNAMED], [1], [Define to 1 if you have with usable sem_t, sem_init() and sem_destroy() for unnamed semaphores.]) AC_MSG_RESULT([ok]) + nut_have_semaphore_unnamed=yes ], [AC_MSG_RESULT([no])] ) @@ -1381,6 +1386,7 @@ if (semaphore != SEM_FAILED) [AC_DEFINE([HAVE_SEMAPHORE_NAMED], [1], [Define to 1 if you have with usable sem_t, sem_open() and sem_close() for named semaphores.]) AC_MSG_RESULT([ok]) + nut_have_semaphore_named=yes ], [AC_MSG_RESULT([no])] ) @@ -1389,7 +1395,8 @@ if (semaphore != SEM_FAILED) AC_LANG_POP([C]) ] ) -AM_CONDITIONAL(HAVE_SEMAPHORE_LIBS, test -n "${SEMLIBS}") +AM_CONDITIONAL(HAVE_SEMAPHORE_LIBS, [test -n "${SEMLIBS}"]) +AM_CONDITIONAL(HAVE_SEMAPHORE_ABILITY, [test -n "${SEMLIBS}" -o x"${nut_have_semaphore_h}" = xyes -o x"${nut_have_semaphore_unnamed}" = xyes -o x"${nut_have_semaphore_named}" = xyes]) dnl ---------------------------------------------------------------------- dnl Check for --with-threading request @@ -1400,8 +1407,8 @@ NUT_ARG_WITH([threading], AC_MSG_CHECKING([Whether to enable support for parallelization of some tools]) AS_CASE(["${nut_with_threading}"], - [""|yes], [AM_COND_IF([HAVE_SEMAPHORE_LIBS], [], [AC_MSG_ERROR([pthread support was required but libraries not detected])])], - [auto],[AM_COND_IF([HAVE_SEMAPHORE_LIBS], [nut_with_threading=yes], [nut_with_threading=no])], + [""|yes], [AM_COND_IF([HAVE_SEMAPHORE_ABILITY], [], [AC_MSG_ERROR([pthread support was required but libraries not detected])])], + [auto],[AM_COND_IF([HAVE_SEMAPHORE_ABILITY], [nut_with_threading=yes], [nut_with_threading=no])], [no], [], [AC_MSG_ERROR([Unsupported value for --with-threading option: "${nut_with_threading}"])] ) From 182a7c982f1ef8d3b97f7363850e573f8b377ddb Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Feb 2026 00:44:51 +0100 Subject: [PATCH 145/198] configure.ac: avoid reporting "Whether to enable support for parallelization of some tools" twice [#3300] Signed-off-by: Jim Klimov --- configure.ac | 2 -- 1 file changed, 2 deletions(-) diff --git a/configure.ac b/configure.ac index 925bcb2313..60aece48cb 100644 --- a/configure.ac +++ b/configure.ac @@ -1405,14 +1405,12 @@ NUT_ARG_WITH([threading], [If it is possible to parallelize some tools (e.g. nut-scanner), do so?], [auto]) -AC_MSG_CHECKING([Whether to enable support for parallelization of some tools]) AS_CASE(["${nut_with_threading}"], [""|yes], [AM_COND_IF([HAVE_SEMAPHORE_ABILITY], [], [AC_MSG_ERROR([pthread support was required but libraries not detected])])], [auto],[AM_COND_IF([HAVE_SEMAPHORE_ABILITY], [nut_with_threading=yes], [nut_with_threading=no])], [no], [], [AC_MSG_ERROR([Unsupported value for --with-threading option: "${nut_with_threading}"])] ) -AC_MSG_RESULT([${nut_with_threading}]) NUT_REPORT_FEATURE([Enable support for parallelization of some tools], [${nut_with_threading}], [${SEMLIBS}], [WITH_THREADING], [Define to enable build with threading support]) From f2550c48a908d98dff43028029437e8284f07ebc Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Feb 2026 01:24:59 +0000 Subject: [PATCH 146/198] common/common.c: fix freeing of dynamically detected search_paths after fixing use of realpath() to use our buffer [#3300] Signed-off-by: Jim Klimov --- common/common.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/common/common.c b/common/common.c index 73e08db7df..50803b25f4 100644 --- a/common/common.c +++ b/common/common.c @@ -4800,10 +4800,14 @@ static void nut_free_search_paths(void) { } if (search_paths != search_paths_builtin) { +#if HAVE_DECL_REALPATH size_t i; for (i = 0; search_paths[i] != NULL; i++) { + upsdebugx(7, "%s: freeing search_paths[%" PRIuSIZE "]: '%s'", + __func__, i, NUT_STRARG(search_paths[i])); free((char *)search_paths[i]); } +#endif /* else: curated selection of pointers to some of the built-in strings */ free(search_paths); search_paths = search_paths_builtin; } @@ -4892,7 +4896,6 @@ void nut_prepare_search_paths(void) { dupe = 1; #if HAVE_DECL_REALPATH - free((char *)dirname); /* Have some valid value, for kicks (likely * to be ignored in the code path below) */ dirname = search_paths_builtin[i]; @@ -4905,9 +4908,10 @@ void nut_prepare_search_paths(void) { upsdebugx(5, "%s: ADD[#%" PRIuSIZE "] " "existing unique directory: %s", __func__, count_filtered, dirname); -#if !HAVE_DECL_REALPATH - /* Make a copy of table entry, else we have - * a dynamic result of realpath() made above. +#if HAVE_DECL_REALPATH + /* Make a copy of table entry, or the buffer + * with a result of realpath() made above, + * to eventually conststently free(). */ dirname = (const char *)xstrdup(dirname); #endif From 3e7021c1fabb33751a878c38d0c741a45bebd88e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Feb 2026 01:26:20 +0000 Subject: [PATCH 147/198] tools/nut-scanner/scan_usb.c: do not call libusb_exit() after a failed libusb_init() on libusb older than 1.0.24 [#3300] Signed-off-by: Jim Klimov --- tools/nut-scanner/scan_usb.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/tools/nut-scanner/scan_usb.c b/tools/nut-scanner/scan_usb.c index 37faefb614..1e63191948 100644 --- a/tools/nut-scanner/scan_usb.c +++ b/tools/nut-scanner/scan_usb.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2011-2016 - EATON - * Copyright (C) 2020-2024 - Jim Klimov - support and modernization of codebase + * Copyright (C) 2020-2026 - Jim Klimov - support and modernization of codebase * * 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 @@ -73,6 +73,7 @@ static int nut_usb_get_string_with_langid_control_transfer( static int (*nut_usb_get_device_descriptor)( libusb_device *dev, struct libusb_device_descriptor *desc); + static const struct libusb_version * (*nut_usb_get_version)(void); # define USB_DT_STRING LIBUSB_DT_STRING # define USB_ENDPOINT_IN LIBUSB_ENDPOINT_IN # define USB_REQ_GET_DESCRIPTOR LIBUSB_REQUEST_GET_DESCRIPTOR @@ -160,6 +161,11 @@ int nutscan_load_usb_library(const char *libname_path) goto err; } + *(void **) (&nut_usb_get_version) = lt_dlsym(dl_handle, "libusb_get_version"); + if ((dl_error = lt_dlerror()) != NULL) { + goto err; + } + *(void **) (&nut_usb_get_device_list) = lt_dlsym(dl_handle, "libusb_get_device_list"); if ((dl_error = lt_dlerror()) != NULL) { @@ -488,7 +494,15 @@ nutscan_device_t * nutscan_scan_usb(nutscan_usb_t * scanopts) /* Initialize Libusb */ #if WITH_LIBUSB_1_0 if ((*nut_usb_init)(NULL) < 0) { - (*nut_usb_exit)(NULL); + /* Per https://github.com/libusb/libusb/issues/511 fixed since + * 1.0.24 by https://github.com/libusb/libusb/commit/a5624b22267ec0e146825d3fe94d9e4b2f5ae503 + * libusb_exit() should not be called unless libusb_init() + * succeeded for same context. + */ + const struct libusb_version *ver = (*nut_usb_get_version)(); + + if (ver && (ver->major > 1 || (ver->major == 1 && ver->minor >= 24))) + (*nut_usb_exit)(NULL); upsdebug_with_errno(0, "Failed to init libusb 1.0"); /* nutscan_avail_usb = 0; */ return NULL; From 76b801b8b557f3af1bfb513ee5f6dcd1041634d2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Feb 2026 01:37:50 +0000 Subject: [PATCH 148/198] tools/gitlog2version.sh: fix for git describe versions before --exclude option [#3300] Signed-off-by: Jim Klimov --- tools/gitlog2version.sh | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tools/gitlog2version.sh b/tools/gitlog2version.sh index 31cef0deac..01fc08be00 100755 --- a/tools/gitlog2version.sh +++ b/tools/gitlog2version.sh @@ -1,6 +1,6 @@ #!/bin/sh -# Copyright (C) 2016-2025 by Jim Klimov +# Copyright (C) 2016-2026 by 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 @@ -241,9 +241,13 @@ getver_git() { # Praises to old gits and the new, who may --exclude; # NOTE: match/exclude by shell glob expressions, not regex! - DESC="`git describe $ALL_TAGS_ARG $ALWAYS_DESC_ARG --match 'v[0-9]*.[0-9]*.[0-9]' --exclude '*-signed' --exclude '*rc*' --exclude '*alpha*' --exclude '*beta*' --exclude '*Windows*' --exclude '*IPM*' 2>/dev/null`" \ + DESC="`git describe $ALL_TAGS_ARG $ALWAYS_DESC_ARG --match 'v[0123456789]*.[0123456789]*.[0123456789]' --exclude '*-signed' --exclude '*rc*' --exclude '*alpha*' --exclude '*beta*' --exclude '*Windows*' --exclude '*IPM*' 2>/dev/null`" \ && [ -n "${DESC}" ] \ - || DESC="`git describe $ALL_TAGS_ARG $ALWAYS_DESC_ARG | ${EGREP} -v '(rc|-signed|alpha|beta|Windows|IPM)' | ${EGREP} 'v[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*'`" + || { # Try our luck with versions before --exclude + DESC="`git describe $ALL_TAGS_ARG $ALWAYS_DESC_ARG --match 'v[0123456789]*.[0123456789]*.[0123456789]' 2>/dev/null`" \ + && [ -n "${DESC}" ] \ + || DESC="`git describe $ALL_TAGS_ARG $ALWAYS_DESC_ARG | ${EGREP} -v '(rc|-signed|alpha|beta|Windows|IPM)' | ${EGREP} 'v[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*'`" + } # Old stripper (also for possible refspec parts like "tags/"): # echo "${DESC}" | sed -e 's/^v\([0-9]\)/\1/' -e 's,^.*/,,' # Follow https://semver.org/#spec-item-10 about build metadata: From 5804a7355bb9491d9296e21ab610fe499ec4c1f9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Feb 2026 01:54:05 +0000 Subject: [PATCH 149/198] tools/nut-scanner/scan_nut.c: debug-trace what in upscli failed [#3300] Signed-off-by: Jim Klimov --- tools/nut-scanner/scan_nut.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/nut-scanner/scan_nut.c b/tools/nut-scanner/scan_nut.c index 368a80b99d..b9465633ca 100644 --- a/tools/nut-scanner/scan_nut.c +++ b/tools/nut-scanner/scan_nut.c @@ -193,6 +193,7 @@ static void * list_nut_devices_thready(void * arg) if ((*nut_upscli_splitaddr)(target_hostname, &hostname, &port) != 0) { /* Avoid disconnect from not connected ups */ + upsdebugx(4, "%s: upscli_splitaddr() failed", __func__); if (ups) { if (ups->host) free(ups->host); @@ -204,6 +205,7 @@ static void * list_nut_devices_thready(void * arg) if ((*nut_upscli_tryconnect)(ups, hostname, port, UPSCLI_CONN_TRYSSL, &tv) < 0) { /* Avoid disconnect from not connected ups */ + upsdebugx(4, "%s: upscli_tryconnect() failed", __func__); if (ups) { if (ups->host) free(ups->host); @@ -214,12 +216,14 @@ static void * list_nut_devices_thready(void * arg) } if ((*nut_upscli_list_start)(ups, numq, query) < 0) { + upsdebugx(4, "%s: upscli_list_start() failed", __func__); goto end; } while ((*nut_upscli_list_next)(ups, numq, query, &numa, &answer) == 1) { /* UPS */ if (numa < 3) { + upsdebugx(4, "%s: upscli_list_next() failed", __func__); goto end; } From c70970853ba3b085961bb174cf3bd283a01e3af7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Feb 2026 03:22:21 +0100 Subject: [PATCH 150/198] configure.ac: avoid AM_COND_IF absent in older aclocal builds [#3300] Signed-off-by: Jim Klimov --- configure.ac | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 60aece48cb..04a99ef0cf 100644 --- a/configure.ac +++ b/configure.ac @@ -1396,7 +1396,9 @@ if (semaphore != SEM_FAILED) ] ) AM_CONDITIONAL(HAVE_SEMAPHORE_LIBS, [test -n "${SEMLIBS}"]) -AM_CONDITIONAL(HAVE_SEMAPHORE_ABILITY, [test -n "${SEMLIBS}" -o x"${nut_have_semaphore_h}" = xyes -o x"${nut_have_semaphore_unnamed}" = xyes -o x"${nut_have_semaphore_named}" = xyes]) +AS_IF([test -n "${SEMLIBS}" -o x"${nut_have_semaphore_h}" = xyes -o x"${nut_have_semaphore_unnamed}" = xyes -o x"${nut_have_semaphore_named}" = xyes], + [nut_have_semaphore_ability=yes], + [nut_have_semaphore_ability=no]) dnl ---------------------------------------------------------------------- dnl Check for --with-threading request @@ -1406,8 +1408,8 @@ NUT_ARG_WITH([threading], [auto]) AS_CASE(["${nut_with_threading}"], - [""|yes], [AM_COND_IF([HAVE_SEMAPHORE_ABILITY], [], [AC_MSG_ERROR([pthread support was required but libraries not detected])])], - [auto],[AM_COND_IF([HAVE_SEMAPHORE_ABILITY], [nut_with_threading=yes], [nut_with_threading=no])], + [""|yes], [AS_IF([test x"${nut_have_semaphore_ability}" = xyes], [], [AC_MSG_ERROR([pthread support was required but libraries not detected])])], + [auto],[AS_IF([test x"${nut_have_semaphore_ability}" = xyes], [nut_with_threading=yes], [nut_with_threading=no])], [no], [], [AC_MSG_ERROR([Unsupported value for --with-threading option: "${nut_with_threading}"])] ) From 9bd31ff9c3e72d779566b806144528676284e5bb Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Feb 2026 13:18:00 +0100 Subject: [PATCH 151/198] .github/workflows/08-PyNUTClient.yml: do not let @dotMAKE@ get in our way here [#3300] NOTE: We were running Makefile.am previously directly as a makefile for PyPI publishing; now a slightly transformed version of it. Signed-off-by: Jim Klimov --- .github/workflows/08-PyNUTClient.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/08-PyNUTClient.yml b/.github/workflows/08-PyNUTClient.yml index 353394e9bd..541eed1d8a 100644 --- a/.github/workflows/08-PyNUTClient.yml +++ b/.github/workflows/08-PyNUTClient.yml @@ -61,8 +61,8 @@ jobs: run: >- set -e ; cd scripts/python/module ; - cp -f Makefile.am Makefile ; - make -f Makefile.am clean-local dist NUT_SOURCE_GITREV_NUMERIC="${{ steps.tag.outputs.TAG_NAME }}" PYTHON_DEFAULT="${{ steps.pythoncmd.outputs.PYTHON_DEFAULT }}" top_srcdir="../../.." srcdir="." builddir="." ; + sed 's,@dotMAKE@,,' < Makefile.am > Makefile ; + make -f Makefile clean-local dist NUT_SOURCE_GITREV_NUMERIC="${{ steps.tag.outputs.TAG_NAME }}" PYTHON_DEFAULT="${{ steps.pythoncmd.outputs.PYTHON_DEFAULT }}" top_srcdir="../../.." srcdir="." builddir="." ; find . -ls - name: Publish master distribution 📦 to Test PyPI # https://github.com/pypa/gh-action-pypi-publish From b2e08b8355c76a2adb03e71025137a628db71149 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Feb 2026 16:00:20 +0100 Subject: [PATCH 152/198] clients/upsimage.c, clients/upsset.c, clients/upsstats.c: fix indentation for recent fixes and update (C) heading [#3219] Signed-off-by: Jim Klimov --- clients/upsimage.c | 17 +++++++++-------- clients/upsset.c | 17 +++++++++-------- clients/upsstats.c | 17 +++++++++-------- 3 files changed, 27 insertions(+), 24 deletions(-) diff --git a/clients/upsimage.c b/clients/upsimage.c index 1d99fdac15..a055cab28a 100644 --- a/clients/upsimage.c +++ b/clients/upsimage.c @@ -20,6 +20,7 @@ Copyrights: (C) 1998 Russell Kroll (C) 2002 Simon Rozman + (C) 2020-2026 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 @@ -619,14 +620,14 @@ int main(int argc, char **argv) double var = 0; #ifdef WIN32 - /* Required ritual before calling any socket functions */ - static WSADATA WSAdata; - static int WSA_Started = 0; - if (!WSA_Started) { - WSAStartup(2, &WSAdata); - atexit((void(*)(void))WSACleanup); - WSA_Started = 1; - } + /* Required ritual before calling any socket functions */ + static WSADATA WSAdata; + static int WSA_Started = 0; + if (!WSA_Started) { + WSAStartup(2, &WSAdata); + atexit((void(*)(void))WSACleanup); + WSA_Started = 1; + } /* Avoid binary output conversions, e.g. * mangling what looks like CRLF on WIN32 */ diff --git a/clients/upsset.c b/clients/upsset.c index 898acd4dba..83abe0710e 100644 --- a/clients/upsset.c +++ b/clients/upsset.c @@ -1,6 +1,7 @@ /* upsset - CGI program to manage read/write variables Copyright (C) 1999 Russell Kroll + Copyright (C) 2020-2026 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 @@ -1116,14 +1117,14 @@ int main(int argc, char **argv) int i; #ifdef WIN32 - /* Required ritual before calling any socket functions */ - static WSADATA WSAdata; - static int WSA_Started = 0; - if (!WSA_Started) { - WSAStartup(2, &WSAdata); - atexit((void(*)(void))WSACleanup); - WSA_Started = 1; - } + /* Required ritual before calling any socket functions */ + static WSADATA WSAdata; + static int WSA_Started = 0; + if (!WSA_Started) { + WSAStartup(2, &WSAdata); + atexit((void(*)(void))WSACleanup); + WSA_Started = 1; + } /* Avoid binary output conversions, e.g. * mangling what looks like CRLF on WIN32 */ diff --git a/clients/upsstats.c b/clients/upsstats.c index 5a0bf47521..189d7bc368 100644 --- a/clients/upsstats.c +++ b/clients/upsstats.c @@ -2,6 +2,7 @@ Copyright (C) 1998 Russell Kroll Copyright (C) 2005 Arnaud Quette + Copyright (C) 2020-2026 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 @@ -1489,14 +1490,14 @@ int main(int argc, char **argv) int i; #ifdef WIN32 - /* Required ritual before calling any socket functions */ - static WSADATA WSAdata; - static int WSA_Started = 0; - if (!WSA_Started) { - WSAStartup(2, &WSAdata); - atexit((void(*)(void))WSACleanup); - WSA_Started = 1; - } + /* Required ritual before calling any socket functions */ + static WSADATA WSAdata; + static int WSA_Started = 0; + if (!WSA_Started) { + WSAStartup(2, &WSAdata); + atexit((void(*)(void))WSACleanup); + WSA_Started = 1; + } /* Avoid binary output conversions, e.g. * mangling what looks like CRLF on WIN32 */ From 77c206ba2be0f36572d10f7d289b16ac603843d9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Feb 2026 16:05:37 +0100 Subject: [PATCH 153/198] clients/upsstats.c: parameterize template_single and template_list filenames with legacy defaults [#2524] Signed-off-by: Jim Klimov --- clients/upsstats.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/clients/upsstats.c b/clients/upsstats.c index 189d7bc368..b7610ba42e 100644 --- a/clients/upsstats.c +++ b/clients/upsstats.c @@ -63,7 +63,9 @@ static char *monhostdesc = NULL; static uint16_t port; static char *upsname, *hostname; -static char *upsimgpath="upsimage.cgi" EXEEXT, *upsstatpath="upsstats.cgi" EXEEXT; +static char *upsimgpath="upsimage.cgi" EXEEXT, *upsstatpath="upsstats.cgi" EXEEXT, + *template_single = "upsstats-single.html", + *template_list = "upsstats.html"; static UPSCONN_t ups; static FILE *tf; @@ -1327,7 +1329,7 @@ static void display_single(void) if (treemode) display_tree(1); else - display_template("upsstats-single.html"); + display_template(template_single); upscli_disconnect(&ups); upsdebug_call_finished0(); @@ -1559,7 +1561,7 @@ int main(int argc, char **argv) /* default: multimon replacement mode */ load_hosts_conf(); currups = ulhead; - display_template("upsstats.html"); + display_template(template_list); } /* Clean up memory */ From 477b381b44fe44251a89ed3ebf28bdd6b41d8511 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Feb 2026 14:13:37 +0100 Subject: [PATCH 154/198] server/upsd.c, docs/man/upsd.conf.txt, conf/upsd.conf.sample, NEWS.adoc: track "sysmaxconn" not as a reason to fail data server configuration, but to chunk the MAXCONN-sized array processing into several smaller polls as needed [#3302] Signed-off-by: Jim Klimov --- NEWS.adoc | 4 +- conf/upsd.conf.sample | 5 ++ docs/man/upsd.conf.txt | 6 ++ server/upsd.c | 155 ++++++++++++++++++++++++++++++++--------- 4 files changed, 137 insertions(+), 33 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index b618b57d3c..1ecbd6662c 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -12,7 +12,6 @@ For a complete and more detailed list of changes, please refer to the ChangeLog file (generated for release archives), or to the Git version control history for "live" codebase. - PLANNED: Release notes for NUT 2.8.5 - what's new since 2.8.4 ------------------------------------------------------------- @@ -287,6 +286,9 @@ https://github.com/networkupstools/nut/milestone/12 comes into play and breaks things. [issue #661] * Fixed `LISTEN *` handling for `upsd.exe` in NUT for Windows builds. [PR #3237] + * Extended processing of `MAXCONN` setting to allow larger values than the + operating system allows, by only waiting for that amount of Unix sockets + or Windows `HANDLE`'s at a time, and moving on to another chunk. [#3302] - `upsdrvctl` tool updates: * Make use of `setproctag()` and `getproctag()` to report parent/child diff --git a/conf/upsd.conf.sample b/conf/upsd.conf.sample index 9497b1c63b..d2ed9a8f71 100644 --- a/conf/upsd.conf.sample +++ b/conf/upsd.conf.sample @@ -121,6 +121,11 @@ # LISTEN address and each client count as one connection. If the server # runs out of connections, it will no longer accept new incoming client # connections. Only set this if you know exactly what you're doing. +# Note that on some platforms there may be a smaller amount of file descriptors +# or handles that can be polled in one operation, the server would then poll +# several smaller groups until it handles all the connections it tracks. +# With a large amount of connections this may however impact the delays between +# processing loops, and time before an incoming message is seen and processed. # ======================================================================= # CERTFILE diff --git a/docs/man/upsd.conf.txt b/docs/man/upsd.conf.txt index a79355f656..f6d538e7c6 100644 --- a/docs/man/upsd.conf.txt +++ b/docs/man/upsd.conf.txt @@ -150,6 +150,12 @@ This defaults to maximum number allowed on your system. Each UPS, each `LISTEN` address and each client count as one connection. If the server runs out of connections, it will no longer accept new incoming client connections. Only set this if you know exactly what you're doing. ++ +Note that on some platforms there may be a smaller amount of file descriptors +or handles that can be polled in one operation, the server would then poll +several smaller groups until it handles all the connections it tracks. +With a large amount of connections this may however impact the delays between +processing loops, and time before an incoming message is seen and processed. *CERTFILE 'certificate file'*:: diff --git a/server/upsd.c b/server/upsd.c index 12ca91beea..363ec5c5e0 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -5,7 +5,7 @@ 2008 Arjen de Korte 2011 - 2012 Arnaud Quette 2019 Eaton (author: Arnaud Quette ) - 2020 - 2025 Jim Klimov + 2020 - 2026 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 @@ -94,8 +94,12 @@ int allow_no_device = 0; */ int allow_not_all_listeners = 0; -/* preloaded to {OPEN_MAX} in main, can be overridden via upsd.conf */ +/* preloaded to POSIX sysconf(_SC_OPEN_MAX) or WIN32 MAX_WAIT_OBJECTS in main + * and elsewhere, the run-time value can be overridden via upsd.conf `MAXCONN` + * option (may cause partial waits chunk by chunk, if sysmaxconn is smaller). + */ nfds_t maxconn = 0; +static nfds_t sysmaxconn = 0; /* preloaded to STATEPATH in main, can be overridden via upsd.conf */ char *statepath = NULL; @@ -112,7 +116,7 @@ nut_ctype_t *firstclient = NULL; /* default is to listen on all local interfaces */ static stype_t *firstaddr = NULL; -static int opt_af = AF_UNSPEC; +static int opt_af = AF_UNSPEC; typedef enum { DRIVER = 1, @@ -1224,30 +1228,37 @@ static void poll_reload(void) size_t maxalloc; #ifndef WIN32 + /* Not likely this would change, but refresh just in case */ ret = sysconf(_SC_OPEN_MAX); #else /* WIN32 */ ret = (long)MAXIMUM_WAIT_OBJECTS; #endif /* WIN32 */ - if ((intmax_t)ret < (intmax_t)maxconn) { + if (ret < 1) { + /* TOTHINK: Not fail, but use a conservative fallback number? */ fatalx(EXIT_FAILURE, + "System reported an absurd value %ld as maximum number of connections.\n" + "The server won't start until this problem is resolved.\n", ret); + } + + if ((intmax_t)ret < (intmax_t)maxconn) { + upslogx(LOG_WARNING, "Your system limits the maximum number of connections to %ld\n" - "but you requested %" PRIdMAX ". The server won't start until this\n" - "problem is resolved.\n", ret, (intmax_t)maxconn); + "but you requested %" PRIdMAX ". The server may handle connections\n" + "in smaller groups, maybe affecting efficiency and response time.\n", + ret, (intmax_t)maxconn); } + sysmaxconn = (nfds_t)ret; + if (1 > maxconn) { fatalx(EXIT_FAILURE, "You requested %" PRIdMAX " as maximum number of connections.\n" "The server won't start until this problem is resolved.\n", (intmax_t)maxconn); } -#ifndef WIN32 /* How many items can we stuff into the array? */ maxalloc = SIZE_MAX / sizeof(void *); -#else /* WIN32 */ - maxalloc = MAXIMUM_WAIT_OBJECTS; -#endif /* WIN32 */ if ((uintmax_t)maxalloc < (uintmax_t)maxconn) { fatalx(EXIT_FAILURE, "You requested %" PRIdMAX " as maximum number of connections, but we can only allocate %" PRIuSIZE ".\n" @@ -1497,14 +1508,15 @@ static void mainloop(void) nfds_t i; #else /* WIN32 */ DWORD ret; - pipe_conn_t * conn; + pipe_conn_t *conn; + size_t chunk = 0; #endif /* WIN32 */ size_t nfds_wanted = 0, /* Connections we looked at (some may be invalid) */ nfds_considered = 0; /* Connections we wanted to poll (but might be over maxconn limit) */ nfds_t nfds = 0; upstype_t *ups; - nut_ctype_t *client, *cnext; + nut_ctype_t *client, *cnext; stype_t *server; time_t now; @@ -1644,18 +1656,53 @@ static void mainloop(void) upsdebugx(2, "%s: polling %" PRIdMAX " filedescriptors; some stats: " "considered %" PRIdMAX " connections, " "wanted to actually poll %" PRIdMAX - " and was constrained by maxconn=%" PRIdMAX, + " and was constrained by maxconn=%" PRIdMAX + " and chunked by sysmaxconn=%" PRIdMAX, __func__, (intmax_t)nfds, (intmax_t)nfds_considered, - (intmax_t)nfds_wanted, (intmax_t)maxconn); + (intmax_t)nfds_wanted, (intmax_t)maxconn, (intmax_t)sysmaxconn); if (nfds_wanted != nfds || nfds_wanted >= maxconn) { upslogx(LOG_ERR, "upsd polling %" PRIdMAX " filedescriptors," " but wanted to poll %" PRIdMAX - " and was constrained by maxconn=%" PRIdMAX, + " and was constrained by maxconn=%" PRIdMAX + " (see upsd.conf MAXCONN setting to adjust)", (intmax_t)nfds, (intmax_t)nfds_wanted, (intmax_t)maxconn); } - ret = poll(fds, nfds, 2000); + if (nfds <= sysmaxconn) { + ret = poll(fds, nfds, 2000); + } else { + /* Chunk it all; try to fit into same 2 sec as above. + * Note that nfds at the moment may be smaller than + * maxconn (allocated array size). + */ + size_t last_chunk = nfds % sysmaxconn, chunk, + chunks = nfds / sysmaxconn + (last_chunk ? 1 : 0); + int poll_TO = 2000 / chunks, tmpret; + + if (poll_TO < 10) + poll_TO = 10; + + ret = 0; + for (chunk = 0; chunk < chunks; chunk++) { + upsdebugx(5, + "%s: chunked filedescriptor polling #%" PRIuSIZE + " of %" PRIuSIZE " chunks, with %d hits so far", + __func__, chunk, chunks, ret); + tmpret = poll(&fds[chunk * sysmaxconn], + (last_chunk && chunk == chunks - 1 ? last_chunk : sysmaxconn), + poll_TO); + if (tmpret < 0) { + upsdebug_with_errno(2, + "%s: failed during chunked polling, handled %" PRIuSIZE + " of %" PRIuSIZE " chunks so far, with %d hits", + __func__, chunk, chunks, ret); + ret = tmpret; + break; + } + ret += tmpret; + } + } if (ret == 0) { upsdebugx(2, "%s: no data available", __func__); @@ -1942,19 +1989,53 @@ static void mainloop(void) upsdebugx(2, "%s: wait for %" PRIdMAX " filedescriptors; some stats: " "considered %" PRIdMAX " connections, " "wanted to actually poll %" PRIdMAX - " and was constrained by maxconn=%" PRIdMAX, + " and was constrained by maxconn=%" PRIdMAX + " and chunked by sysmaxconn=%" PRIdMAX, __func__, (intmax_t)nfds, (intmax_t)nfds_considered, - (intmax_t)nfds_wanted, (intmax_t)maxconn); + (intmax_t)nfds_wanted, (intmax_t)maxconn, (intmax_t)sysmaxconn); if (nfds_wanted != nfds || nfds_wanted >= maxconn) { upslogx(LOG_ERR, "upsd polling %" PRIuMAX " filedescriptors," " but wanted to poll %" PRIuMAX - " and was constrained by maxconn=%" PRIuMAX, + " and was constrained by maxconn=%" PRIuMAX + " (see upsd.conf MAXCONN setting to adjust)", (uintmax_t)nfds, (uintmax_t)nfds_wanted, (uintmax_t)maxconn); } - /* https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitformultipleobjects */ - ret = WaitForMultipleObjects(nfds,fds,FALSE,2000); + /* https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitformultipleobjects + * We handle whoever lights up first, one per loop cycle. + */ + chunk = 0; + if (nfds <= sysmaxconn) { + ret = WaitForMultipleObjects(nfds, fds, FALSE, 2000); + } else { + /* Chunk it all; try to fit into same 2 sec as above. + * Note that nfds at the moment may be smaller than + * maxconn (allocated array size). + */ + size_t last_chunk = nfds % sysmaxconn, + chunks = nfds / sysmaxconn + (last_chunk ? 1 : 0); + DWORD poll_TO = 2000 / chunks, tmpret; + + if (poll_TO < 10) + poll_TO = 10; + + ret = WAIT_TIMEOUT; + for (chunk = 0; chunk < chunks; chunk++) { + upsdebugx(5, + "%s: chunked filedescriptor polling #%" PRIuSIZE + " of %" PRIuSIZE " chunks, with %" PRIu64 " hits so far", + __func__, chunk, chunks, ret); + tmpret = WaitForMultipleObjects( + (last_chunk && chunk == chunks - 1 ? last_chunk : sysmaxconn), + &fds[chunk * sysmaxconn], + FALSE, poll_TO); + if (tmpret != WAIT_TIMEOUT) { + ret = tmpret; + break; + } + } + } upsdebugx(6, "%s: wait for filedescriptors done: %" PRIu64, __func__, ret); @@ -1981,7 +2062,7 @@ static void mainloop(void) #ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE # pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare" #endif - if (ret >= WAIT_ABANDONED_0 && ret <= WAIT_ABANDONED_0 + nfds - 1) { + if (ret >= WAIT_ABANDONED_0 && ret <= WAIT_ABANDONED_0 + (nfds < sysmaxconn ? nfds : sysmaxconn) - 1) { /* One abandoned mutex object that satisfied the wait? */ ret = ret - WAIT_ABANDONED_0; upsdebugx(5, "%s: got abandoned FD array item: %" PRIu64, __func__, nfds, ret); @@ -1991,7 +2072,7 @@ static void mainloop(void) /* Which one handle was triggered this time? */ /* Note: WAIT_OBJECT_0 may be currently defined as 0, * but docs insist on checking and shifting the range */ - ret = ret - WAIT_OBJECT_0; + ret = ret - WAIT_OBJECT_0 + chunk * sysmaxconn; upsdebugx(5, "%s: got event on FD array item: %" PRIu64, __func__, nfds, ret); } #if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) ) @@ -2150,6 +2231,7 @@ void check_perms(const char *fn) int main(int argc, char **argv) { int i, cmdret = 0, foreground = -1; + long l; #ifndef WIN32 int cmd = 0; pid_t oldpid = -1; @@ -2284,14 +2366,14 @@ int main(int argc, char **argv) } { /* scoping */ - char *s = getenv("NUT_DEBUG_LEVEL"); - int l; - if (s && str_to_int(s, &l, 10)) { - if (l > 0 && nut_debug_level_args < 1) { + char *s = getenv("NUT_DEBUG_LEVEL"); + int lvl; + if (s && str_to_int(s, &lvl, 10)) { + if (lvl > 0 && nut_debug_level_args < 1) { upslogx(LOG_INFO, "Defaulting debug verbosity to NUT_DEBUG_LEVEL=%d " - "since none was requested by command-line options", l); - nut_debug_level = l; - nut_debug_level_args = l; + "since none was requested by command-line options", lvl); + nut_debug_level = lvl; + nut_debug_level_args = lvl; } /* else follow -D settings */ } /* else nothing to bother about */ } @@ -2447,12 +2529,21 @@ int main(int argc, char **argv) #ifndef WIN32 /* default to system limit (may be overridden in upsd.conf) */ /* FIXME: Check for overflows (and int size of nfds_t vs. long) - see get_max_pid_t() for example */ - maxconn = (nfds_t)sysconf(_SC_OPEN_MAX); + l = sysconf(_SC_OPEN_MAX); #else /* WIN32 */ /* hard-coded 64 (from ddk/wdm.h or winnt.h) */ - maxconn = MAXIMUM_WAIT_OBJECTS; + l = (long)MAXIMUM_WAIT_OBJECTS; #endif /* WIN32 */ + if (l < 1) { + /* TOTHINK: Not fail, but use a conservative fallback number? */ + fatalx(EXIT_FAILURE, + "System reported an absurd value %ld as maximum number of connections.\n" + "The server won't start until this problem is resolved.\n", l); + } + + maxconn = sysmaxconn = (nfds_t)l; + /* handle upsd.conf */ load_upsdconf(0); /* 0 = initial */ From 7cca1ccd432cad7d1dec043fb547644e808684b4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 6 Feb 2026 16:34:36 +0100 Subject: [PATCH 155/198] clients/upsstats.c, docs/man/upsstats.cgi.txt, NEWS.adoc: support providing CGI options for alternate template file names (co-located with original ones) [#2524, #3304] Signed-off-by: Jim Klimov --- NEWS.adoc | 2 + clients/upsstats.c | 79 +++++++++++++++++++++++++++++++++++---- docs/man/upsstats.cgi.txt | 5 +++ 3 files changed, 79 insertions(+), 7 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index b618b57d3c..2b1d469ff4 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -338,6 +338,8 @@ several `FSD` notifications into one executed action. [PR #3097] * Introduced a `@NUT_UPSSTATS_TEMPLATE@` command which the HTML template files now MUST start with (safety check that we are reading a template). [issue #3252, PR #3249] + * (Experimental) Custom templates other than `upsstats{,-single}.html` can + now be specified as CGI parameters. [issue #2524, PR #3304] - `upssched` tool updates: * Previously in PR #2896 (NUT releases v2.8.3 and v2.8.4) the `UPSNAME` and diff --git a/clients/upsstats.c b/clients/upsstats.c index b7610ba42e..fefec01ff5 100644 --- a/clients/upsstats.c +++ b/clients/upsstats.c @@ -63,9 +63,8 @@ static char *monhostdesc = NULL; static uint16_t port; static char *upsname, *hostname; -static char *upsimgpath="upsimage.cgi" EXEEXT, *upsstatpath="upsstats.cgi" EXEEXT, - *template_single = "upsstats-single.html", - *template_list = "upsstats.html"; +static char *upsimgpath = "upsimage.cgi" EXEEXT, *upsstatpath = "upsstats.cgi" EXEEXT, + *template_single = NULL, *template_list = NULL; static UPSCONN_t ups; static FILE *tf; @@ -102,6 +101,18 @@ void parsearg(char *var, char *value) output_json = 1; } + if (!strcmp(var, "template_single")) { + /* Error-checking in display_template(), when we have all options in place */ + free(template_single); + template_single = xstrdup(value); + } + + if (!strcmp(var, "template_list")) { + /* Error-checking in display_template(), when we have all options in place */ + free(template_list); + template_list = xstrdup(value); + } + upsdebug_call_finished0(); } @@ -529,6 +540,14 @@ static void do_hostlink(void) printf("sys); + if (strcmp(template_single, "upsstats-single.html")) { + printf("&template_single=%s", template_single); + } + + if (strcmp(template_list, "upsstats.html")) { + printf("&template_list=%s", template_list); + } + if (refreshdelay > 0) { printf("&refresh=%d", refreshdelay); } @@ -546,8 +565,22 @@ static void do_treelink_json(const char *text) return; } - printf("%s", - upsstatpath, currups->sys, + printf("sys); + + if (strcmp(template_single, "upsstats-single.html")) { + printf("&template_single=%s", template_single); + } + + if (strcmp(template_list, "upsstats.html")) { + printf("&template_list=%s", template_list); + } + + if (refreshdelay > 0) { + printf("&refresh=%d", refreshdelay); + } + + printf("\">%s", ((text && *text) ? text : "JSON")); upsdebug_call_finished0(); @@ -562,8 +595,22 @@ static void do_treelink(const char *text) return; } - printf("%s", - upsstatpath, currups->sys, + printf("sys); + + if (strcmp(template_single, "upsstats-single.html")) { + printf("&template_single=%s", template_single); + } + + if (strcmp(template_list, "upsstats.html")) { + printf("&template_list=%s", template_list); + } + + if (refreshdelay > 0) { + printf("&refresh=%d", refreshdelay); + } + + printf("\">%s", ((text && *text) ? text : "All data")); upsdebug_call_finished0(); @@ -1096,6 +1143,16 @@ static void display_template(const char *tfn) upsdebug_call_starting_for_str1(tfn); + if (!tfn || !*tfn || strstr(tfn, "/") || strstr(tfn, "\\") || !strstr(tfn, ".htm")) { + /* We only allow pre-configured templates in one managed location, with ".htm" in the name */ + fprintf(stderr, "upsstats: Can't open %s: %s: asked to look not exactly in the managed location\n", fn, strerror(errno)); + + printf("Error: can't open template file (%s): asked to look not exactly in the managed location\n", tfn); + + upsdebug_call_finished1(": subdir in template"); + exit(EXIT_FAILURE); + } + snprintf(fn, sizeof(fn), "%s/%s", confpath(), tfn); tf = fopen(fn, "rb"); @@ -1519,6 +1576,10 @@ int main(int argc, char **argv) nut_debug_level = i; } + /* Built-in defaults */ + template_single = xstrdup("upsstats-single.html"); + template_list = xstrdup("upsstats.html"); + extractcgiargs(); upscli_init_default_connect_timeout(NULL, NULL, UPSCLI_DEFAULT_CONNECT_TIMEOUT); @@ -1544,6 +1605,8 @@ int main(int argc, char **argv) } free(upsname); free(hostname); + free(template_single); + free(template_list); exit(EXIT_SUCCESS); } @@ -1576,6 +1639,8 @@ int main(int argc, char **argv) free(ulhead); ulhead = currups; } + free(template_single); + free(template_list); return 0; } diff --git a/docs/man/upsstats.cgi.txt b/docs/man/upsstats.cgi.txt index b83fca8c13..5665e28560 100644 --- a/docs/man/upsstats.cgi.txt +++ b/docs/man/upsstats.cgi.txt @@ -48,9 +48,14 @@ The web page that is displayed is actually a template containing commands to `upsstats` which are replaced by status information. The default file used for the overview of devices is `upsstats.html`. +An alternate template may be provided by `&template_list=...` CGI query option. When monitoring a single UPS, the file displayed is `upsstats-single.html`. +An alternate template may be provided by `&template_single=...` CGI query option. + +Alternate templates must be structured similarly to default ones, located in the +same directory, and contain `.htm` in the file name. The format of these files, including the possible commands, is documented in linkman:upsstats.html[5]. From 53cb321b4264f9a14e60d63651b5927f35b9baf0 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 8 Feb 2026 05:34:37 +0100 Subject: [PATCH 156/198] drivers/upsdrvctl.c: forkexec(): double-quote the WIN32 argv[0] in commandline [#3294, #3305] Closes: #3305 Signed-off-by: Jim Klimov --- drivers/upsdrvctl.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index 475d4a6d49..8b1ee9a9db 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -952,8 +952,11 @@ static void forkexec(char *const argv[], const ups_t *ups) /* the command line is made of the driver name followed by args */ 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]); + /* We already know whom to call (got a pointer + * to needle in the haystack); that path may + * have spaces ("Program Files") so quoted. + */ + 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 @@ -966,6 +969,7 @@ static void forkexec(char *const argv[], const ups_t *ups) } while (argv[i] != NULL) { + /* TOTHINK: No known toxic spaces to quote here... */ snprintfcat(commandline, sizeof(commandline), " %s", argv[i]); i++; } From 60bd71326b3556c15653b96736fa3574949cedb2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 8 Feb 2026 05:34:37 +0100 Subject: [PATCH 157/198] drivers/upsdrvctl.c: forkexec(): double-quote the WIN32 argv[0] in commandline [#3294, #3305] Closes: #3305 Signed-off-by: Jim Klimov --- drivers/upsdrvctl.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index 475d4a6d49..8b1ee9a9db 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -952,8 +952,11 @@ static void forkexec(char *const argv[], const ups_t *ups) /* the command line is made of the driver name followed by args */ 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]); + /* We already know whom to call (got a pointer + * to needle in the haystack); that path may + * have spaces ("Program Files") so quoted. + */ + 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 @@ -966,6 +969,7 @@ static void forkexec(char *const argv[], const ups_t *ups) } while (argv[i] != NULL) { + /* TOTHINK: No known toxic spaces to quote here... */ snprintfcat(commandline, sizeof(commandline), " %s", argv[i]); i++; } From 3d083927688301102efdfb6aa6013abfab3cf169 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 8 Feb 2026 07:24:03 +0100 Subject: [PATCH 158/198] common/common.c: vupslog(): use a larger initial buffer Signed-off-by: Jim Klimov --- common/common.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/common.c b/common/common.c index 50803b25f4..b74c039a74 100644 --- a/common/common.c +++ b/common/common.c @@ -3768,7 +3768,8 @@ static void vupslog(int priority, const char *fmt, va_list va, int use_strerror) { int ret, errno_orig = errno; #ifdef HAVE_VA_COPY_VARIANT - size_t bufsize = 128; + /* Most our debug messages fit into this */ + size_t bufsize = 256; #else /* err on the safe(r) side, as re-runs can truncate * the output when varargs are re-used */ From 9879eb79807a672fd702c9c9be60a441aa07c320 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 8 Feb 2026 07:47:39 +0100 Subject: [PATCH 159/198] server/upsd.c: refactor with one update_sysmaxconn() implementation [#3302] Signed-off-by: Jim Klimov --- server/upsd.c | 65 ++++++++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/server/upsd.c b/server/upsd.c index 363ec5c5e0..de4b8d6e30 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -1222,35 +1222,52 @@ static void upsd_cleanup(void) upsdebugx(1, "%s: finished", __func__); } -static void poll_reload(void) +static void update_sysmaxconn(void) { - long ret; - size_t maxalloc; + long l; #ifndef WIN32 - /* Not likely this would change, but refresh just in case */ - ret = sysconf(_SC_OPEN_MAX); + /* default to system limit (may be overridden in upsd.conf) */ + /* FIXME: Check for overflows (and int size of nfds_t vs. long) - see get_max_pid_t() for example */ + l = sysconf(_SC_OPEN_MAX); #else /* WIN32 */ - ret = (long)MAXIMUM_WAIT_OBJECTS; + /* hard-coded 64 (from ddk/wdm.h or winnt.h) */ + l = (long)MAXIMUM_WAIT_OBJECTS; #endif /* WIN32 */ - if (ret < 1) { - /* TOTHINK: Not fail, but use a conservative fallback number? */ + if (l < 1) { + /* TOTHINK: Not fail, but use a conservative fallback number? + * Can we trust the OS to support any? + */ fatalx(EXIT_FAILURE, "System reported an absurd value %ld as maximum number of connections.\n" - "The server won't start until this problem is resolved.\n", ret); + "The server won't start until this problem is resolved.\n", + l); } - if ((intmax_t)ret < (intmax_t)maxconn) { + /* TOTHINK: envvar for NIT or similar tests? + * Still do not exceed what the OS said. + * Note this historically also serves as + * the initial/default MAXCONN setting. + */ + sysmaxconn = (nfds_t)l; +} + +static void poll_reload(void) +{ + size_t maxalloc; + + /* Not likely this would change, but refresh just in case */ + update_sysmaxconn(); + + if ((intmax_t)sysmaxconn < (intmax_t)maxconn) { upslogx(LOG_WARNING, - "Your system limits the maximum number of connections to %ld\n" + "Your system limits the maximum number of connections to %" PRIdMAX "\n" "but you requested %" PRIdMAX ". The server may handle connections\n" "in smaller groups, maybe affecting efficiency and response time.\n", - ret, (intmax_t)maxconn); + (intmax_t)sysmaxconn, (intmax_t)maxconn); } - sysmaxconn = (nfds_t)ret; - if (1 > maxconn) { fatalx(EXIT_FAILURE, "You requested %" PRIdMAX " as maximum number of connections.\n" @@ -2231,7 +2248,6 @@ void check_perms(const char *fn) int main(int argc, char **argv) { int i, cmdret = 0, foreground = -1; - long l; #ifndef WIN32 int cmd = 0; pid_t oldpid = -1; @@ -2526,23 +2542,8 @@ int main(int argc, char **argv) chroot_start(chroot_path); } -#ifndef WIN32 - /* default to system limit (may be overridden in upsd.conf) */ - /* FIXME: Check for overflows (and int size of nfds_t vs. long) - see get_max_pid_t() for example */ - l = sysconf(_SC_OPEN_MAX); -#else /* WIN32 */ - /* hard-coded 64 (from ddk/wdm.h or winnt.h) */ - l = (long)MAXIMUM_WAIT_OBJECTS; -#endif /* WIN32 */ - - if (l < 1) { - /* TOTHINK: Not fail, but use a conservative fallback number? */ - fatalx(EXIT_FAILURE, - "System reported an absurd value %ld as maximum number of connections.\n" - "The server won't start until this problem is resolved.\n", l); - } - - maxconn = sysmaxconn = (nfds_t)l; + update_sysmaxconn(); + maxconn = sysmaxconn; /* handle upsd.conf */ load_upsdconf(0); /* 0 = initial */ From 7d2d13ae3e59c93e01156d6edae5caed19104336 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 8 Feb 2026 07:48:24 +0100 Subject: [PATCH 160/198] server/upsd.c: mainloop(): debug-log chunking details [#3302] Signed-off-by: Jim Klimov --- server/upsd.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/server/upsd.c b/server/upsd.c index de4b8d6e30..efec5b04e6 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -1700,6 +1700,11 @@ static void mainloop(void) if (poll_TO < 10) poll_TO = 10; + upsdebugx(4, "%s: chunked filedescriptor polling via %" PRIuSIZE + " chunks, last one sized %" PRIuSIZE + ", with timeout of %d msec per chunk", + __func__, chunks, last_chunk, poll_TO); + ret = 0; for (chunk = 0; chunk < chunks; chunk++) { upsdebugx(5, @@ -2037,6 +2042,11 @@ static void mainloop(void) if (poll_TO < 10) poll_TO = 10; + upsdebugx(4, "%s: chunked filedescriptor polling via %" PRIuSIZE + " chunks, last one sized %" PRIuSIZE + ", with timeout of %" PRIi64 " msec per chunk", + __func__, chunks, last_chunk, poll_TO); + ret = WAIT_TIMEOUT; for (chunk = 0; chunk < chunks; chunk++) { upsdebugx(5, From 996b8706e842c0a990c80d7f5c690c38d10d512b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 8 Feb 2026 07:55:07 +0100 Subject: [PATCH 161/198] server/upsd.c: mainloop(): only log warnings if nfds_wanted > maxconn (equality should be ok) [#3302] Signed-off-by: Jim Klimov --- server/upsd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/upsd.c b/server/upsd.c index efec5b04e6..f0cdaa7e7d 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -1678,7 +1678,7 @@ static void mainloop(void) __func__, (intmax_t)nfds, (intmax_t)nfds_considered, (intmax_t)nfds_wanted, (intmax_t)maxconn, (intmax_t)sysmaxconn); - if (nfds_wanted != nfds || nfds_wanted >= maxconn) { + if (nfds_wanted != nfds || nfds_wanted > maxconn) { upslogx(LOG_ERR, "upsd polling %" PRIdMAX " filedescriptors," " but wanted to poll %" PRIdMAX " and was constrained by maxconn=%" PRIdMAX @@ -2016,7 +2016,7 @@ static void mainloop(void) __func__, (intmax_t)nfds, (intmax_t)nfds_considered, (intmax_t)nfds_wanted, (intmax_t)maxconn, (intmax_t)sysmaxconn); - if (nfds_wanted != nfds || nfds_wanted >= maxconn) { + if (nfds_wanted != nfds || nfds_wanted > maxconn) { upslogx(LOG_ERR, "upsd polling %" PRIuMAX " filedescriptors," " but wanted to poll %" PRIuMAX " and was constrained by maxconn=%" PRIuMAX From 4385bed3c4360c235526a5288f1b1050bc3a9b85 Mon Sep 17 00:00:00 2001 From: darkglade <35511291+darkglade@users.noreply.github.com> Date: Sun, 8 Feb 2026 19:13:32 +1100 Subject: [PATCH 162/198] Fix hang in gen-snmp-subdriver.sh Fix an issue introduced in commit 8b038f4 whereby grep-snmp-subdriver.sh hangs indefinitely. Issue https://github.com/networkupstools/nut/issues/3308 --- scripts/subdriver/gen-snmp-subdriver.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/subdriver/gen-snmp-subdriver.sh b/scripts/subdriver/gen-snmp-subdriver.sh index 17e3e3474e..602aa716a5 100755 --- a/scripts/subdriver/gen-snmp-subdriver.sh +++ b/scripts/subdriver/gen-snmp-subdriver.sh @@ -487,8 +487,8 @@ done # remove blank and "End of MIB" lines TABCHAR="`printf '\t'`" -${EGREP} "^[ ${TABCHAR}]?\$" | ${GREP} "End of MIB" | ${GREP} -v "${NUMWALKFILE}" > "${TMP_NUMWALKFILE}" -${EGREP} "^[ ${TABCHAR}]?\$" | ${GREP} "End of MIB" | ${GREP} -v "${STRWALKFILE}" > "${TMP_STRWALKFILE}" +${EGREP} -v "^[ ${TABCHAR}]?\$" "${NUMWALKFILE}" | ${GREP} -v "End of MIB" > "${TMP_NUMWALKFILE}" +${EGREP} -v "^[ ${TABCHAR}]?\$" "${STRWALKFILE}" | ${GREP} -v "End of MIB" > "${TMP_STRWALKFILE}" NUMWALKFILE="${TMP_NUMWALKFILE}" STRWALKFILE="${TMP_STRWALKFILE}" From 97eb3b1ed0fbaacb2d9d305bd8790de89b814476 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 8 Feb 2026 08:33:28 +0100 Subject: [PATCH 163/198] server/upsd.c, NEWS.adoc, docs/nut.dict: update_sysmaxconn(): support NUT_SYSMAXCONN_LIMIT envvar to tweak [#3302] Signed-off-by: Jim Klimov --- NEWS.adoc | 4 +++- docs/nut.dict | 3 ++- server/upsd.c | 28 +++++++++++++++++++++++----- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index 1ecbd6662c..88bc6a04a9 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -288,7 +288,9 @@ https://github.com/networkupstools/nut/milestone/12 [PR #3237] * Extended processing of `MAXCONN` setting to allow larger values than the operating system allows, by only waiting for that amount of Unix sockets - or Windows `HANDLE`'s at a time, and moving on to another chunk. [#3302] + or Windows `HANDLE`'s at a time, and moving on to another chunk. + The system-provided value can be further limited by `NUT_SYSMAXCONN_LIMIT` + environment variable (e.g. in tests). [#3302] - `upsdrvctl` tool updates: * Make use of `setproctag()` and `getproctag()` to report parent/child diff --git a/docs/nut.dict b/docs/nut.dict index a88fe53d6d..3a904cb3b6 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3655 utf-8 +personal_ws-1.1 en 3656 utf-8 AAC AAS ABI @@ -1241,6 +1241,7 @@ SX SXI SXL SYMLINKDIR +SYSMAXCONN SafeNet Salicru Salvia diff --git a/server/upsd.c b/server/upsd.c index f0cdaa7e7d..fd82500f75 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -1225,6 +1225,7 @@ static void upsd_cleanup(void) static void update_sysmaxconn(void) { long l; + char *s = getenv("NUT_SYSMAXCONN_LIMIT"); #ifndef WIN32 /* default to system limit (may be overridden in upsd.conf) */ @@ -1245,12 +1246,29 @@ static void update_sysmaxconn(void) l); } - /* TOTHINK: envvar for NIT or similar tests? - * Still do not exceed what the OS said. - * Note this historically also serves as - * the initial/default MAXCONN setting. + /* Note this historically also serves as + * the initial/default MAXCONN setting + * (so site/platform-dependent). */ sysmaxconn = (nfds_t)l; + if (maxconn < 1) { + upsdebugx(1, "%s: defaulting maxconn to sysmaxconn: %ld", + __func__, l); + maxconn = sysmaxconn; + } + + /* Support envvar for NIT or similar tests. + * Still do not exceed what the OS said. + */ + if (s && str_to_long(s, &l, 10)) { + if (l > 0 && (nfds_t)l < sysmaxconn) { + upslogx(LOG_INFO, "Adjusting sysmaxconn according to NUT_SYSMAXCONN_LIMIT envvar: %ld", l); + sysmaxconn = (nfds_t)l; + } else { + upslogx(LOG_WARNING, "Adjusting sysmaxconn according to NUT_SYSMAXCONN_LIMIT envvar failed: %ld is out of range. Keeping OS-provided %ld.", + l, (long)sysmaxconn); + } + } /* else nothing to bother about */ } static void poll_reload(void) @@ -2552,8 +2570,8 @@ int main(int argc, char **argv) chroot_start(chroot_path); } + /* Also initializes maxconn to what the OS says */ update_sysmaxconn(); - maxconn = sysmaxconn; /* handle upsd.conf */ load_upsdconf(0); /* 0 = initial */ From 6a7cd03be0eb457944d333383dba0612a64c2192 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 8 Feb 2026 13:48:25 +0100 Subject: [PATCH 164/198] tools/nut-scanner/scan_upower.c: drop unused import of "g_variant_get()" [#3293] Signed-off-by: Jim Klimov --- tools/nut-scanner/scan_upower.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tools/nut-scanner/scan_upower.c b/tools/nut-scanner/scan_upower.c index 3f623ef5a8..3866ad30bd 100644 --- a/tools/nut-scanner/scan_upower.c +++ b/tools/nut-scanner/scan_upower.c @@ -47,7 +47,6 @@ static GDBusConnection * (*nut_g_bus_get_sync)(GBusType bus_type, GCancellable * static GDBusProxy * (*nut_g_dbus_proxy_new_sync)(GDBusConnection *connection, GDBusProxyFlags flags, GDBusInterfaceInfo *info, const gchar *name, const gchar *object_path, const gchar *interface_name, GCancellable *cancellable, GError **error); static GVariant * (*nut_g_dbus_proxy_call_sync)(GDBusProxy *proxy, const gchar *method_name, GVariant *parameters, GDBusCallFlags flags, gint timeout_msec, GCancellable *cancellable, GError **error); static GVariant * (*nut_g_dbus_proxy_get_cached_property)(GDBusProxy *proxy, const gchar *property_name); -static void (*nut_g_variant_get)(GVariant *value, const gchar *format_string, ...); static void (*nut_g_variant_unref)(GVariant *value); static void (*nut_g_object_unref)(gpointer object); static void (*nut_g_error_free)(GError *error); @@ -110,9 +109,6 @@ int nutscan_load_upower_library(const char *libname_path) *(void **) (&nut_g_dbus_proxy_get_cached_property) = lt_dlsym(dl_handle, "g_dbus_proxy_get_cached_property"); if ((dl_error = lt_dlerror()) != NULL) goto err; - *(void **) (&nut_g_variant_get) = lt_dlsym(dl_handle, "g_variant_get"); - if ((dl_error = lt_dlerror()) != NULL) goto err; - *(void **) (&nut_g_variant_unref) = lt_dlsym(dl_handle, "g_variant_unref"); if ((dl_error = lt_dlerror()) != NULL) goto err; From 54c9e42a5e597a12f9f0cdb6c7caff7d6715f9a4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 8 Feb 2026 17:50:57 +0000 Subject: [PATCH 165/198] scripts/augeas/gen-nutupsconf-aug.py.in: try to actually catch warnings (e.g. DeprecationWarning) to use correct form of open() [#3256] Signed-off-by: Jim Klimov --- scripts/augeas/gen-nutupsconf-aug.py.in | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/scripts/augeas/gen-nutupsconf-aug.py.in b/scripts/augeas/gen-nutupsconf-aug.py.in index 29fa19c15d..f2c51a8e56 100755 --- a/scripts/augeas/gen-nutupsconf-aug.py.in +++ b/scripts/augeas/gen-nutupsconf-aug.py.in @@ -27,6 +27,15 @@ import os import re import glob +HAVE_WARNINGS = False +try: + import warnings + warnings.filterwarnings("error") + HAVE_WARNINGS = True +except Exception as x: + # sys.stderr.write("WARNING: failed to import warnings or configure them: %s" % str(x)) + pass + try: # NOTE: Deprecated as of python3.14 import codecs @@ -47,6 +56,9 @@ except Exception as x: HAVE_CODECS = False USE_CODECS = False +if HAVE_WARNINGS: + warnings.resetwarnings() + # Return a sorted list of unique entries, based on the input 'list' def sortUnique(list): newVarList = [] From 9dd88ff7f40ce32ee742a938fba43c08d701bd0b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 8 Feb 2026 17:51:33 +0000 Subject: [PATCH 166/198] scripts/augeas/gen-nutupsconf-aug.py.in: fix ResourceWarnings about unclosed file descriptors [#3256] Signed-off-by: Jim Klimov --- scripts/augeas/gen-nutupsconf-aug.py.in | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/augeas/gen-nutupsconf-aug.py.in b/scripts/augeas/gen-nutupsconf-aug.py.in index f2c51a8e56..5aa3c1c4e8 100755 --- a/scripts/augeas/gen-nutupsconf-aug.py.in +++ b/scripts/augeas/gen-nutupsconf-aug.py.in @@ -141,9 +141,11 @@ if __name__ == '__main__': defRow = re.findall(r'"([^"]*)",?', varDefine) if (len(defRow) == 1): variableNames.append(defRow[0]) + defFd.close() else: # Remove quotes variableNames.append(row[1].replace('"', '').lstrip()) + fd.close() # Filter multiply defined variables variableNames = sortUnique(variableNames) @@ -160,6 +162,7 @@ if __name__ == '__main__': # 2.1/ Search for the pattern to replace outputText = tplFd.read() + tplFd.close() outputText = outputText.replace('@SPECIFIC_DRV_VARS@', specificVars) # 3/ Output final lens @@ -168,3 +171,4 @@ if __name__ == '__main__': else: outFd = open(outputFilename, mode='w', encoding='utf-8') outFd.write(outputText) + outFd.close() From b05fb12eee065fb38e59c31599f465614c3c175e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 8 Feb 2026 17:55:33 +0000 Subject: [PATCH 167/198] scripts/python/module/setup.py.in: try to actually catch warnings (e.g. DeprecationWarning) to use correct form of open() [#3256] Signed-off-by: Jim Klimov --- scripts/python/module/setup.py.in | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/scripts/python/module/setup.py.in b/scripts/python/module/setup.py.in index 098e2d43b4..51383d1593 100644 --- a/scripts/python/module/setup.py.in +++ b/scripts/python/module/setup.py.in @@ -10,6 +10,15 @@ import sys here = os.path.abspath(os.path.dirname(__file__)) +HAVE_WARNINGS = False +try: + import warnings + warnings.filterwarnings("error") + HAVE_WARNINGS = True +except Exception as x: + # sys.stderr.write("WARNING: failed to import warnings or configure them: %s" % str(x)) + pass + try: # NOTE: Deprecated as of python3.14 import codecs @@ -30,6 +39,9 @@ except Exception as x: HAVE_CODECS = False USE_CODECS = False +if HAVE_WARNINGS: + warnings.resetwarnings() + # README.txt appears from README.adoc during package or CI build if USE_CODECS: with codecs.open(os.path.join(here, "README.txt"), encoding="utf-8") as fh: From 34f15d9ae138c7d0880632f32790979a833f5d68 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 8 Feb 2026 18:13:25 +0000 Subject: [PATCH 168/198] docs/config-prereqs.txt, docs/nut.dict: update for Fedora 43 [#3311] Signed-off-by: Jim Klimov --- docs/config-prereqs.txt | 60 ++++++++++++++++++++++++++++++++++------- docs/nut.dict | 6 ++++- 2 files changed, 56 insertions(+), 10 deletions(-) diff --git a/docs/config-prereqs.txt b/docs/config-prereqs.txt index 1333939aed..b4adb9d96f 100644 --- a/docs/config-prereqs.txt +++ b/docs/config-prereqs.txt @@ -313,16 +313,21 @@ NOTE: For Jenkins agents, also need to `apt-get install openjdk-21-jdk-headless` You may have to ensure that `/proc` is mounted in the target chroot (or do this from the running container). -CentOS 6 and 7 -~~~~~~~~~~~~~~ +CentOS 6 and 7, Fedora 43 +~~~~~~~~~~~~~~~~~~~~~~~~~ CentOS is another popular baseline among Linux distributions, being a free derivative of the RedHat Linux, upon which many other distros are based as well. These systems typically use the RPM package manager, using directly `rpm` command, or `yum` or `dnf` front-ends depending on their generation. +In fact, most of the instructions directly apply to much newer distributions +like Fedora 43. + For CI farm container setup, prepared root filesystem archives from http://download.proxmox.com/images/system/ worked sufficiently well. +For Fedora, https://images.linuxcontainers.org/images/fedora/43/amd64/default +nightly image was used. Prepare CentOS repository mirrors ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -388,6 +393,7 @@ enable it: :; yum install \ openssh-server openssh-clients +# On CentOS 6/7: :; chkconfig sshd on :; service sshd start @@ -400,8 +406,8 @@ NOTE: Below we request to install generic `python` per system defaults. You may request specifically `python2` or `python3` (or both): current NUT should be compatible with both (2.7+ at least). -NOTE: On CentOS, `libusb` means 0.1.x and `libusbx` means 1.x.x API version -(latter is not available for CentOS 6). +NOTE: On CentOS, `libusb` means 0.1.x (not available on modern Fedora), +and `libusbx` means 1.x.x API version (latter is not available for CentOS 6). NOTE: On CentOS, it seems that development against libi2c/smbus is not supported. Neither the suitable devel packages were found, nor i2c-based @@ -435,6 +441,8 @@ drivers in distro packaging of NUT. Resolution and doc PRs are welcome. # You can find a list of what is (pre-)installed with: # :; rpm -qa | grep -Ei 'perl|python' # Note that CentOS 6 includes python-2.6.x and does not serve newer versions +# For Fedora 43, further packages can be installed to test more: +# :; yum install python3-qt5 python3-setuptools # For spell-checking, highly recommended if you would propose pull requests: :; yum install \ @@ -445,6 +453,10 @@ drivers in distro packaging of NUT. Resolution and doc PRs are welcome. :; yum install \ asciidoc source-highlight python-pygments dblatex +# For PDF generation, you may need explicitly (at least on Fedora 43): +:; yum install \ + texlive 'tex(upquote.sty)' + # For CGI graph generation - massive packages (X11): :; yum install \ gd-devel @@ -454,20 +466,30 @@ drivers in distro packaging of NUT. Resolution and doc PRs are welcome. systemd-devel # NOTE: "libusbx" is the CentOS way of naming "libusb-1.0" (not in CentOS 6) -# vs. the older "libusb" as the package with "libusb-0.1" +# vs. the older "libusb" as the package with "libusb-0.1" (not in recent Fedora) +:; yum install \ + libusb-devel + +:; yum install \ + libusbx-devel + :; yum install \ cppunit-devel \ openssl-devel nss-devel \ augeas augeas-devel \ - libusb-devel libusbx-devel \ glib2-devel \ i2c-tools \ libmodbus-devel \ net-snmp-devel \ - powerman-devel \ freeipmi-devel \ avahi-devel \ neon-devel + +# Not in recent Fedora releases: +:; yum install \ + powerman-devel + +# Not in CentOS, some present in Fedora: #?# is python-augeas needed? exists at least... #?# no (lib)i2c-devel ... #?# no (lib)ipmimonitoring-devel ... would "freeipmi-ipmidetectd" @@ -475,6 +497,11 @@ drivers in distro packaging of NUT. Resolution and doc PRs are welcome. #?# no (lib)gpio(d)-devel - starts with CentOS 8 (or extra repositories #?# for later minor releases of CentOS 7) +# In Fedora: +:; yum install \ + libi2c-devel \ + libgpiod-devel + # Some NUT code related to lua may be currently limited to lua-5.1 # or possibly 5.2; the former is default in CentOS 7 releases... :; yum install \ @@ -482,6 +509,14 @@ drivers in distro packaging of NUT. Resolution and doc PRs are welcome. :; yum install \ bash dash ksh + +# If available: +:; yum install \ + bash-completion + +# In Fedora: +:; yum install \ + busybox ------ NOTE: `busybox` is not packaged for CentOS 7 release; a static binary can @@ -499,8 +534,15 @@ other described environments by adding a symlink `/usr/lib/ccache`: ====== For Jenkins agents, also need to install JDK 17 or newer, which is not available for CentOS 6 nor 7 directly (in distribution packaging). -Alternative packaging, such as Temurin from the Adoptium project, is possible -(checked for at least CentOS 7), see + +In Fedora e.g.: +------ +:; yum install \ + java-21-openjdk-headless +------ + +Alternative packaging for older distros, such as Temurin from the Adoptium +project, is possible (checked for at least CentOS 7), see link:https://adoptium.net/installation/linux/#_centosrhelfedora_instructions[their instructions] for specific details. This may require updated library package versions as dependencies from the OS distribution, so you may also have to make diff --git a/docs/nut.dict b/docs/nut.dict index a88fe53d6d..f71819d51d 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3655 utf-8 +personal_ws-1.1 en 3659 utf-8 AAC AAS ABI @@ -3137,6 +3137,7 @@ setproctag setq setuid setupCommands +setuptools setvar setvar's sfr @@ -3335,6 +3336,8 @@ testime testtime testuser testvar +tex +texlive textproc tgcware tgt @@ -3436,6 +3439,7 @@ unstash updateinfo upexia upower +upquote upsBypassCurrent upsBypassPower upsBypassVoltage From c7bd72ddeb72ecfaec1429de7f6da85f15f4fa88 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 8 Feb 2026 19:06:03 +0000 Subject: [PATCH 169/198] drivers/generic_gpio_common.c, drivers/generic_gpio_libgpiod.c, tests/generic_gpio_utest.c: fix more casting from xcalloc() et al [#3297] Signed-off-by: Jim Klimov --- drivers/generic_gpio_common.c | 12 ++++++------ drivers/generic_gpio_libgpiod.c | 6 +++--- tests/generic_gpio_utest.c | 10 +++++----- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/generic_gpio_common.c b/drivers/generic_gpio_common.c index a163f7784e..dc956e04f2 100644 --- a/drivers/generic_gpio_common.c +++ b/drivers/generic_gpio_common.c @@ -75,13 +75,13 @@ struct gpioups_t *generic_gpio_open(const char *chipName) { if (!rules) /* rules is required configuration parameter */ fatalx(EXIT_FAILURE, "UPS status calculation rules not specified"); - upsfdlocal = xcalloc(1, sizeof(*upsfdlocal)); + upsfdlocal = (struct gpioups_t *)xcalloc(1, sizeof(*upsfdlocal)); upsfdlocal->runOptions = 0; /* don't use ROPT_REQRES and ROPT_EVMODE yet */ upsfdlocal->chipName = chipName; get_ups_rules(upsfdlocal, (unsigned char *)rules); - upsfdlocal->upsLinesStates = xcalloc(upsfdlocal->upsLinesCount, sizeof(int)); + upsfdlocal->upsLinesStates = (int *)xcalloc(upsfdlocal->upsLinesCount, sizeof(int)); return upsfdlocal; } @@ -122,7 +122,7 @@ void add_rule_item(struct gpioups_t *upsfdlocal, int newValue) { int subCount = (upsfdlocal->rules[upsfdlocal->rulesCount - 1]) ? upsfdlocal->rules[upsfdlocal->rulesCount - 1]->subCount + 1 : 1; int itemSize = subCount * sizeof(upsfdlocal->rules[0]->cRules[0]) + sizeof(rulesint); - upsfdlocal->rules[upsfdlocal->rulesCount - 1] = xrealloc(upsfdlocal->rules[upsfdlocal->rulesCount - 1], itemSize); + upsfdlocal->rules[upsfdlocal->rulesCount - 1] = (struct rulesint_t *)xrealloc(upsfdlocal->rules[upsfdlocal->rulesCount - 1], itemSize); upsfdlocal->rules[upsfdlocal->rulesCount - 1]->subCount = subCount; upsfdlocal->rules[upsfdlocal->rulesCount - 1]->cRules[subCount - 1] = newValue; } @@ -197,8 +197,8 @@ void get_ups_rules(struct gpioups_t *upsfdlocal, unsigned char *rulesString) { } else { lexStatus = 1; upsfdlocal->rulesCount++; - upsfdlocal->rules = xrealloc(upsfdlocal->rules, (size_t)(sizeof(upsfdlocal->rules[0])*upsfdlocal->rulesCount)); - upsfdlocal->rules[upsfdlocal->rulesCount -1 ] = xcalloc(1, sizeof(rulesint)); + upsfdlocal->rules = (struct rulesint_t **)xrealloc(upsfdlocal->rules, (size_t)(sizeof(upsfdlocal->rules[0])*upsfdlocal->rulesCount)); + upsfdlocal->rules[upsfdlocal->rulesCount -1 ] = (struct rulesint_t *)xcalloc(1, sizeof(rulesint)); strncpy(upsfdlocal->rules[upsfdlocal->rulesCount - 1]->stateName, (char *)(rulesString + startPos), endPos - startPos); upsfdlocal->rules[upsfdlocal->rulesCount - 1]->stateName[endPos - startPos] = 0; } @@ -291,7 +291,7 @@ void get_ups_rules(struct gpioups_t *upsfdlocal, unsigned char *rulesString) { if (!pinOnList) { if (upsfdlocal->rules[i]->cRules[j] >= 0) { upsfdlocal->upsLinesCount++; - upsfdlocal->upsLines = xrealloc(upsfdlocal->upsLines, sizeof(upsfdlocal->upsLines[0])*upsfdlocal->upsLinesCount); + upsfdlocal->upsLines = (int *)xrealloc(upsfdlocal->upsLines, sizeof(upsfdlocal->upsLines[0])*upsfdlocal->upsLinesCount); upsfdlocal->upsLines[upsfdlocal->upsLinesCount - 1] = upsfdlocal->rules[i]->cRules[j]; if (upsfdlocal->upsLines[upsfdlocal->upsLinesCount - 1] > upsfdlocal->upsMaxLine) { upsfdlocal->upsMaxLine = upsfdlocal->upsLines[upsfdlocal->upsLinesCount - 1]; diff --git a/drivers/generic_gpio_libgpiod.c b/drivers/generic_gpio_libgpiod.c index 30c2dd806f..a9c923ed73 100644 --- a/drivers/generic_gpio_libgpiod.c +++ b/drivers/generic_gpio_libgpiod.c @@ -121,7 +121,7 @@ static void reserve_lines_libgpiod(struct gpioups_t *gpioupsfdlocal, int inner) * and check lines numbers validity - consistency with h/w chip */ void gpio_open(struct gpioups_t *gpioupsfdlocal) { - struct libgpiod_data_t *libgpiod_data = xcalloc(1, sizeof(struct libgpiod_data_t)); + struct libgpiod_data_t *libgpiod_data = (struct libgpiod_data_t *)xcalloc(1, sizeof(struct libgpiod_data_t)); gpioupsfdlocal->lib_data = libgpiod_data; #if WITH_LIBGPIO_VERSION < 0x00020000 @@ -129,7 +129,7 @@ void gpio_open(struct gpioups_t *gpioupsfdlocal) { #else /* #if WITH_LIBGPIO_VERSION >= 0x00020000 */ if(!strchr(gpioupsfdlocal->chipName, '/')) { size_t pathNameLen = strlen(gpioupsfdlocal->chipName)+6; - char *pathName = xcalloc(pathNameLen, sizeof(char)); + char *pathName = (char *)xcalloc(pathNameLen, sizeof(char)); strncpy(pathName, "/dev/", pathNameLen); strncat(pathName, gpioupsfdlocal->chipName, pathNameLen); libgpiod_data->gpioChipHandle = gpiod_chip_open(pathName); @@ -182,7 +182,7 @@ void gpio_open(struct gpioups_t *gpioupsfdlocal) { &libgpiod_data->gpioLines ); #else /* #if WITH_LIBGPIO_VERSION >= 0x00020000 */ - libgpiod_data->values = xcalloc(gpioupsfdlocal->upsLinesCount, sizeof(*libgpiod_data->values)); + libgpiod_data->values = (enum gpiod_line_value *)xcalloc(gpioupsfdlocal->upsLinesCount, sizeof(*libgpiod_data->values)); lineSettings = gpiod_line_settings_new(); libgpiod_data->lineConfig = gpiod_line_config_new(); libgpiod_data->config = gpiod_request_config_new(); diff --git a/tests/generic_gpio_utest.c b/tests/generic_gpio_utest.c index 363ee71d18..62b4577dfa 100644 --- a/tests/generic_gpio_utest.c +++ b/tests/generic_gpio_utest.c @@ -238,7 +238,7 @@ int main(int argc, char **argv) { #endif if(fEof!=EOF) { if(!strcmp(testType, "rules")) { - struct gpioups_t *upsfdtest = xcalloc(1, sizeof(*upsfdtest)); + struct gpioups_t *upsfdtest = (struct gpioups_t *)xcalloc(1, sizeof(*upsfdtest)); /* NOTE: here and below, freed by generic_gpio_close(&upsfdtest) */ jmp_result = setjmp(env_buffer); if(jmp_result) { /* test case exiting */ @@ -252,11 +252,11 @@ int main(int argc, char **argv) { if(!strcmp(testType, "states")) { int expectedStateValue; int calculatedStateValue; - struct gpioups_t *upsfdtest = xcalloc(1, sizeof(*upsfdtest)); + struct gpioups_t *upsfdtest = (struct gpioups_t *)xcalloc(1, sizeof(*upsfdtest)); int j; get_ups_rules(upsfdtest, (unsigned char *)rules); - upsfdtest->upsLinesStates = xcalloc(upsfdtest->upsLinesCount, sizeof(int)); + upsfdtest->upsLinesStates = (int *)xcalloc(upsfdtest->upsLinesCount, sizeof(int)); for (j=0; j < upsfdtest->upsLinesCount; j++) { fEof=fscanf(testData, "%d", &upsfdtest->upsLinesStates[j]); } @@ -283,7 +283,7 @@ int main(int argc, char **argv) { char chargeStatus[256]; char chargeLow[256]; char charge[256]; - struct gpioups_t *upsfdtest = xcalloc(1, sizeof(*upsfdtest)); + struct gpioups_t *upsfdtest = (struct gpioups_t *)xcalloc(1, sizeof(*upsfdtest)); int j; /* "volatile" trickery to avoid the likes of: @@ -296,7 +296,7 @@ int main(int argc, char **argv) { const char * volatile currCharge = NULL; get_ups_rules(upsfdtest, (unsigned char *)rules); - upsfdtest->upsLinesStates = xcalloc(upsfdtest->upsLinesCount, sizeof(int)); + upsfdtest->upsLinesStates = (int *)xcalloc(upsfdtest->upsLinesCount, sizeof(int)); for (j = 0; j < upsfdtest->upsLinesCount; j++) { fEof=fscanf(testData, "%d", &upsfdtest->upsLinesStates[j]); } From 96c9acba517b8cb871bbf57f67ed9f41d0dc2c46 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 8 Feb 2026 19:06:21 +0000 Subject: [PATCH 170/198] drivers/nutdrv_qx_voltronic-axpert.c: fix more casting from xcalloc() et al [#3297] Signed-off-by: Jim Klimov --- drivers/nutdrv_qx_voltronic-axpert.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/nutdrv_qx_voltronic-axpert.c b/drivers/nutdrv_qx_voltronic-axpert.c index c5da6fb5e3..9f2f754ac6 100644 --- a/drivers/nutdrv_qx_voltronic-axpert.c +++ b/drivers/nutdrv_qx_voltronic-axpert.c @@ -2419,7 +2419,7 @@ static int voltronic_sunny_energy_hour(item_t *item, char *command, const size_t return -1; } - buf = xcalloc(commandlen, sizeof(char)); + buf = (char *)xcalloc(commandlen, sizeof(char)); if (!buf) { upsdebugx(2, "%s: cannot allocate buffer", __func__); return -1; @@ -2448,7 +2448,7 @@ static int voltronic_sunny_energy_day(item_t *item, char *command, const size_t return -1; } - buf = xcalloc(commandlen, sizeof(char)); + buf = (char *)xcalloc(commandlen, sizeof(char)); if (!buf) { upsdebugx(2, "%s: cannot allocate buffer", __func__); return -1; @@ -2477,7 +2477,7 @@ static int voltronic_sunny_energy_month(item_t *item, char *command, const size_ return -1; } - buf = xcalloc(commandlen, sizeof(char)); + buf = (char *)xcalloc(commandlen, sizeof(char)); if (!buf) { upsdebugx(2, "%s: cannot allocate buffer", __func__); return -1; @@ -2506,7 +2506,7 @@ static int voltronic_sunny_energy_year(item_t *item, char *command, const size_t return -1; } - buf = xcalloc(commandlen, sizeof(char)); + buf = (char *)xcalloc(commandlen, sizeof(char)); if (!buf) { upsdebugx(2, "%s: cannot allocate buffer", __func__); return -1; From eee929773e6e7b7e9c6e7ca899ecb7d35434a3b6 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 8 Feb 2026 19:09:55 +0000 Subject: [PATCH 171/198] tests/generic_gpio_liblocal.c: gpiod_line_request_get_values(): do not assign plain number to enum variables [#3297] Signed-off-by: Jim Klimov --- tests/generic_gpio_liblocal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/generic_gpio_liblocal.c b/tests/generic_gpio_liblocal.c index 9cce190e0d..6fd1d24570 100644 --- a/tests/generic_gpio_liblocal.c +++ b/tests/generic_gpio_liblocal.c @@ -271,7 +271,7 @@ int gpiod_line_request_get_values( return -1; } for(i=0; i Date: Mon, 9 Feb 2026 10:27:31 +0100 Subject: [PATCH 172/198] clients/cgilib.c: debug-trace also extractcgiargs() with what query-string text we pass into caller parsearg() implementations [#2524, #3219] Signed-off-by: Jim Klimov --- clients/cgilib.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clients/cgilib.c b/clients/cgilib.c index 36bc0395b8..dba55b5ffb 100644 --- a/clients/cgilib.c +++ b/clients/cgilib.c @@ -111,6 +111,8 @@ void extractcgiargs(void) cleanvar = unescape(varname); cleanval = unescape(value); + upsdebugx(3, "%s: parsearg('%s', '%s')
", + __func__, NUT_STRARG(cleanvar), NUT_STRARG(cleanval)); parsearg(cleanvar, cleanval); free(cleanvar); free(cleanval); From be0ae0ea56c473f7ecc1c7cc658bb2a1601fea2c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 9 Feb 2026 10:54:27 +0100 Subject: [PATCH 173/198] docs/download.txt: link to "Finding recent development iteration artifacts" wiki page Signed-off-by: Jim Klimov --- docs/download.txt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/download.txt b/docs/download.txt index a1357f85de..74e1cb8155 100644 --- a/docs/download.txt +++ b/docs/download.txt @@ -79,9 +79,13 @@ workspace to try subsequent iterations), although the latter are now also available for development iterations. See the live Wiki article on -https://github.com/networkupstools/nut/wiki/Building-NUT-for-in%E2%80%90place-upgrades-or-non%E2%80%90disruptive-tests -for latest suggestions for building, testing and installing the latest -NUT code base. +link:https://github.com/networkupstools/nut/wiki/Building-NUT-for-in%E2%80%90place-upgrades-or-non%E2%80%90disruptive-tests[Building +NUT for in-place upgrades or non-disruptive tests] +for the most up-to-date suggestions for building, testing and installing +the latest (or experimental) revisions of the NUT code base, and +link:https://github.com/networkupstools/nut/wiki/Finding-recent-development-iteration-artifacts[Finding +recent development iteration artifacts] about fetching the results of +the hard work done by the NUT CI farm. Code repository ^^^^^^^^^^^^^^^ From 6ebc852d5f5c498952af0503a3e87a8b98367e49 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 9 Feb 2026 10:58:41 +0100 Subject: [PATCH 174/198] clients/upsclient.c: fix void* casting for a NSS build [#3311] Signed-off-by: Jim Klimov --- clients/upsclient.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/upsclient.c b/clients/upsclient.c index 1d4851f18e..63bbc7051e 100644 --- a/clients/upsclient.c +++ b/clients/upsclient.c @@ -501,7 +501,7 @@ int upscli_init(int certverify, const char *certpath, void upscli_add_host_cert(const char* hostname, const char* certname, int certverify, int forcessl) { #ifdef WITH_NSS - HOST_CERT_t* cert = xmalloc(sizeof(HOST_CERT_t)); + HOST_CERT_t* cert = (HOST_CERT_t *)xmalloc(sizeof(HOST_CERT_t)); cert->next = first_host_cert; cert->host = xstrdup(hostname); cert->certname = xstrdup(certname); From 70f7ed95c388f40178ff58606077a54acdb528be Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 8 Feb 2026 13:52:25 +0100 Subject: [PATCH 175/198] tools/nut-scanner/scan_*.c, NEWS.adoc: track seeked symbols to know where import failed [#3310] Signed-off-by: Jim Klimov --- NEWS.adoc | 4 ++ tools/nut-scanner/scan_avahi.c | 71 ++++++++++++++++++++++--------- tools/nut-scanner/scan_ipmi.c | 71 ++++++++++++++++++++++--------- tools/nut-scanner/scan_nut.c | 27 ++++++++---- tools/nut-scanner/scan_snmp.c | 69 ++++++++++++++++++------------ tools/nut-scanner/scan_upower.c | 51 ++++++++++++++++------ tools/nut-scanner/scan_usb.c | 61 ++++++++++++++++---------- tools/nut-scanner/scan_xml_http.c | 31 ++++++++++---- 8 files changed, 264 insertions(+), 121 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index b618b57d3c..c2c93e87d2 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -277,6 +277,10 @@ https://github.com/networkupstools/nut/milestone/12 built-in NUT configuration path on all platforms, but to also consider `NUT_CONFPATH` and other fallback locations, like other code does. [PR #3249] + * Enhance debug-logging of dynamic library loading with information about + any missing method in the library discovered at run-time, if lack of such + prevents us from using that library, and blocks scanning of corresponding + protocol and/or media to discover possibly supported devices. [PR #3310] * Introduced `nut-scanner` support for new `nut-upower` driver. [PR #3293] - `upsd` data server updates: diff --git a/tools/nut-scanner/scan_avahi.c b/tools/nut-scanner/scan_avahi.c index f9afce3ef5..66f9b6f16c 100644 --- a/tools/nut-scanner/scan_avahi.c +++ b/tools/nut-scanner/scan_avahi.c @@ -1,7 +1,7 @@ /* * Copyright (C) 2011-2024 Arnaud Quette (Design and part of implementation) * Copyright (C) 2011 - EATON - * Copyright (C) 2020-2024 - Jim Klimov - support and modernization of codebase + * Copyright (C) 2020-2026 - Jim Klimov - support and modernization of codebase * * 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 @@ -108,6 +108,8 @@ int nutscan_unload_avahi_library(void) int nutscan_load_avahi_library(const char *libname_path); int nutscan_load_avahi_library(const char *libname_path) { + char *symbol = NULL; + if (dl_handle != NULL) { /* if previous init failed */ if (dl_handle == (lt_dlhandle)1) { @@ -133,99 +135,122 @@ int nutscan_load_avahi_library(const char *libname_path) goto err; } + upsdebugx(2, "%s: lt_dlopen() succeeded, searching for needed methods", __func__); + /* Clear any existing error */ lt_dlerror(); - *(void **) (&nut_avahi_service_browser_get_client) = lt_dlsym(dl_handle, "avahi_service_browser_get_client"); + *(void **) (&nut_avahi_service_browser_get_client) = lt_dlsym(dl_handle, + symbol = "avahi_service_browser_get_client"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_simple_poll_loop) = lt_dlsym(dl_handle, "avahi_simple_poll_loop"); + *(void **) (&nut_avahi_simple_poll_loop) = lt_dlsym(dl_handle, + symbol = "avahi_simple_poll_loop"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_client_free) = lt_dlsym(dl_handle, "avahi_client_free"); + *(void **) (&nut_avahi_client_free) = lt_dlsym(dl_handle, + symbol = "avahi_client_free"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_client_errno) = lt_dlsym(dl_handle, "avahi_client_errno"); + *(void **) (&nut_avahi_client_errno) = lt_dlsym(dl_handle, + symbol = "avahi_client_errno"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_free) = lt_dlsym(dl_handle, "avahi_free"); + *(void **) (&nut_avahi_free) = lt_dlsym(dl_handle, + symbol = "avahi_free"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_simple_poll_quit) = lt_dlsym(dl_handle, "avahi_simple_poll_quit"); + *(void **) (&nut_avahi_simple_poll_quit) = lt_dlsym(dl_handle, + symbol = "avahi_simple_poll_quit"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_client_new) = lt_dlsym(dl_handle, "avahi_client_new"); + *(void **) (&nut_avahi_client_new) = lt_dlsym(dl_handle, + symbol = "avahi_client_new"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_simple_poll_free) = lt_dlsym(dl_handle, "avahi_simple_poll_free"); + *(void **) (&nut_avahi_simple_poll_free) = lt_dlsym(dl_handle, + symbol = "avahi_simple_poll_free"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_service_resolver_new) = lt_dlsym(dl_handle, "avahi_service_resolver_new"); + *(void **) (&nut_avahi_service_resolver_new) = lt_dlsym(dl_handle, + symbol = "avahi_service_resolver_new"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_strerror) = lt_dlsym(dl_handle, "avahi_strerror"); + *(void **) (&nut_avahi_strerror) = lt_dlsym(dl_handle, + symbol = "avahi_strerror"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_service_resolver_get_client) = lt_dlsym(dl_handle, "avahi_service_resolver_get_client"); + *(void **) (&nut_avahi_service_resolver_get_client) = lt_dlsym(dl_handle, + symbol = "avahi_service_resolver_get_client"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_service_browser_new) = lt_dlsym(dl_handle, "avahi_service_browser_new"); + *(void **) (&nut_avahi_service_browser_new) = lt_dlsym(dl_handle, + symbol = "avahi_service_browser_new"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_service_resolver_free) = lt_dlsym(dl_handle, "avahi_service_resolver_free"); + *(void **) (&nut_avahi_service_resolver_free) = lt_dlsym(dl_handle, + symbol = "avahi_service_resolver_free"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_simple_poll_new) = lt_dlsym(dl_handle, "avahi_simple_poll_new"); + *(void **) (&nut_avahi_simple_poll_new) = lt_dlsym(dl_handle, + symbol = "avahi_simple_poll_new"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_string_list_to_string) = lt_dlsym(dl_handle, "avahi_string_list_to_string"); + *(void **) (&nut_avahi_string_list_to_string) = lt_dlsym(dl_handle, + symbol = "avahi_string_list_to_string"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_service_browser_free) = lt_dlsym(dl_handle, "avahi_service_browser_free"); + *(void **) (&nut_avahi_service_browser_free) = lt_dlsym(dl_handle, + symbol = "avahi_service_browser_free"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_address_snprint) = lt_dlsym(dl_handle, "avahi_address_snprint"); + *(void **) (&nut_avahi_address_snprint) = lt_dlsym(dl_handle, + symbol = "avahi_address_snprint"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_simple_poll_get) = lt_dlsym(dl_handle, "avahi_simple_poll_get"); + *(void **) (&nut_avahi_simple_poll_get) = lt_dlsym(dl_handle, + symbol = "avahi_simple_poll_get"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } + /* Passed final lt_dlsym() */ + symbol = NULL; + if (dl_saved_libname) free(dl_saved_libname); dl_saved_libname = xstrdup(libname_path); @@ -234,8 +259,12 @@ int nutscan_load_avahi_library(const char *libname_path) err: upsdebugx(0, - "Cannot load AVAHI library (%s) : %s. AVAHI search disabled.", - libname_path, dl_error); + "Cannot load AVAHI library (%s) : %s%s%s%s. AVAHI search disabled.", + libname_path, dl_error, + symbol ? " Error happened during search for symbol '" : "", + symbol ? symbol : "", + symbol ? "'" : "" + ); dl_handle = (lt_dlhandle)1; lt_dlexit(); if (dl_saved_libname) { diff --git a/tools/nut-scanner/scan_ipmi.c b/tools/nut-scanner/scan_ipmi.c index 740381cba5..c7afdb4268 100644 --- a/tools/nut-scanner/scan_ipmi.c +++ b/tools/nut-scanner/scan_ipmi.c @@ -2,7 +2,7 @@ * Copyright (C) * 2011 - 2012 Arnaud Quette * 2016 - 2021 EATON - Various threads-related improvements - * 2020 - 2024 Jim Klimov + * 2020 - 2026 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 @@ -150,6 +150,8 @@ int nutscan_unload_ipmi_library(void) int nutscan_load_ipmi_library(const char *libname_path); int nutscan_load_ipmi_library(const char *libname_path) { + char *symbol = NULL; + if (dl_handle != NULL) { /* if previous init failed */ if (dl_handle == (lt_dlhandle)1) { @@ -175,104 +177,127 @@ int nutscan_load_ipmi_library(const char *libname_path) goto err; } + upsdebugx(2, "%s: lt_dlopen() succeeded, searching for needed methods", __func__); + /* Clear any existing error */ lt_dlerror(); - *(void **) (&nut_ipmi_fru_close_device_id) = lt_dlsym(dl_handle, IPMI_FRU_CLOSE_DEVICE_ID); + *(void **) (&nut_ipmi_fru_close_device_id) = lt_dlsym(dl_handle, + symbol = IPMI_FRU_CLOSE_DEVICE_ID); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_fru_ctx_destroy) = lt_dlsym(dl_handle, IPMI_FRU_CTX_DESTROY); + *(void **) (&nut_ipmi_fru_ctx_destroy) = lt_dlsym(dl_handle, + symbol = IPMI_FRU_CTX_DESTROY); if ((dl_error = lt_dlerror()) != NULL) { goto err; } #ifdef HAVE_FREEIPMI_11X_12X - *(void **) (&nut_ipmi_sdr_ctx_destroy) = lt_dlsym(dl_handle, "ipmi_sdr_ctx_destroy"); + *(void **) (&nut_ipmi_sdr_ctx_destroy) = lt_dlsym(dl_handle, + symbol = "ipmi_sdr_ctx_destroy"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } #else /* HAVE_FREEIPMI_11X_12X */ - *(void **) (&nut_ipmi_sdr_cache_ctx_destroy) = lt_dlsym(dl_handle, "ipmi_sdr_cache_ctx_destroy"); + *(void **) (&nut_ipmi_sdr_cache_ctx_destroy) = lt_dlsym(dl_handle, + symbol = "ipmi_sdr_cache_ctx_destroy"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_sdr_parse_ctx_destroy) = lt_dlsym(dl_handle, "ipmi_sdr_parse_ctx_destroy"); + *(void **) (&nut_ipmi_sdr_parse_ctx_destroy) = lt_dlsym(dl_handle, + symbol = "ipmi_sdr_parse_ctx_destroy"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } #endif /* HAVE_FREEIPMI_11X_12X */ - *(void **) (&nut_ipmi_fru_ctx_create) = lt_dlsym(dl_handle, IPMI_FRU_CTX_CREATE); + *(void **) (&nut_ipmi_fru_ctx_create) = lt_dlsym(dl_handle, + symbol = IPMI_FRU_CTX_CREATE); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_fru_ctx_set_flags) = lt_dlsym(dl_handle, IPMI_FRU_CTX_SET_FLAGS); + *(void **) (&nut_ipmi_fru_ctx_set_flags) = lt_dlsym(dl_handle, + symbol = IPMI_FRU_CTX_SET_FLAGS); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_fru_open_device_id) = lt_dlsym(dl_handle, IPMI_FRU_OPEN_DEVICE_ID); + *(void **) (&nut_ipmi_fru_open_device_id) = lt_dlsym(dl_handle, + symbol = IPMI_FRU_OPEN_DEVICE_ID); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_fru_ctx_errormsg) = lt_dlsym(dl_handle, IPMI_FRU_CTX_ERRORMSG); + *(void **) (&nut_ipmi_fru_ctx_errormsg) = lt_dlsym(dl_handle, + symbol = IPMI_FRU_CTX_ERRORMSG); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_fru_read_data_area) = lt_dlsym(dl_handle, IPMI_FRU_READ_DATA_AREA); + *(void **) (&nut_ipmi_fru_read_data_area) = lt_dlsym(dl_handle, + symbol = IPMI_FRU_READ_DATA_AREA); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_fru_next) = lt_dlsym(dl_handle, IPMI_FRU_PARSE_NEXT); + *(void **) (&nut_ipmi_fru_next) = lt_dlsym(dl_handle, + symbol = IPMI_FRU_PARSE_NEXT); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_ctx_create) = lt_dlsym(dl_handle, "ipmi_ctx_create"); + *(void **) (&nut_ipmi_ctx_create) = lt_dlsym(dl_handle, + symbol = "ipmi_ctx_create"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_ctx_find_inband) = lt_dlsym(dl_handle, "ipmi_ctx_find_inband"); + *(void **) (&nut_ipmi_ctx_find_inband) = lt_dlsym(dl_handle, + symbol = "ipmi_ctx_find_inband"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_ctx_open_outofband) = lt_dlsym(dl_handle, "ipmi_ctx_open_outofband"); + *(void **) (&nut_ipmi_ctx_open_outofband) = lt_dlsym(dl_handle, + symbol = "ipmi_ctx_open_outofband"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_ctx_errnum) = lt_dlsym(dl_handle, "ipmi_ctx_errnum"); + *(void **) (&nut_ipmi_ctx_errnum) = lt_dlsym(dl_handle, + symbol = "ipmi_ctx_errnum"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_ctx_errormsg) = lt_dlsym(dl_handle, "ipmi_ctx_errormsg"); + *(void **) (&nut_ipmi_ctx_errormsg) = lt_dlsym(dl_handle, + symbol = "ipmi_ctx_errormsg"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_ctx_close) = lt_dlsym(dl_handle, "ipmi_ctx_close"); + *(void **) (&nut_ipmi_ctx_close) = lt_dlsym(dl_handle, + symbol = "ipmi_ctx_close"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_ctx_destroy) = lt_dlsym(dl_handle, "ipmi_ctx_destroy"); + *(void **) (&nut_ipmi_ctx_destroy) = lt_dlsym(dl_handle, + symbol = "ipmi_ctx_destroy"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } + /* Passed final lt_dlsym() */ + symbol = NULL; + if (dl_saved_libname) free(dl_saved_libname); dl_saved_libname = xstrdup(libname_path); @@ -281,8 +306,12 @@ int nutscan_load_ipmi_library(const char *libname_path) err: upsdebugx(0, - "Cannot load IPMI library (%s) : %s. IPMI search disabled.", - libname_path, dl_error); + "Cannot load IPMI library (%s) : %s%s%s%s. IPMI search disabled.", + libname_path, dl_error, + symbol ? " Error happened during search for symbol '" : "", + symbol ? symbol : "", + symbol ? "'" : "" + ); dl_handle = (lt_dlhandle)1; lt_dlexit(); if (dl_saved_libname) { diff --git a/tools/nut-scanner/scan_nut.c b/tools/nut-scanner/scan_nut.c index b9465633ca..acdaa16c47 100644 --- a/tools/nut-scanner/scan_nut.c +++ b/tools/nut-scanner/scan_nut.c @@ -2,7 +2,7 @@ * Copyright (C) 2011 - 2023 Arnaud Quette (Design and part of implementation) * Copyright (C) 2011 - EATON * Copyright (C) 2016-2021 - EATON - Various threads-related improvements - * Copyright (C) 2020-2024 - Jim Klimov - support and modernization of codebase + * Copyright (C) 2020-2026 - Jim Klimov - support and modernization of codebase * * 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 @@ -86,6 +86,8 @@ int nutscan_unload_upsclient_library(void) int nutscan_load_upsclient_library(const char *libname_path); int nutscan_load_upsclient_library(const char *libname_path) { + char *symbol = NULL; + if (dl_handle != NULL) { /* if previous init failed */ if (dl_handle == (lt_dlhandle)1) { @@ -111,39 +113,44 @@ int nutscan_load_upsclient_library(const char *libname_path) goto err; } + upsdebugx(2, "%s: lt_dlopen() succeeded, searching for needed methods", __func__); + /* Clear any existing error */ lt_dlerror(); *(void **) (&nut_upscli_splitaddr) = lt_dlsym(dl_handle, - "upscli_splitaddr"); + symbol = "upscli_splitaddr"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_upscli_tryconnect) = lt_dlsym(dl_handle, - "upscli_tryconnect"); + symbol = "upscli_tryconnect"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_upscli_list_start) = lt_dlsym(dl_handle, - "upscli_list_start"); + symbol = "upscli_list_start"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_upscli_list_next) = lt_dlsym(dl_handle, - "upscli_list_next"); + symbol = "upscli_list_next"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_upscli_disconnect) = lt_dlsym(dl_handle, - "upscli_disconnect"); + symbol = "upscli_disconnect"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } + /* Passed final lt_dlsym() */ + symbol = NULL; + if (dl_saved_libname) free(dl_saved_libname); dl_saved_libname = xstrdup(libname_path); @@ -152,8 +159,12 @@ int nutscan_load_upsclient_library(const char *libname_path) err: upsdebugx(0, - "Cannot load NUT library (%s) : %s. NUT search disabled.", - libname_path, dl_error); + "Cannot load NUT library (%s) : %s%s%s%s. NUT search disabled.", + libname_path, dl_error, + symbol ? " Error happened during search for symbol '" : "", + symbol ? symbol : "", + symbol ? "'" : "" + ); dl_handle = (lt_dlhandle)1; lt_dlexit(); if (dl_saved_libname) { diff --git a/tools/nut-scanner/scan_snmp.c b/tools/nut-scanner/scan_snmp.c index d70a7917d2..5709cf05fe 100644 --- a/tools/nut-scanner/scan_snmp.c +++ b/tools/nut-scanner/scan_snmp.c @@ -1,7 +1,7 @@ /* * Copyright (C) 2011 - EATON * Copyright (C) 2016-2021 - EATON - Various threads-related improvements - * Copyright (C) 2020-2024 - Jim Klimov - support and modernization of codebase + * Copyright (C) 2020-2026 - Jim Klimov - support and modernization of codebase * * 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 @@ -295,6 +295,8 @@ int nutscan_load_snmp_library(const char *libname_path) # endif #else /* not WITH_SNMP_STATIC */ + char *symbol = NULL; + if (dl_handle != NULL) { /* if previous init failed */ if (dl_handle == (lt_dlhandle)1) { @@ -320,98 +322,104 @@ int nutscan_load_snmp_library(const char *libname_path) goto err; } + upsdebugx(2, "%s: lt_dlopen() succeeded, searching for needed methods", __func__); + /* Clear any existing error */ lt_dlerror(); - *(void **) (&nut_init_snmp) = lt_dlsym(dl_handle, "init_snmp"); + *(void **) (&nut_init_snmp) = lt_dlsym(dl_handle, + symbol = "init_snmp"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_sess_init) = lt_dlsym(dl_handle, - "snmp_sess_init"); + symbol = "snmp_sess_init"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_sess_open) = lt_dlsym(dl_handle, - "snmp_sess_open"); + symbol = "snmp_sess_open"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_sess_close) = lt_dlsym(dl_handle, - "snmp_sess_close"); + symbol = "snmp_sess_close"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_sess_session) = lt_dlsym(dl_handle, - "snmp_sess_session"); + symbol = "snmp_sess_session"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_parse_oid) = lt_dlsym(dl_handle, - "snmp_parse_oid"); + symbol = "snmp_parse_oid"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_pdu_create) = lt_dlsym(dl_handle, - "snmp_pdu_create"); + symbol = "snmp_pdu_create"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_add_null_var) = lt_dlsym(dl_handle, - "snmp_add_null_var"); + symbol = "snmp_add_null_var"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_sess_synch_response) = lt_dlsym(dl_handle, - "snmp_sess_synch_response"); + symbol = "snmp_sess_synch_response"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_oid_compare) = lt_dlsym(dl_handle, - "snmp_oid_compare"); + symbol = "snmp_oid_compare"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_snmp_free_pdu) = lt_dlsym(dl_handle, "snmp_free_pdu"); + *(void **) (&nut_snmp_free_pdu) = lt_dlsym(dl_handle, + symbol = "snmp_free_pdu"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_generate_Ku) = lt_dlsym(dl_handle, "generate_Ku"); + *(void **) (&nut_generate_Ku) = lt_dlsym(dl_handle, + symbol = "generate_Ku"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_out_toggle_options) = lt_dlsym(dl_handle, - "snmp_out_toggle_options"); + symbol = "snmp_out_toggle_options"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_api_errstring) = lt_dlsym(dl_handle, - "snmp_api_errstring"); + symbol = "snmp_api_errstring"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_snmp_errno) = lt_dlsym(dl_handle, "snmp_errno"); + *(void **) (&nut_snmp_errno) = lt_dlsym(dl_handle, + symbol = "snmp_errno"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } #if NUT_HAVE_LIBNETSNMP_usmAESPrivProtocol || NUT_HAVE_LIBNETSNMP_usmAES128PrivProtocol *(void **) (&nut_usmAESPrivProtocol) = lt_dlsym(dl_handle, - USMAESPRIVPROTOCOL); + symbol = USMAESPRIVPROTOCOL); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -419,7 +427,7 @@ int nutscan_load_snmp_library(const char *libname_path) #if NUT_HAVE_LIBNETSNMP_usmHMACMD5AuthProtocol *(void **) (&nut_usmHMACMD5AuthProtocol) = lt_dlsym(dl_handle, - "usmHMACMD5AuthProtocol"); + symbol = "usmHMACMD5AuthProtocol"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -427,7 +435,7 @@ int nutscan_load_snmp_library(const char *libname_path) #if NUT_HAVE_LIBNETSNMP_usmHMACSHA1AuthProtocol *(void **) (&nut_usmHMACSHA1AuthProtocol) = lt_dlsym(dl_handle, - "usmHMACSHA1AuthProtocol"); + symbol = "usmHMACSHA1AuthProtocol"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -435,7 +443,7 @@ int nutscan_load_snmp_library(const char *libname_path) #if NUT_HAVE_LIBNETSNMP_usmDESPrivProtocol *(void **) (&nut_usmDESPrivProtocol) = lt_dlsym(dl_handle, - "usmDESPrivProtocol"); + symbol = "usmDESPrivProtocol"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -444,7 +452,7 @@ int nutscan_load_snmp_library(const char *libname_path) #if NUT_HAVE_LIBNETSNMP_DRAFT_BLUMENTHAL_AES_04 # if NUT_HAVE_LIBNETSNMP_usmAES192PrivProtocol *(void **) (&nut_usmAES192PrivProtocol) = lt_dlsym(dl_handle, - "usmAES192PrivProtocol"); + symbol = "usmAES192PrivProtocol"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -452,7 +460,7 @@ int nutscan_load_snmp_library(const char *libname_path) # if NUT_HAVE_LIBNETSNMP_usmAES256PrivProtocol *(void **) (&nut_usmAES256PrivProtocol) = lt_dlsym(dl_handle, - "usmAES256PrivProtocol"); + symbol = "usmAES256PrivProtocol"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -461,7 +469,7 @@ int nutscan_load_snmp_library(const char *libname_path) #if NUT_HAVE_LIBNETSNMP_usmHMAC192SHA256AuthProtocol *(void **) (&nut_usmHMAC192SHA256AuthProtocol) = lt_dlsym(dl_handle, - "usmHMAC192SHA256AuthProtocol"); + symbol = "usmHMAC192SHA256AuthProtocol"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -469,7 +477,7 @@ int nutscan_load_snmp_library(const char *libname_path) #if NUT_HAVE_LIBNETSNMP_usmHMAC256SHA384AuthProtocol *(void **) (&nut_usmHMAC256SHA384AuthProtocol) = lt_dlsym(dl_handle, - "usmHMAC256SHA384AuthProtocol"); + symbol = "usmHMAC256SHA384AuthProtocol"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -477,12 +485,15 @@ int nutscan_load_snmp_library(const char *libname_path) #if NUT_HAVE_LIBNETSNMP_usmHMAC384SHA512AuthProtocol *(void **) (&nut_usmHMAC384SHA512AuthProtocol) = lt_dlsym(dl_handle, - "usmHMAC384SHA512AuthProtocol"); + symbol = "usmHMAC384SHA512AuthProtocol"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } #endif /* NUT_HAVE_LIBNETSNMP_usmHMAC384SHA512AuthProtocol */ + /* Passed final lt_dlsym() */ + symbol = NULL; + if (dl_saved_libname) free(dl_saved_libname); dl_saved_libname = xstrdup(libname_path); @@ -494,8 +505,12 @@ int nutscan_load_snmp_library(const char *libname_path) #ifndef WITH_SNMP_STATIC err: upsdebugx(0, - "Cannot load SNMP library (%s) : %s. SNMP search disabled.", - libname_path, dl_error); + "Cannot load SNMP library (%s) : %s%s%s%s. SNMP search disabled.", + libname_path, dl_error, + symbol ? " Error happened during search for symbol '" : "", + symbol ? symbol : "", + symbol ? "'" : "" + ); dl_handle = (lt_dlhandle)1; lt_dlexit(); if (dl_saved_libname) { diff --git a/tools/nut-scanner/scan_upower.c b/tools/nut-scanner/scan_upower.c index 3866ad30bd..d2ab2b8a2d 100644 --- a/tools/nut-scanner/scan_upower.c +++ b/tools/nut-scanner/scan_upower.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2026 Tim Niemueller + * Copyright (C) 2026 - Jim Klimov - support and modernization of codebase * * 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 @@ -69,6 +70,8 @@ int nutscan_unload_upower_library(void) int nutscan_load_upower_library(const char *libname_path); int nutscan_load_upower_library(const char *libname_path) { + char *symbol = NULL; + if (dl_handle != NULL) { /* if previous init failed */ if (dl_handle == (lt_dlhandle)1) { @@ -93,46 +96,62 @@ int nutscan_load_upower_library(const char *libname_path) dl_error = lt_dlerror(); goto err; } + upsdebugx(2, "%s: lt_dlopen() succeeded, searching for needed methods", __func__); /* Clear any existing error */ lt_dlerror(); - *(void **) (&nut_g_bus_get_sync) = lt_dlsym(dl_handle, "g_bus_get_sync"); + *(void **) (&nut_g_bus_get_sync) = lt_dlsym(dl_handle, + symbol = "g_bus_get_sync"); if ((dl_error = lt_dlerror()) != NULL) goto err; - *(void **) (&nut_g_dbus_proxy_new_sync) = lt_dlsym(dl_handle, "g_dbus_proxy_new_sync"); + *(void **) (&nut_g_dbus_proxy_new_sync) = lt_dlsym(dl_handle, + symbol = "g_dbus_proxy_new_sync"); if ((dl_error = lt_dlerror()) != NULL) goto err; - *(void **) (&nut_g_dbus_proxy_call_sync) = lt_dlsym(dl_handle, "g_dbus_proxy_call_sync"); + *(void **) (&nut_g_dbus_proxy_call_sync) = lt_dlsym(dl_handle, + symbol = "g_dbus_proxy_call_sync"); if ((dl_error = lt_dlerror()) != NULL) goto err; - *(void **) (&nut_g_dbus_proxy_get_cached_property) = lt_dlsym(dl_handle, "g_dbus_proxy_get_cached_property"); + *(void **) (&nut_g_dbus_proxy_get_cached_property) = lt_dlsym(dl_handle, + symbol = "g_dbus_proxy_get_cached_property"); if ((dl_error = lt_dlerror()) != NULL) goto err; - *(void **) (&nut_g_variant_unref) = lt_dlsym(dl_handle, "g_variant_unref"); + *(void **) (&nut_g_variant_unref) = lt_dlsym(dl_handle, + symbol = "g_variant_unref"); if ((dl_error = lt_dlerror()) != NULL) goto err; - *(void **) (&nut_g_object_unref) = lt_dlsym(dl_handle, "g_object_unref"); + *(void **) (&nut_g_object_unref) = lt_dlsym(dl_handle, + symbol = "g_object_unref"); if ((dl_error = lt_dlerror()) != NULL) goto err; - *(void **) (&nut_g_error_free) = lt_dlsym(dl_handle, "g_error_free"); + *(void **) (&nut_g_error_free) = lt_dlsym(dl_handle, + symbol = "g_error_free"); if ((dl_error = lt_dlerror()) != NULL) goto err; - *(void **) (&nut_g_variant_get_string) = lt_dlsym(dl_handle, "g_variant_get_string"); + *(void **) (&nut_g_variant_get_string) = lt_dlsym(dl_handle, + symbol = "g_variant_get_string"); if ((dl_error = lt_dlerror()) != NULL) goto err; - *(void **) (&nut_g_variant_iter_next) = lt_dlsym(dl_handle, "g_variant_iter_next"); + *(void **) (&nut_g_variant_iter_next) = lt_dlsym(dl_handle, + symbol = "g_variant_iter_next"); if ((dl_error = lt_dlerror()) != NULL) goto err; - *(void **) (&nut_g_variant_iter_init) = lt_dlsym(dl_handle, "g_variant_iter_init"); + *(void **) (&nut_g_variant_iter_init) = lt_dlsym(dl_handle, + symbol = "g_variant_iter_init"); if ((dl_error = lt_dlerror()) != NULL) goto err; - *(void **) (&nut_g_variant_get_uint32) = lt_dlsym(dl_handle, "g_variant_get_uint32"); + *(void **) (&nut_g_variant_get_uint32) = lt_dlsym(dl_handle, + symbol = "g_variant_get_uint32"); if ((dl_error = lt_dlerror()) != NULL) goto err; - *(void **) (&nut_g_variant_get_child_value) = lt_dlsym(dl_handle, "g_variant_get_child_value"); + *(void **) (&nut_g_variant_get_child_value) = lt_dlsym(dl_handle, + symbol = "g_variant_get_child_value"); if ((dl_error = lt_dlerror()) != NULL) goto err; + /* Passed final lt_dlsym() */ + symbol = NULL; + if (dl_saved_libname) free(dl_saved_libname); dl_saved_libname = xstrdup(libname_path); @@ -141,8 +160,12 @@ int nutscan_load_upower_library(const char *libname_path) err: upsdebugx(0, - "Cannot load GIO library (%s) : %s. UPower search disabled.", - libname_path, dl_error); + "Cannot load GIO library (%s) : %s%s%s%s. UPower search disabled.", + libname_path, dl_error, + symbol ? " Error happened during search for symbol '" : "", + symbol ? symbol : "", + symbol ? "'" : "" + ); dl_handle = (lt_dlhandle)1; lt_dlexit(); if (dl_saved_libname) { diff --git a/tools/nut-scanner/scan_usb.c b/tools/nut-scanner/scan_usb.c index 1e63191948..29bd9baf52 100644 --- a/tools/nut-scanner/scan_usb.c +++ b/tools/nut-scanner/scan_usb.c @@ -107,6 +107,8 @@ int nutscan_unload_usb_library(void) int nutscan_load_usb_library(const char *libname_path); int nutscan_load_usb_library(const char *libname_path) { + char *symbol = NULL; + if (dl_handle != NULL) { /* if previous init failed */ if (dl_handle == (lt_dlhandle)1) { @@ -132,54 +134,62 @@ int nutscan_load_usb_library(const char *libname_path) goto err; } + upsdebugx(2, "%s: lt_dlopen() succeeded, searching for needed methods", __func__); + /* Clear any existing error */ lt_dlerror(); - *(void **) (&nut_usb_init) = lt_dlsym(dl_handle, USB_INIT_SYMBOL); + *(void **) (&nut_usb_init) = lt_dlsym(dl_handle, + symbol = USB_INIT_SYMBOL); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_usb_open) = lt_dlsym(dl_handle, USB_OPEN_SYMBOL); + *(void **) (&nut_usb_open) = lt_dlsym(dl_handle, + symbol = USB_OPEN_SYMBOL); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_usb_close) = lt_dlsym(dl_handle, USB_CLOSE_SYMBOL); + *(void **) (&nut_usb_close) = lt_dlsym(dl_handle, + symbol = USB_CLOSE_SYMBOL); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_usb_strerror) = lt_dlsym(dl_handle, USB_STRERROR_SYMBOL); + *(void **) (&nut_usb_strerror) = lt_dlsym(dl_handle, + symbol = USB_STRERROR_SYMBOL); if ((dl_error = lt_dlerror()) != NULL) { goto err; } #if WITH_LIBUSB_1_0 - *(void **) (&nut_usb_exit) = lt_dlsym(dl_handle, "libusb_exit"); + *(void **) (&nut_usb_exit) = lt_dlsym(dl_handle, + symbol = "libusb_exit"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_usb_get_version) = lt_dlsym(dl_handle, "libusb_get_version"); + *(void **) (&nut_usb_get_version) = lt_dlsym(dl_handle, + symbol = "libusb_get_version"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_usb_get_device_list) = lt_dlsym(dl_handle, - "libusb_get_device_list"); + symbol = "libusb_get_device_list"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_usb_free_device_list) = lt_dlsym(dl_handle, - "libusb_free_device_list"); + symbol = "libusb_free_device_list"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_usb_get_bus_number) = lt_dlsym(dl_handle, - "libusb_get_bus_number"); + symbol = "libusb_get_bus_number"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -189,7 +199,7 @@ int nutscan_load_usb_library(const char *libname_path) * not for too long (libusb-1.0.12...1.0.16) and now it is deprecated. */ *(void **) (&nut_usb_get_device_address) = lt_dlsym(dl_handle, - "libusb_get_device_address"); + symbol = "libusb_get_device_address"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -199,7 +209,7 @@ int nutscan_load_usb_library(const char *libname_path) * #if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) */ *(void **) (&nut_usb_get_port_number) = lt_dlsym(dl_handle, - "libusb_get_port_number"); + symbol = "libusb_get_port_number"); if ((dl_error = lt_dlerror()) != NULL) { upsdebugx(0, "WARNING: %s: " "While loading USB library (%s), failed to find libusb_get_port_number() : %s. " @@ -209,19 +219,19 @@ int nutscan_load_usb_library(const char *libname_path) } *(void **) (&nut_usb_get_device_descriptor) = lt_dlsym(dl_handle, - "libusb_get_device_descriptor"); + symbol = "libusb_get_device_descriptor"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_usb_control_transfer) = lt_dlsym(dl_handle, - "libusb_control_transfer"); + symbol = "libusb_control_transfer"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_usb_get_string_with_langid) = lt_dlsym(dl_handle, - "libusb_get_string_descriptor"); + symbol = "libusb_get_string_descriptor"); if ((dl_error = lt_dlerror()) != NULL) { /* This one may be only defined in a header as an inline method; * then we are adapting it via nut_usb_control_transfer(). @@ -230,39 +240,39 @@ int nutscan_load_usb_library(const char *libname_path) } #else /* for libusb 0.1 */ *(void **) (&nut_usb_find_busses) = lt_dlsym(dl_handle, - "usb_find_busses"); + symbol = "usb_find_busses"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } # ifndef WIN32 *(void **) (&nut_usb_busses) = lt_dlsym(dl_handle, - "usb_busses"); + symbol = "usb_busses"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } # else *(void **) (&nut_usb_get_busses) = lt_dlsym(dl_handle, - "usb_get_busses"); + symbol = "usb_get_busses"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } # endif /* WIN32 */ *(void **)(&nut_usb_find_devices) = lt_dlsym(dl_handle, - "usb_find_devices"); + symbol = "usb_find_devices"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_usb_control_transfer) = lt_dlsym(dl_handle, - "usb_control_msg"); + symbol = "usb_control_msg"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_usb_get_string_with_langid) = lt_dlsym(dl_handle, - "usb_get_string"); + symbol = "usb_get_string"); if ((dl_error = lt_dlerror()) != NULL) { /* See comment above */ nut_usb_get_string_with_langid = NULL; @@ -273,6 +283,9 @@ int nutscan_load_usb_library(const char *libname_path) nut_usb_get_string_with_langid = nut_usb_get_string_with_langid_control_transfer; } + /* Passed final lt_dlsym() */ + symbol = NULL; + if (dl_saved_libname) free(dl_saved_libname); dl_saved_libname = xstrdup(libname_path); @@ -281,8 +294,12 @@ int nutscan_load_usb_library(const char *libname_path) err: upsdebugx(0, - "Cannot load USB library (%s) : %s. USB search disabled.", - libname_path, dl_error); + "Cannot load USB library (%s) : %s%s%s%s. USB search disabled.", + libname_path, dl_error, + symbol ? " Error happened during search for symbol '" : "", + symbol ? symbol : "", + symbol ? "'" : "" + ); dl_handle = (lt_dlhandle)1; lt_dlexit(); if (dl_saved_libname) { diff --git a/tools/nut-scanner/scan_xml_http.c b/tools/nut-scanner/scan_xml_http.c index 23b0c96073..e0b0d0b992 100644 --- a/tools/nut-scanner/scan_xml_http.c +++ b/tools/nut-scanner/scan_xml_http.c @@ -2,7 +2,7 @@ * Copyright (C) 2011 - EATON * Copyright (C) 2016 - EATON - IP addressed XML scan * Copyright (C) 2016-2021 - EATON - Various threads-related improvements - * Copyright (C) 2020-2024 - Jim Klimov - support and modernization of codebase + * Copyright (C) 2020-2026 - Jim Klimov - support and modernization of codebase * * 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 @@ -102,6 +102,8 @@ int nutscan_unload_neon_library(void) int nutscan_load_neon_library(const char *libname_path); int nutscan_load_neon_library(const char *libname_path) { + char *symbol = NULL; + if (dl_handle != NULL) { /* if previous init failed */ if (dl_handle == (lt_dlhandle)1) { @@ -127,35 +129,44 @@ int nutscan_load_neon_library(const char *libname_path) goto err; } + upsdebugx(2, "%s: lt_dlopen() succeeded, searching for needed methods", __func__); + /* Clear any existing error */ lt_dlerror(); *(void **) (&nut_ne_xml_push_handler) = lt_dlsym(dl_handle, - "ne_xml_push_handler"); + symbol = "ne_xml_push_handler"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ne_xml_destroy) = lt_dlsym(dl_handle, "ne_xml_destroy"); + *(void **) (&nut_ne_xml_destroy) = lt_dlsym(dl_handle, + symbol = "ne_xml_destroy"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ne_xml_create) = lt_dlsym(dl_handle, "ne_xml_create"); + *(void **) (&nut_ne_xml_create) = lt_dlsym(dl_handle, + symbol = "ne_xml_create"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ne_xml_parse) = lt_dlsym(dl_handle, "ne_xml_parse"); + *(void **) (&nut_ne_xml_parse) = lt_dlsym(dl_handle, + symbol = "ne_xml_parse"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ne_xml_failed) = lt_dlsym(dl_handle, "ne_xml_failed"); + *(void **) (&nut_ne_xml_failed) = lt_dlsym(dl_handle, + symbol = "ne_xml_failed"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } + /* Passed final lt_dlsym() */ + symbol = NULL; + if (dl_saved_libname) free(dl_saved_libname); dl_saved_libname = xstrdup(libname_path); @@ -164,8 +175,12 @@ int nutscan_load_neon_library(const char *libname_path) err: upsdebugx(0, - "Cannot load XML library (%s) : %s. XML search disabled.", - libname_path, dl_error); + "Cannot load XML library (%s) : %s%s%s%s. XML search disabled.", + libname_path, dl_error, + symbol ? " Error happened during search for symbol '" : "", + symbol ? symbol : "", + symbol ? "'" : "" + ); dl_handle = (lt_dlhandle)1; lt_dlexit(); if (dl_saved_libname) { From e27269497069fbb2483d67056eb6a57c6914fcb8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 9 Feb 2026 12:46:33 +0100 Subject: [PATCH 176/198] common/common.c, include/common.h: introduce UPSLOG_STDOUT bit and support in vupslog(), and cgilogbit_set() for browser-friendly logging in NUT CGI programs [#2524] Signed-off-by: Jim Klimov --- common/common.c | 51 +++++++++++++++++++++++++++++++++++++++++------- include/common.h | 11 +++++++++++ 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/common/common.c b/common/common.c index 50803b25f4..832871ae77 100644 --- a/common/common.c +++ b/common/common.c @@ -588,6 +588,16 @@ int syslog_is_disabled(void) return value; } +/* enable writing upslog_with_errno() and upslogx() type messages to + * the stdout instead of stderr, and end them with HTML
tag, + * to help troubleshoot NUT CGI programs specifically */ +void cgilogbit_set(void) +{ + xbit_set(&upslog_flags, UPSLOG_STDOUT); + xbit_set(&upslog_flags, UPSLOG_CGI_BR); + xbit_clear(&upslog_flags, UPSLOG_STDERR); +} + /* enable writing upslog_with_errno() and upslogx() type messages to the syslog */ void syslogbit_set(void) @@ -3927,7 +3937,7 @@ static void vupslog(int priority, const char *fmt, va_list va, int use_strerror) upslog_start = now; } - if (xbit_test(upslog_flags, UPSLOG_STDERR)) { + if (xbit_test(upslog_flags, UPSLOG_STDERR) || xbit_test(upslog_flags, UPSLOG_STDOUT)) { if (nut_debug_level > 0) { struct timeval now; @@ -3940,15 +3950,42 @@ static void vupslog(int priority, const char *fmt, va_list va, int use_strerror) /* Print all in one shot, to better avoid * mixed lines in parallel threads */ - fprintf(stderr, "%4.0f.%06ld\t%s\n", - difftime(now.tv_sec, upslog_start.tv_sec), - (long)(now.tv_usec - upslog_start.tv_usec), - buf); + if (xbit_test(upslog_flags, UPSLOG_STDERR)) { +#ifdef WIN32 + fflush(stderr); +#endif /* WIN32 */ + fprintf(stderr, "%s%4.0f.%06ld\t%s%s\n", + xbit_test(upslog_flags, UPSLOG_CGI_BR) ? "
" : "",
+					difftime(now.tv_sec, upslog_start.tv_sec),
+					(long)(now.tv_usec - upslog_start.tv_usec),
+					buf,
+					xbit_test(upslog_flags, UPSLOG_CGI_BR) ? "
" : "" + ); + } + + if (xbit_test(upslog_flags, UPSLOG_STDOUT)) { +#ifdef WIN32 + fflush(stdout); +#endif /* WIN32 */ + fprintf(stdout, "%s%4.0f.%06ld\t%s%s\n", + xbit_test(upslog_flags, UPSLOG_CGI_BR) ? "
" : "",
+					difftime(now.tv_sec, upslog_start.tv_sec),
+					(long)(now.tv_usec - upslog_start.tv_usec),
+					buf,
+					xbit_test(upslog_flags, UPSLOG_CGI_BR) ? "
" : "" + ); + } } else { - fprintf(stderr, "%s\n", buf); + if (xbit_test(upslog_flags, UPSLOG_STDERR)) + fprintf(stderr, "%s\n", buf); + if (xbit_test(upslog_flags, UPSLOG_STDOUT)) + fprintf(stdout, "%s\n", buf); } #ifdef WIN32 - fflush(stderr); + if (xbit_test(upslog_flags, UPSLOG_STDERR)) + fflush(stderr); + if (xbit_test(upslog_flags, UPSLOG_STDOUT)) + fflush(stdout); #endif /* WIN32 */ } if (xbit_test(upslog_flags, UPSLOG_SYSLOG)) diff --git a/include/common.h b/include/common.h index 39987916ca..85bb4e8291 100644 --- a/include/common.h +++ b/include/common.h @@ -446,6 +446,11 @@ int sendsignalfnaliases(const char *pidfn, const char * sig, const char **progna * caller should strdup() a copy to retain beyond the lifetime of "file" */ const char *xbasename(const char *file); +/* enable writing upslog_with_errno() and upslogx() type messages to + * the stdout instead of stderr, and end them with HTML
tag, + * to help troubleshoot NUT CGI programs specifically */ +void cgilogbit_set(void); + /* enable writing upslog_with_errno() and upslogx() type messages to the syslog */ void syslogbit_set(void); @@ -755,6 +760,12 @@ extern int optind; #define UPSLOG_STDERR_ON_FATAL 0x0004 #define UPSLOG_SYSLOG_ON_FATAL 0x0008 +/* Special cases, primarily for NUT CGI programs to dump logs + * in a way better usable when troubleshooting with a browser: + */ +#define UPSLOG_STDOUT 0x0010 +#define UPSLOG_CGI_BR 0x0020 + #ifndef HAVE_SETEUID # define seteuid(x) setresuid(-1,x,-1) /* Works for HP-UX 10.20 */ # define setegid(x) setresgid(-1,x,-1) /* Works for HP-UX 10.20 */ From 8818a3aba7fc4579ded9afa3ee56896309d54671 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 9 Feb 2026 12:48:00 +0100 Subject: [PATCH 177/198] clients/ups{image,set,stats}.c: introduce support for browser-friendly logging in NUT CGI programs (in developer build and/or command-line runs) [#2524] Signed-off-by: Jim Klimov --- clients/upsimage.c | 17 +++++++++++++++++ clients/upsset.c | 14 ++++++++++++++ clients/upsstats.c | 17 +++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/clients/upsimage.c b/clients/upsimage.c index a055cab28a..18d7cf882b 100644 --- a/clients/upsimage.c +++ b/clients/upsimage.c @@ -647,6 +647,23 @@ int main(int argc, char **argv) nut_debug_level = i; } +#ifdef NUT_CGI_DEBUG_UPSIMAGE +# if (NUT_CGI_DEBUG_UPSIMAGE - 0 < 1) +# undef NUT_CGI_DEBUG_UPSIMAGE +# define NUT_CGI_DEBUG_UPSIMAGE 6 +# endif + /* Un-comment via make flags when developer-troubleshooting: */ + nut_debug_level = NUT_CGI_DEBUG_UPSIMAGE; +#endif + + if (nut_debug_level > 0) { + cgilogbit_set(); + printf("Content-type: text/html\n"); + printf("Pragma: no-cache\n"); + printf("\n"); + printf("

NUT CGI Debugging enabled, level: %d

\n\n", nut_debug_level); + } + extractcgiargs(); upscli_init_default_connect_timeout(NULL, NULL, UPSCLI_DEFAULT_CONNECT_TIMEOUT); diff --git a/clients/upsset.c b/clients/upsset.c index 83abe0710e..2ac3a5d052 100644 --- a/clients/upsset.c +++ b/clients/upsset.c @@ -1149,6 +1149,20 @@ int main(int argc, char **argv) nut_debug_level = i; } +#ifdef NUT_CGI_DEBUG_UPSSET +# if (NUT_CGI_DEBUG_UPSSET - 0 < 1) +# undef NUT_CGI_DEBUG_UPSSET +# define NUT_CGI_DEBUG_UPSSET 6 +# endif + /* Un-comment via make flags when developer-troubleshooting: */ + nut_debug_level = NUT_CGI_DEBUG_UPSSET; +#endif + + if (nut_debug_level > 0) { + cgilogbit_set(); + printf("

NUT CGI Debugging enabled, level: %d

\n\n", nut_debug_level); + } + /* see if the magic string is present in the config file */ check_conf(); diff --git a/clients/upsstats.c b/clients/upsstats.c index fefec01ff5..a26f79256d 100644 --- a/clients/upsstats.c +++ b/clients/upsstats.c @@ -1580,6 +1580,23 @@ int main(int argc, char **argv) template_single = xstrdup("upsstats-single.html"); template_list = xstrdup("upsstats.html"); +#ifdef NUT_CGI_DEBUG_UPSSTATS +# if (NUT_CGI_DEBUG_UPSSTATS - 0 < 1) +# undef NUT_CGI_DEBUG_UPSSTATS +# define NUT_CGI_DEBUG_UPSSTATS 6 +# endif + /* Un-comment via make flags when developer-troubleshooting: */ + nut_debug_level = NUT_CGI_DEBUG_UPSSTATS; +#endif + + if (nut_debug_level > 0) { + cgilogbit_set(); + printf("Content-type: text/html\n"); + printf("Pragma: no-cache\n"); + printf("\n"); + printf("

NUT CGI Debugging enabled, level: %d

\n\n", nut_debug_level); + } + extractcgiargs(); upscli_init_default_connect_timeout(NULL, NULL, UPSCLI_DEFAULT_CONNECT_TIMEOUT); From 38a9de1e7048567c4f0b39ff65ac92d52a1caf98 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 9 Feb 2026 12:48:48 +0100 Subject: [PATCH 178/198] clients/upsset.c: use "Pragma: no-cache" HTTP header as in upsstats.cgi [#2524] Signed-off-by: Jim Klimov --- clients/upsset.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clients/upsset.c b/clients/upsset.c index 2ac3a5d052..3074bf63ef 100644 --- a/clients/upsset.c +++ b/clients/upsset.c @@ -1137,7 +1137,9 @@ int main(int argc, char **argv) NUT_UNUSED_VARIABLE(argv); username = password = function = monups = NULL; - printf("Content-type: text/html\n\n"); + printf("Content-type: text/html\n"); + printf("Pragma: no-cache\n"); + printf("\n"); /* NOTE: Caller must `export NUT_DEBUG_LEVEL` to see debugs for upsc * and NUT methods called from it. This line aims to just initialize From 15308355ba8f7389478af1ff632951b44351bee5 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 9 Feb 2026 13:08:39 +0100 Subject: [PATCH 179/198] clients/cgilib.c: extractcgiargs(): fix processing of query strings with flag tokens (no assignment) in the middle, not at end [#2524] Signed-off-by: Jim Klimov --- clients/cgilib.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/clients/cgilib.c b/clients/cgilib.c index dba55b5ffb..044432c1b0 100644 --- a/clients/cgilib.c +++ b/clients/cgilib.c @@ -87,8 +87,15 @@ void extractcgiargs(void) while (ptr) { varname = ptr; eq = strchr(varname, '='); - if (!eq) { - ptr = strchr(varname, '&'); + amp = strchr(varname, '&'); + if (!eq + || (eq && amp && amp < eq) + ) { + /* Last token is a flag (without assignment in sight), + * OR we've got a flag token in the middle of a query + * string, followed by another key=value pair later on. + */ + ptr = amp; if (ptr) *ptr++ = '\0'; @@ -99,6 +106,8 @@ void extractcgiargs(void) continue; } + /* The nearest point of interest is a key=value pair, + * maybe followed by another amp and flag or assignment... */ *eq = '\0'; value = eq + 1; amp = strchr(value, '&'); From c21672df4f529be833d736f488a518540c2bcb63 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 9 Feb 2026 14:06:54 +0100 Subject: [PATCH 180/198] clients/upsstats.c: do_*link*() methods: err on the safe side and NULL-check the template_list/single vars before comparing strings [#2524] Signed-off-by: Jim Klimov --- clients/upsstats.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/clients/upsstats.c b/clients/upsstats.c index a26f79256d..923197a5f1 100644 --- a/clients/upsstats.c +++ b/clients/upsstats.c @@ -540,11 +540,11 @@ static void do_hostlink(void) printf("sys); - if (strcmp(template_single, "upsstats-single.html")) { + if (template_single && strcmp(template_single, "upsstats-single.html")) { printf("&template_single=%s", template_single); } - if (strcmp(template_list, "upsstats.html")) { + if (template_list && strcmp(template_list, "upsstats.html")) { printf("&template_list=%s", template_list); } @@ -568,11 +568,11 @@ static void do_treelink_json(const char *text) printf("sys); - if (strcmp(template_single, "upsstats-single.html")) { + if (template_single && strcmp(template_single, "upsstats-single.html")) { printf("&template_single=%s", template_single); } - if (strcmp(template_list, "upsstats.html")) { + if (template_list && strcmp(template_list, "upsstats.html")) { printf("&template_list=%s", template_list); } @@ -598,11 +598,11 @@ static void do_treelink(const char *text) printf("sys); - if (strcmp(template_single, "upsstats-single.html")) { + if (template_single && strcmp(template_single, "upsstats-single.html")) { printf("&template_single=%s", template_single); } - if (strcmp(template_list, "upsstats.html")) { + if (template_list && strcmp(template_list, "upsstats.html")) { printf("&template_list=%s", template_list); } From 1d2aee1a8ab2d16aa06cce1f08a75956c266ce67 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 9 Feb 2026 14:31:36 +0100 Subject: [PATCH 181/198] Introduce CUSTOM_TEMPLATE_LIST and CUSTOM_TEMPLATE_SINGLE settings in NUT CGI hosts.conf to constrain the permitted custom HTML template file names to a set that admins intend to use [#2524] Signed-off-by: Jim Klimov --- NEWS.adoc | 3 +- clients/upsstats.c | 171 ++++++++++++++++++++++++++++++++++---- conf/hosts.conf.sample | 33 +++++++- docs/man/hosts.conf.txt | 20 +++++ docs/man/upsstats.cgi.txt | 20 +++-- 5 files changed, 223 insertions(+), 24 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index 2b1d469ff4..ad32b08d8c 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -339,7 +339,8 @@ several `FSD` notifications into one executed action. [PR #3097] files now MUST start with (safety check that we are reading a template). [issue #3252, PR #3249] * (Experimental) Custom templates other than `upsstats{,-single}.html` can - now be specified as CGI parameters. [issue #2524, PR #3304] + now be specified as CGI parameters, if locally permitted via `hosts.conf`. + [issue #2524, PR #3304] - `upssched` tool updates: * Previously in PR #2896 (NUT releases v2.8.3 and v2.8.4) the `UPSNAME` and diff --git a/clients/upsstats.c b/clients/upsstats.c index 923197a5f1..0cfe4b3929 100644 --- a/clients/upsstats.c +++ b/clients/upsstats.c @@ -70,7 +70,11 @@ static UPSCONN_t ups; static FILE *tf; static long forofs = 0; -static ulist_t *ulhead = NULL, *currups = NULL; +static ulist_t *ulhead = NULL, *currups = NULL, + /* hijack the linked-list structure to store + * just filenames (as "sys") so far */ + *allowed_template_single_lhead = NULL, + *allowed_template_list_lhead = NULL; static int skip_clause = 0, skip_block = 0; @@ -1137,22 +1141,68 @@ static void parse_line(const char *buf) upsdebug_call_finished0(); } -static void display_template(const char *tfn) +/* type = 1 for upsstats-single.html (or custom copy), 2 for upsstats.html (list) */ +static void display_template(const char *tfn, int type) { char fn[NUT_PATH_MAX + 1], buf[LARGEBUF]; + ulist_t *tmp = NULL; upsdebug_call_starting_for_str1(tfn); - if (!tfn || !*tfn || strstr(tfn, "/") || strstr(tfn, "\\") || !strstr(tfn, ".htm")) { + if (!tfn || !*tfn || strstr(tfn, "/") || strstr(tfn, "\\")) { /* We only allow pre-configured templates in one managed location, with ".htm" in the name */ - fprintf(stderr, "upsstats: Can't open %s: %s: asked to look not exactly in the managed location\n", fn, strerror(errno)); + errno = EPERM; + fprintf(stderr, "upsstats: Can't open %s: %s: asked to look not exactly in the managed location\n", tfn, strerror(errno)); - printf("Error: can't open template file (%s): asked to look not exactly in the managed location\n", tfn); + printf("Error: can't open template file (%s): Not authorized\n", tfn); upsdebug_call_finished1(": subdir in template"); exit(EXIT_FAILURE); } + if (!strstr(tfn, ".htm")) { + /* We only allow pre-configured templates with ".htm" in the name */ + errno = EPERM; + fprintf(stderr, "upsstats: Can't open %s: %s: asked to look at not a *.htm* file\n", tfn, strerror(errno)); + + printf("Error: can't open template file (%s): Not authorized\n", tfn); + + upsdebug_call_finished1(": not a *.htm* file"); + exit(EXIT_FAILURE); + } + + if (type == 1) { + /* Check if [custom] single template is allowed + * (built-in/legacy default starts the list) */ + tmp = allowed_template_single_lhead; + while (tmp) { + if (!strcmp(tmp->sys, tfn)) + break; + tmp = (ulist_t *)tmp->next; + } + } else + if (type == 2) { + /* Check if [custom] list template is allowed + * (built-in/legacy default starts the list) */ + tmp = allowed_template_list_lhead; + while (tmp) { + if (!strcmp(tmp->sys, tfn)) + break; + tmp = (ulist_t *)tmp->next; + } + } + + if (!tmp) { + /* We only allow pre-configured templates permitted via hosts.conf */ + errno = EPERM; + fprintf(stderr, "upsstats: Can't open %s: %s: Not authorized: template not permitted via hosts.conf\n", tfn, strerror(errno)); + + printf("Error: can't open template file (%s): Not authorized\n", tfn); + + upsdebug_call_finished1(": template not permitted via hosts.conf"); + exit(EXIT_FAILURE); + } + snprintf(fn, sizeof(fn), "%s/%s", confpath(), tfn); tf = fopen(fn, "rb"); @@ -1291,13 +1341,69 @@ static void add_ups(char *sys, char *desc) ulhead = tmp; } +static void add_allowed_template_list(char *tfn) +{ + ulist_t *tmp, *last; + + if (!tfn || !*tfn) + return; + + tmp = last = allowed_template_list_lhead; + + while (tmp) { + if (!strcmp(tmp->sys, tfn)) + return; + last = tmp; + tmp = (ulist_t *)tmp->next; + } + + tmp = (ulist_t *)xmalloc(sizeof(ulist_t)); + + tmp->sys = xstrdup(tfn); + tmp->desc = NULL; + tmp->next = NULL; + + if (last) + last->next = tmp; + else + allowed_template_list_lhead = tmp; +} + +static void add_allowed_template_single(char *tfn) +{ + ulist_t *tmp, *last; + + if (!tfn || !*tfn) + return; + + tmp = last = allowed_template_single_lhead; + + while (tmp) { + if (!strcmp(tmp->sys, tfn)) + return; + last = tmp; + tmp = (ulist_t *)tmp->next; + } + + tmp = (ulist_t *)xmalloc(sizeof(ulist_t)); + + tmp->sys = xstrdup(tfn); + tmp->desc = NULL; + tmp->next = NULL; + + if (last) + last->next = tmp; + else + allowed_template_single_lhead = tmp; +} + /* called for fatal errors in parseconf like malloc failures */ static void upsstats_hosts_err(const char *errmsg) { upslogx(LOG_ERR, "Fatal error in parseconf(hosts.conf): %s", errmsg); } -static void load_hosts_conf(void) +static void load_hosts_conf(int handle_MONITOR) { char fn[NUT_PATH_MAX + 1]; PCONF_CTX_t ctx; @@ -1335,18 +1441,29 @@ static void load_hosts_conf(void) continue; } + if (ctx.numargs < 2) + continue; + + /* CUSTOM_TEMPLATE_LIST */ + if (!strcmp(ctx.arglist[0], "CUSTOM_TEMPLATE_LIST")) + add_allowed_template_list(ctx.arglist[1]); + + /* CUSTOM_TEMPLATE_SINGLE */ + if (!strcmp(ctx.arglist[0], "CUSTOM_TEMPLATE_SINGLE")) + add_allowed_template_single(ctx.arglist[1]); + if (ctx.numargs < 3) continue; /* MONITOR */ - if (!strcmp(ctx.arglist[0], "MONITOR")) + if (handle_MONITOR && !strcmp(ctx.arglist[0], "MONITOR")) add_ups(ctx.arglist[1], ctx.arglist[2]); } pconf_finish(&ctx); - if (!ulhead) { + if (!ulhead && handle_MONITOR) { /* Don't print HTML here if we are in JSON mode. * The JSON function will handle the error. */ @@ -1386,7 +1503,7 @@ static void display_single(void) if (treemode) display_tree(1); else - display_template(template_single); + display_template(template_single, 1); upscli_disconnect(&ups); upsdebug_call_finished0(); @@ -1428,7 +1545,7 @@ static void display_json(void) add_ups(monhost, monhostdesc); currups = ulhead; } else { - load_hosts_conf(); /* This populates ulhead */ + load_hosts_conf(1); /* This populates ulhead */ currups = ulhead; } @@ -1576,9 +1693,6 @@ int main(int argc, char **argv) nut_debug_level = i; } - /* Built-in defaults */ - template_single = xstrdup("upsstats-single.html"); - template_list = xstrdup("upsstats.html"); #ifdef NUT_CGI_DEBUG_UPSSTATS # if (NUT_CGI_DEBUG_UPSSTATS - 0 < 1) @@ -1597,6 +1711,10 @@ int main(int argc, char **argv) printf("

NUT CGI Debugging enabled, level: %d

\n\n", nut_debug_level); } + /* Built-in defaults */ + template_single = xstrdup("upsstats-single.html"); + template_list = xstrdup("upsstats.html"); + extractcgiargs(); upscli_init_default_connect_timeout(NULL, NULL, UPSCLI_DEFAULT_CONNECT_TIMEOUT); @@ -1634,14 +1752,18 @@ int main(int argc, char **argv) printf("Pragma: no-cache\n"); printf("\n"); - /* if a host is specified, use upsstats-single.html instead */ + /* if a host is specified, use upsstats-single.html instead + * of listing whatever we know about with upsstats.html */ + add_allowed_template_single("upsstats-single.html"); + add_allowed_template_list("upsstats.html"); if (monhost) { + load_hosts_conf(0); display_single(); } else { /* default: multimon replacement mode */ - load_hosts_conf(); + load_hosts_conf(1); currups = ulhead; - display_template(template_list); + display_template(template_list, 2); } /* Clean up memory */ @@ -1659,5 +1781,22 @@ int main(int argc, char **argv) free(template_single); free(template_list); + /* Free storage of allowed template names (reusing same kind of structure as UPSes) */ + while (allowed_template_single_lhead) { + currups = (ulist_t *)allowed_template_single_lhead->next; + free(allowed_template_single_lhead->sys); + free(allowed_template_single_lhead->desc); + free(allowed_template_single_lhead); + allowed_template_single_lhead = currups; + } + + while (allowed_template_list_lhead) { + currups = (ulist_t *)allowed_template_list_lhead->next; + free(allowed_template_list_lhead->sys); + free(allowed_template_list_lhead->desc); + free(allowed_template_list_lhead); + allowed_template_list_lhead = currups; + } + return 0; } diff --git a/conf/hosts.conf.sample b/conf/hosts.conf.sample index 37e561e78b..ef9fb8b525 100644 --- a/conf/hosts.conf.sample +++ b/conf/hosts.conf.sample @@ -9,8 +9,21 @@ # ----------------------------------------------------------------------- # # upsstats will use the list of MONITOR entries when displaying the -# default template (upsstats.html). The "FOREACHUPS" directive in the -# template will use this file to find systems running upsd. +# list template (default upsstats.html). The "FOREACHUPS" directive +# in the template will use this file to find systems running upsd. +# +# upsstats allows to use custom HTML template files for some of its +# outputs (JSON and "treemode" mark-ups are currently hard-coded in +# the binary), which you can specify in the query string part of the +# URI (in your `index.html` and/or added cells of `header.html`) as e.g. +# .../cgi-bin/upsstats.cgi?template_single=upsstats-custom-single.html&template_list=upsstats-custom-list.html +# Specific file names must be permitted below with `CUSTOM_TEMPLATE_LIST` +# or `CUSTOM_TEMPLATE_SINGLE` directive, as applicable; they must contain +# the `.htm` substring, and be located directly in the NUT configuration +# directory (same as default templates). If custom templates are used +# in the original request URI, they will be automatically suffixed to +# generated links (primarily HOSTLINK, but also just in case added to +# TREELINK and TREELINK_JSON). # # upsstats and upsimage also use this file to determine if a host may be # monitored. This keeps evil people from using your system to annoy @@ -30,3 +43,19 @@ # MONITOR myups@localhost "Local UPS" # MONITOR su2200@10.64.1.1 "Finance department" # MONITOR matrix@shs-server.example.edu "Sierra High School data room #1" + +# ----------------------------------------------------------------------- +# +# Allowed custom template file (adapted copy of upsstats.html) for listing +# your devices, which must be located in the same configuration directory +# and contain `.htm` in the file name. +# +# CUSTOM_TEMPLATE_LIST + +# ----------------------------------------------------------------------- +# +# Allowed custom template file (adapted copy of upsstats-single.html) for +# listing details about a single device, which must be located in the same +# configuration directory and contain `.htm` in the file name. +# +# CUSTOM_TEMPLATE_SINGLE diff --git a/docs/man/hosts.conf.txt b/docs/man/hosts.conf.txt index 940329b871..9f57e657d4 100644 --- a/docs/man/hosts.conf.txt +++ b/docs/man/hosts.conf.txt @@ -40,6 +40,26 @@ The description must be one element, so if it has spaces, then it must be wrapped with quotes as shown above. The default hostname is "localhost". +*CUSTOM_TEMPLATE_LIST* 'filename':: +*CUSTOM_TEMPLATE_SINGLE* 'filename':: + +linkman:upsstats[8] allows to use custom HTML template files for some of +its outputs (JSON and "treemode" mark-ups are currently hard-coded in +the binary), which you can specify in the query string part of the +URI (in your `index.html` and/or added cells of `header.html`) as e.g. +------ +.../cgi-bin/upsstats.cgi?template_single=custom-s.htm&template_list=custom-l.htm +------ ++ +Specific file names for a specific role must be permitted with these +directives (can be repeated). File names must contain the `.htm` sub-string +and must be located directly in the NUT configuration directory (same as +default templates). If custom templates are used in the original request +URI, they will be automatically suffixed to generated links (primarily +`HOSTLINK`, but also just in case added to `TREELINK` and `TREELINK_JSON`, +see linkman:upsstats.html[5] for more details). + + SEE ALSO -------- diff --git a/docs/man/upsstats.cgi.txt b/docs/man/upsstats.cgi.txt index 5665e28560..b30a37a03e 100644 --- a/docs/man/upsstats.cgi.txt +++ b/docs/man/upsstats.cgi.txt @@ -48,14 +48,24 @@ The web page that is displayed is actually a template containing commands to `upsstats` which are replaced by status information. The default file used for the overview of devices is `upsstats.html`. -An alternate template may be provided by `&template_list=...` CGI query option. +An alternate template may be provided by `&template_list=...` CGI +query option; relevant file must be allowed via `CUSTOM_TEMPLATE_LIST` +option in linkman:hosts.conf[5]. When monitoring a single UPS, the file displayed is `upsstats-single.html`. -An alternate template may be provided by `&template_single=...` CGI query option. +An alternate template may be provided by `&template_single=...` CGI +query option; relevant file must be allowed via `CUSTOM_TEMPLATE_SINGLE` +option in linkman:hosts.conf[5]. -Alternate templates must be structured similarly to default ones, located in the -same directory, and contain `.htm` in the file name. +Alternate templates must be structured similarly to default ones, +located in the same directory, and contain `.htm` in the file name. +You can specify in the query string part of the URI (for example, +in your local `index.html` and/or added cells of `header.html`) as e.g. + +------ +.../cgi-bin/upsstats.cgi?template_single=custom-s.html&template_list=custom-l.html +------ The format of these files, including the possible commands, is documented in linkman:upsstats.html[5]. @@ -88,7 +98,7 @@ parameter is also provided: In both modes, each UPS object includes: * *host*: The UPS identifier (e.g., "myups@localhost") -* *desc*: The host description from ``hosts.conf`` +* *desc*: The host description from `hosts.conf` * *status_raw*: The raw status string (e.g., "OL") * *status_parsed*: An array of human-readable status strings (e.g., ["Online"]) From 8b444e3ef61bebee58e01e76ff0e2b16febcb0be Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 9 Feb 2026 14:32:37 +0100 Subject: [PATCH 182/198] clients/upsstats.c: display_template(): if rejecting a file, or after other errors, use HTML
tags in the printout (especially if debug is on) [#2524] Signed-off-by: Jim Klimov --- clients/upsstats.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/clients/upsstats.c b/clients/upsstats.c index 0cfe4b3929..e1d310b192 100644 --- a/clients/upsstats.c +++ b/clients/upsstats.c @@ -1152,9 +1152,9 @@ static void display_template(const char *tfn, int type) if (!tfn || !*tfn || strstr(tfn, "/") || strstr(tfn, "\\")) { /* We only allow pre-configured templates in one managed location, with ".htm" in the name */ errno = EPERM; - fprintf(stderr, "upsstats: Can't open %s: %s: asked to look not exactly in the managed location\n", tfn, strerror(errno)); + fprintf(stderr, "upsstats: Can't open %s: %s: asked to look not exactly in the managed location
\n", tfn, strerror(errno)); - printf("Error: can't open template file (%s): Not authorized\n", tfn); + printf("Error: can't open template file (%s): Not authorized
\n", tfn); upsdebug_call_finished1(": subdir in template"); exit(EXIT_FAILURE); @@ -1163,9 +1163,9 @@ static void display_template(const char *tfn, int type) if (!strstr(tfn, ".htm")) { /* We only allow pre-configured templates with ".htm" in the name */ errno = EPERM; - fprintf(stderr, "upsstats: Can't open %s: %s: asked to look at not a *.htm* file\n", tfn, strerror(errno)); + fprintf(stderr, "upsstats: Can't open %s: %s: asked to look at not a *.htm* file
\n", tfn, strerror(errno)); - printf("Error: can't open template file (%s): Not authorized\n", tfn); + printf("Error: can't open template file (%s): Not authorized
\n", tfn); upsdebug_call_finished1(": not a *.htm* file"); exit(EXIT_FAILURE); @@ -1195,9 +1195,9 @@ static void display_template(const char *tfn, int type) if (!tmp) { /* We only allow pre-configured templates permitted via hosts.conf */ errno = EPERM; - fprintf(stderr, "upsstats: Can't open %s: %s: Not authorized: template not permitted via hosts.conf\n", tfn, strerror(errno)); + fprintf(stderr, "upsstats: Can't open %s: %s: Not authorized: template not permitted via hosts.conf
\n", tfn, strerror(errno)); - printf("Error: can't open template file (%s): Not authorized\n", tfn); + printf("Error: can't open template file (%s): Not authorized
\n", tfn); upsdebug_call_finished1(": template not permitted via hosts.conf"); exit(EXIT_FAILURE); @@ -1208,18 +1208,18 @@ static void display_template(const char *tfn, int type) tf = fopen(fn, "rb"); if (!tf) { - fprintf(stderr, "upsstats: Can't open %s: %s\n", fn, strerror(errno)); + fprintf(stderr, "upsstats: Can't open %s: %s
\n", fn, strerror(errno)); - printf("Error: can't open template file (%s)\n", tfn); + printf("Error: can't open template file (%s)
\n", tfn); upsdebug_call_finished1(": no template"); exit(EXIT_FAILURE); } if (!fgets(buf, sizeof(buf), tf)) { - fprintf(stderr, "upsstats: template file %s seems to be empty (fgets failed): %s\n", fn, strerror(errno)); + fprintf(stderr, "upsstats: template file %s seems to be empty (fgets failed): %s
\n", fn, strerror(errno)); - printf("Error: template file %s seems to be empty\n", tfn); + printf("Error: template file %s seems to be empty
\n", tfn); upsdebug_call_finished1(": empty template"); exit(EXIT_FAILURE); @@ -1229,9 +1229,9 @@ static void display_template(const char *tfn, int type) if (!strncmp(buf, "@NUT_UPSSTATS_TEMPLATE", 22)) { parse_line(buf); } else { - fprintf(stderr, "upsstats: template file %s does not start with NUT_UPSSTATS_TEMPLATE command\n", fn); + fprintf(stderr, "upsstats: template file %s does not start with NUT_UPSSTATS_TEMPLATE command
\n", fn); - printf("Error: template file %s does not start with NUT_UPSSTATS_TEMPLATE command\n", tfn); + printf("Error: template file %s does not start with NUT_UPSSTATS_TEMPLATE command
\n", tfn); upsdebug_call_finished1(": not a valid template"); exit(EXIT_FAILURE); From b993e630395855e66c4fab207631555e1869d5d9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 9 Feb 2026 16:39:47 +0100 Subject: [PATCH 183/198] scripts/Windows/wininit.c, NEWS.adoc, docs/man/nut.exe.txt: support exiting from "nut.exe -N" with Ctrl+C [#3312] Signed-off-by: Jim Klimov --- NEWS.adoc | 5 +++ docs/man/nut.exe.txt | 6 ++++ scripts/Windows/wininit.c | 73 +++++++++++++++++++++++++++++++++++++-- 3 files changed, 82 insertions(+), 2 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index b618b57d3c..07251d523a 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -114,6 +114,11 @@ https://github.com/networkupstools/nut/milestone/12 operations. (Re-)registration of the "Network UPS Tools" service should now populate a nice description of it. The `-U` (uninstall) action should now also try to stop the service first. [PR #3235] + * Using `nut.exe -N` for testing and pressing 'Ctrl+C' should now cause the + started daemons to be killed off. Previously they would linger and e.g. + preclude subsequent experiments with the service wrapper. Console close + events are ignored, so there is a way to indefinitely keep the daemons + started by test-mode wrapper running (kill via Task Manager). [#3312] * Revised WIN32 `WSAStartup()` and registration of `atexit(WSACleanup)` to only be done once per program (and cleanups to be always registered); this impacts the C `libupsclient` and C++ `libnutclient` libraries (and so most diff --git a/docs/man/nut.exe.txt b/docs/man/nut.exe.txt index ed4e233bc3..a9717a6976 100644 --- a/docs/man/nut.exe.txt +++ b/docs/man/nut.exe.txt @@ -99,6 +99,12 @@ Install as a Windows service called "Network UPS Tools". Does not start it. *-N*:: Run once in non-service mode (for troubleshooting). ++ +Since NUT v2.8.5, using `nut.exe -N` for testing and pressing 'Ctrl+C' should +cause the started daemons to be killed off. Previously they would linger and +e.g. preclude subsequent experiments with the service wrapper. Console close +events are ignored, so there is a way to indefinitely keep the daemons started +by the test-mode wrapper running (kill later if needed via Task Manager). *start*:: Install as a Windows service called "Network UPS Tools" (if not yet done), diff --git a/scripts/Windows/wininit.c b/scripts/Windows/wininit.c index 864c7ce05f..a1fc5577a1 100644 --- a/scripts/Windows/wininit.c +++ b/scripts/Windows/wininit.c @@ -38,6 +38,7 @@ typedef struct conn_s { struct conn_s *next; } conn_t; +static int exit_flag = 0; static DWORD upsd_pid = 0; static DWORD upsmon_pid = 0; static DWORD upsdrvctl_pid = 0; @@ -581,6 +582,54 @@ static void ReportSvcStatus( SetServiceStatus(SvcStatusHandle, &SvcStatus); } +/* For `nut.exe -N` runs + * https://learn.microsoft.com/en-us/windows/console/registering-a-control-handler-function + */ +static BOOL WINAPI ConsoleCtrlHandler(DWORD Ctrl) +{ + switch(Ctrl) + { + case CTRL_C_EVENT: + print_event(LOG_INFO, "Ctrl+C received on console"); + exit_flag = 1; /* Break SvcMain() infinite loop */ + if (upsmon_pid) { + print_event(LOG_INFO, "Stopping upsmon"); + stop_upsmon(); + } + if (upsd_pid) { + print_event(LOG_INFO, "Stopping upsd"); + stop_upsd(); + } + if (upsdrvctl_pid) { + print_event(LOG_INFO, "Stopping drivers"); + stop_drivers(); + } + exit_flag = 2; /* Allow to finish SvcMain() infinite loop and proceed to exit() */ + /* confirm that the user wants to exit */ + return TRUE; + + case CTRL_CLOSE_EVENT: + print_event(LOG_INFO, "Close event received on console, currently ignored"); + return FALSE; + + case CTRL_BREAK_EVENT: + print_event(LOG_INFO, "Ctrl+Break event received on console, currently ignored"); + return FALSE; + + /* TOTHINK: Do we in fact want these two handled specially? */ + case CTRL_LOGOFF_EVENT: + print_event(LOG_INFO, "Logoff event received on console, currently ignored"); + return FALSE; + + case CTRL_SHUTDOWN_EVENT: + print_event(LOG_INFO, "Shutdown event received on console, currently ignored"); + return FALSE; + + default: + return FALSE; + } +} + static void WINAPI SvcCtrlHandler(DWORD Ctrl) { switch(Ctrl) @@ -659,7 +708,7 @@ static void close_all(void) static void WINAPI SvcMain(DWORD argc, LPTSTR *argv) { DWORD ret; - HANDLE handles[MAXIMUM_WAIT_OBJECTS]; /* 64 per current WinAPI sheaders */ + HANDLE handles[MAXIMUM_WAIT_OBJECTS]; /* 64 per current WinAPI headers */ size_t maxhandle = 0; pipe_conn_t *conn; DWORD priority; @@ -697,7 +746,7 @@ static void WINAPI SvcMain(DWORD argc, LPTSTR *argv) SvcReady(); } - while (1) { + while (!exit_flag) { maxhandle = 0; memset(&handles, 0, sizeof(handles)); @@ -766,6 +815,10 @@ static void WINAPI SvcMain(DWORD argc, LPTSTR *argv) } } + /* Do not check on daemons nor revive them in vain if we are exiting */ + if (exit_flag) + break; + /* Check on each daemon: Was it supposed to run? Does it still? */ if (upsdrvctl_pid) { DWORD status = 0; @@ -785,6 +838,10 @@ static void WINAPI SvcMain(DWORD argc, LPTSTR *argv) } } + /* Do not check on daemons nor revive them in vain if we are exiting */ + if (exit_flag) + break; + if (upsd_pid) { DWORD status = 0; BOOL res = FALSE; @@ -803,6 +860,10 @@ static void WINAPI SvcMain(DWORD argc, LPTSTR *argv) } } + /* Do not check on daemons nor revive them in vain if we are exiting */ + if (exit_flag) + break; + if (upsmon_pid) { DWORD status = 0; BOOL res = FALSE; @@ -821,6 +882,10 @@ static void WINAPI SvcMain(DWORD argc, LPTSTR *argv) } } } + + while (exit_flag < 2) { + Sleep(1000); + } } static void help(const char *arg_progname) @@ -1020,6 +1085,10 @@ int main(int argc, char **argv) } } else { + if (!SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE)) { + upslog_with_errno(LOG_ERR, "SetConsoleCtrlHandler failed, may ignore Ctrl+C"); + } + SvcMain(argc, argv); } From 9a805e28c582205ed1c5234f8ef632ce1082b9c8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 10 Feb 2026 11:17:28 +0100 Subject: [PATCH 184/198] configure.ac: refer to docs with Solaris man section layout [#3314] Signed-off-by: Jim Klimov --- configure.ac | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 465932a477..b7c20dff69 100644 --- a/configure.ac +++ b/configure.ac @@ -2782,7 +2782,8 @@ DEFAULT_MAN_DIR_AS_BASE='m4nut_DEFAULT_MAN_DIR_AS_BASE' case "${target_os}" in solaris*|sunos*|SunOS*|illumos*) - dnl Note: this regards target OS standard layout + dnl Note: this regards target OS standard layout as documented in + dnl https://docs.oracle.com/cd/E23824_01/html/821-1451/gladp.html dnl but may not fit certain packaging projects DEFAULT_MAN_SECTION_CMD_SYS="1m" DEFAULT_MAN_DIR_AS_BASE="no" From dea9c11ed2a4eac476c1a01e6199506bc847f606 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 10 Feb 2026 11:18:00 +0100 Subject: [PATCH 185/198] configure.ac: comment the trouble with automating Solaris man section layout when we only use dist-tarball pre-built pages [#3314] Signed-off-by: Jim Klimov --- configure.ac | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/configure.ac b/configure.ac index b7c20dff69..c497b19461 100644 --- a/configure.ac +++ b/configure.ac @@ -2785,6 +2785,11 @@ case "${target_os}" in dnl Note: this regards target OS standard layout as documented in dnl https://docs.oracle.com/cd/E23824_01/html/821-1451/gladp.html dnl but may not fit certain packaging projects + dnl FIXME https://github.com/networkupstools/nut/issue/3314 : + dnl If we have no tools or wish to build man pages, and would + dnl just deliver what we have in dist tarball (or otherwise), we + dnl must keep the original names and cross-links of files we copy + dnl (no section substitutions then!) DEFAULT_MAN_SECTION_CMD_SYS="1m" DEFAULT_MAN_DIR_AS_BASE="no" ;; From 933f2c1ed8d9c9bc0fa23261879d2bdb5aaa0554 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 10 Feb 2026 11:18:32 +0100 Subject: [PATCH 186/198] configure.ac: note more visibly that we can fall back to dist-tarball pre-built pages when we have only them and want something installed [#3314] NOTE: want_disted_doc_man=yes is set lower in code, hopefully we do reach that part; else have inputs for troubleshooting the recipes. Signed-off-by: Jim Klimov --- configure.ac | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/configure.ac b/configure.ac index c497b19461..f486b18ac4 100644 --- a/configure.ac +++ b/configure.ac @@ -4129,6 +4129,11 @@ dnl not fail if we have no tools to generate it (so add to SKIP list). ( cd "$DOCTESTDIR" && ${A2X} --format manpage --destination-dir=. --xsltproc-opts="--nonet" "${abs_srcdir}"/docs/man/snmp-ups.txt && test -s snmp-ups.8 ) && can_build_doc_man=yes rm -f "${DOCTESTDIR}"/snmp-ups.8 fi + if test x"${can_build_doc_man}" != xyes && test x"${have_disted_doc_man}" = xyes && test x"${nut_doc_build_target_flag}" != xno ; then + dnl https://github.com/networkupstools/nut/issue/3314 + AC_MSG_NOTICE([Seems we can not build man pages, but have some pre-built ones...]) + dnl want_disted_doc_man=yes + fi can_install_doc_man=no if test "${want_disted_doc_man}" = yes && ( test "${have_disted_doc_man}" = yes || test "${have_disted_doc_man}" = yes-placeholder ) ; then AC_MSG_NOTICE([Requested, and can, install pre-built distributed copies of ${nut_doc_build_target_base} documentation]) From 86b84c95188839673ff793a32212c3d35da80c28 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 10 Feb 2026 11:24:34 +0100 Subject: [PATCH 187/198] configure.ac: when falling back to can_install_doc_man=yes do also try to touch the artifacts as when we do upon deliberate choice [#3314] Signed-off-by: Jim Klimov --- configure.ac | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configure.ac b/configure.ac index f486b18ac4..da1730b8eb 100644 --- a/configure.ac +++ b/configure.ac @@ -4166,6 +4166,9 @@ dnl not fail if we have no tools to generate it (so add to SKIP list). if test "${have_disted_doc_man}" = yes || test "${have_disted_doc_man}" = yes-placeholder ; then AC_MSG_WARN([Unable to build ${nut_doc_build_target_base} documentation, but can install pre-built distributed copies]) DOC_INSTALL_DISTED_MANS="yes" + dnl Avoid rebuilding existing build products due to their timestamp dependencies; + dnl ignore "touch" errors due to e.g. read-only sources (distcheck, ISO image, etc.): + touch -r "${abs_srcdir}"/docs/man/Makefile.am "${abs_srcdir}"/docs/man/*.{1,2,3,4,5,6,7,8,9}* "${abs_srcdir}"/docs/man/*.{txt,xml,html,pdf} || true can_install_doc_man=yes else AC_MSG_WARN([Unable to build ${nut_doc_build_target_base} documentation, and unable to install pre-built distributed copies because they are absent; will reflect on this below]) From aa12c172d294c2e35b118d363be9effbfe89a7c5 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 29 Jan 2026 14:47:22 +0100 Subject: [PATCH 188/198] docs/maintainer-guide.txt: move VERSION_FORCED* file preparation (involves git tagging) to after changing committed files Signed-off-by: Jim Klimov --- docs/maintainer-guide.txt | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/docs/maintainer-guide.txt b/docs/maintainer-guide.txt index c1d684b795..b8b4915153 100644 --- a/docs/maintainer-guide.txt +++ b/docs/maintainer-guide.txt @@ -164,9 +164,23 @@ symbol names and API versions, similar to what `GNUC` or `SUNW` libraries do. * bump the release identification (consider committing as one commit later on): ** see `docs/nut-versioning.adoc` for details about NUT SEMVER spec and practice +** revise `.github/workflows/PyNUTClient.yml` for fallback `TAG_NAME` naming +** revise `appveyor.yml` for branch naming +** revise `scripts/Windows/build-mingw-nut.sh` for fallback value of `VER_OPT` ** update the fallback `NUT_DEFAULT_VERSION` in `tools/gitlog2version.sh` to - (ex: `2.8.0`), and provide the `VERSION_FORCED` - and `VERSION_FORCED_SEMVER` files (to same effect but more explicitly and + (ex: `2.8.0`) +*** DOUBLE-CHECK that the `NUT_DEFAULT_VERSION` in `tools/gitlog2version.sh` + is an `X.Y.Z` triplet, without the fourth `.1` suffix, for the release! +*** Note that since NUT v2.8.3 this script dictates the version propagated by + the `configure` script, so direct changes of `AC_INIT` there are no longer + needed +** commit with a relevant release message, e.g.: ++ +---- +:; git commit -sm 'Update versions for release of NUT v2.8.0' +---- +** provide the `VERSION_FORCED` and `VERSION_FORCED_SEMVER` files (to same + effect as fallback in `tools/gitlog2version.sh` but more explicitly and visibly) in the local workspace to be added to the `dist` archive tarball file (DO NOT add them to git to avoid confusion later, or revert any such addition after the release -- still has a chance to confuse e.g. branches @@ -214,19 +228,6 @@ VERSION_FORCED_SEMVER:NUT_VERSION_FORCED_SEMVER='2.8.3' # if file names in your top_srcdir are removed: :; ln .relver/* . ---- -*** DOUBLE-CHECK that the `NUT_DEFAULT_VERSION` in `tools/gitlog2version.sh` - is an `X.Y.Z` triplet, without the fourth `.1` suffix, for the release! -*** Note that since NUT v2.8.3 this script dictates the version propagated by - the `configure` script, so direct changes of `AC_INIT` there are no longer - needed -** revise `.github/workflows/PyNUTClient.yml` for fallback `TAG_NAME` naming -** revise `appveyor.yml` for branch naming -** revise `scripts/Windows/build-mingw-nut.sh` for fallback value of `VER_OPT` -** commit with a relevant release message, e.g.: -+ ----- -:; git commit -sm 'Update versions for release of NUT v2.8.0' ----- * last-minute update against possible master-branch changes (and be sure to apply the release-version changes described above to your local copy of From 45d4d3b8270658a73064e5320f14c92094db5b41 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 29 Jan 2026 14:49:35 +0100 Subject: [PATCH 189/198] docs/maintainer-guide.txt: add OBS reference recipes to watch for version bump when releasing Signed-off-by: Jim Klimov --- docs/maintainer-guide.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/maintainer-guide.txt b/docs/maintainer-guide.txt index b8b4915153..8bd281a027 100644 --- a/docs/maintainer-guide.txt +++ b/docs/maintainer-guide.txt @@ -167,6 +167,9 @@ symbol names and API versions, similar to what `GNUC` or `SUNW` libraries do. ** revise `.github/workflows/PyNUTClient.yml` for fallback `TAG_NAME` naming ** revise `appveyor.yml` for branch naming ** revise `scripts/Windows/build-mingw-nut.sh` for fallback value of `VER_OPT` +** revise `scripts/obs/debian.changelog` (at least a dummy entry) +** revise `scripts/obs/nut.dsc` and `scripts/obs/nut.spec` for their `Version` + fields ** update the fallback `NUT_DEFAULT_VERSION` in `tools/gitlog2version.sh` to (ex: `2.8.0`) *** DOUBLE-CHECK that the `NUT_DEFAULT_VERSION` in `tools/gitlog2version.sh` From 6ee0afd4b78e5897cae5842da859cb098440da5e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 29 Jan 2026 14:55:36 +0100 Subject: [PATCH 190/198] scripts/Windows/build-mingw-nut.sh: add license header Signed-off-by: Jim Klimov --- scripts/Windows/build-mingw-nut.sh | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/scripts/Windows/build-mingw-nut.sh b/scripts/Windows/build-mingw-nut.sh index b5bbb55443..aca64aa86b 100755 --- a/scripts/Windows/build-mingw-nut.sh +++ b/scripts/Windows/build-mingw-nut.sh @@ -4,6 +4,20 @@ # # script to cross compile NUT for Windows from Linux using MinGW-w64 # http://mingw-w64.sourceforge.net/ +# +# 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 +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. #set -x From 6ecf771cfbb1b91ae20c94a02413df7e5f89d6a5 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 29 Jan 2026 14:56:58 +0100 Subject: [PATCH 191/198] docs/maintainer-guide.txt: GHA file for PyNUTClient was renamed Signed-off-by: Jim Klimov --- docs/maintainer-guide.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/maintainer-guide.txt b/docs/maintainer-guide.txt index 8bd281a027..2fbbe4a3e3 100644 --- a/docs/maintainer-guide.txt +++ b/docs/maintainer-guide.txt @@ -164,7 +164,7 @@ symbol names and API versions, similar to what `GNUC` or `SUNW` libraries do. * bump the release identification (consider committing as one commit later on): ** see `docs/nut-versioning.adoc` for details about NUT SEMVER spec and practice -** revise `.github/workflows/PyNUTClient.yml` for fallback `TAG_NAME` naming +** revise `.github/workflows/08-PyNUTClient.yml` for fallback `TAG_NAME` naming ** revise `appveyor.yml` for branch naming ** revise `scripts/Windows/build-mingw-nut.sh` for fallback value of `VER_OPT` ** revise `scripts/obs/debian.changelog` (at least a dummy entry) From 627cecb868c588954d0222bc320feb2724f81f4b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 29 Jan 2026 18:00:30 +0100 Subject: [PATCH 192/198] Revert ".obs/workflows.yml: separate project builds with what looks like RC tags to use a separate OBS template (tweaked to change the dash into tilde for packaging versions) [#1209]" This reverts commit cced83a58d8d980cbeaad019522ab0f0c25d77e7: the currently deployed OBS service does not filter by "tags"... sadly. Signed-off-by: Jim Klimov --- .obs/workflows.yml | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/.obs/workflows.yml b/.obs/workflows.yml index 34b217483f..013722d0f3 100644 --- a/.obs/workflows.yml +++ b/.obs/workflows.yml @@ -28,22 +28,3 @@ release_tag: target_project: home:networkupstools:nut-releases filters: event: tag_push - tags: - only: - - "v[0-9]+.[0-9]+.[0-9]+" - ignore: - # v1.2.3-rc1, these need a different regex in _service of template project - - "*-*" - -release_candidate_tag: - steps: - - branch_package: - source_project: home:networkupstools:nut-stable-rc - source_package: "%{SCM_REPOSITORY_NAME}" - target_project: home:networkupstools:nut-releases - filters: - event: tag_push - tags: - only: - # v1.2.3-rc1, these need a different regex in _service of template project - - "v[0-9]+.[0-9]+.[0-9]+-.*" From 2cd8817a6a0c15b8d4d29820c83fac934e06bc93 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 11 Feb 2026 18:55:38 +0100 Subject: [PATCH 193/198] conf/upsstats.html.sample.in: drop duplicate @REFRESH@ directive [#3316] Signed-off-by: Jim Klimov --- conf/upsstats.html.sample.in | 1 - 1 file changed, 1 deletion(-) diff --git a/conf/upsstats.html.sample.in b/conf/upsstats.html.sample.in index 01b87e3d7b..9d9c007d9f 100644 --- a/conf/upsstats.html.sample.in +++ b/conf/upsstats.html.sample.in @@ -41,7 +41,6 @@ th, td{padding:0.5ex;} .t2{background:#0f0;} -@REFRESH@ From eca41b7b93062966483c1199a188b0f78ebf0358 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 11 Feb 2026 18:51:51 +0100 Subject: [PATCH 194/198] clients/upsstats.c, docs/man/upsstats.html.txt: extend @STATUS@ to inject any separators, not only
[#3316] Keep
as legacy default, to work with older upsstats*.html templates. Closes: #2525 Signed-off-by: Jim Klimov --- NEWS.adoc | 2 ++ clients/upsstats.c | 16 ++++++++++++---- docs/man/upsstats.html.txt | 7 ++++++- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index 63622e4fe5..21599e1ed9 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -346,6 +346,8 @@ several `FSD` notifications into one executed action. [PR #3097] * Now has JSON output mode via `?json` (or `&json`) CGI query parameter. New `@TREELINK_JSON@` keyword added and HTML templates updated to expose these JSON documents when browsing. [issue #2524, PRs #3171, #3249] + * The `@STATUS@` directive now optionally supports separators (not only + the hard-coded `
` of the older versions. [issue #2525, PR #3318] * Handle `device.model` in addition to `ups.model` in upsstats HTML templates. [#3180] * Introduced a `@NUT_UPSSTATS_TEMPLATE@` command which the HTML template diff --git a/clients/upsstats.c b/clients/upsstats.c index e1d310b192..c7b6dec330 100644 --- a/clients/upsstats.c +++ b/clients/upsstats.c @@ -227,9 +227,9 @@ static void parse_var(const char *var) upsdebug_call_finished0(); } -static void do_status(void) +static void do_status(const char *sep) { - int i; + int i, count = 0; char status[SMALLBUF], *ptr, *last = NULL; upsdebug_call_starting0(); @@ -244,7 +244,9 @@ static void do_status(void) for (i = 0; stattab[i].name != NULL; i++) { if (!strcasecmp(ptr, stattab[i].name)) { - printf("%s
", stattab[i].desc); + /* Note: sep="\0" is a valid case so we do not check for *sep */ + printf("%s%s", count ? (sep ? sep : "
") : "", stattab[i].desc); + count++; } } } @@ -926,8 +928,14 @@ static int do_command(char *cmd) return 1; } + if (!strncmp(cmd, "STATUS ", 7)) { + do_status(&cmd[7]); + upsdebug_call_finished0(); + return 1; + } + if (!strcmp(cmd, "STATUS")) { - do_status(); + do_status(NULL); upsdebug_call_finished0(); return 1; } diff --git a/docs/man/upsstats.html.txt b/docs/man/upsstats.html.txt index a4376fcac9..e41aa4a948 100644 --- a/docs/man/upsstats.html.txt +++ b/docs/man/upsstats.html.txt @@ -244,9 +244,14 @@ Insert the META header magic for refreshing the page if that variable has been set by the browser. This needs to be in the HEAD section of the page. +*@STATUS separator@*:: *@STATUS@*:: Expand the abbreviations in the ups.status variable -- OL becomes -"On line", OB becomes "On battery", and so on. +"On line", OB becomes "On battery", and so on. Reported values are +separated by the specified optional separator (`
` if not specified), +which starts at the next character after the "STATUS" (e.g. +a `@STATUS @` directive might be used to avoid any separation, or +`@STATUS @` to separate by spaces. *@STATUSCOLOR@*:: Insert red, green, or yellow color triplets depending on the severity of From f022e6d204f1374425d62c0cf9ed9f97e1a29509 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 12 Feb 2026 20:52:08 +0100 Subject: [PATCH 195/198] clients/upsstats.c: display_tree(): drop spurious
at end of table data cell [#3316] Signed-off-by: Jim Klimov --- clients/upsstats.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/upsstats.c b/clients/upsstats.c index c7b6dec330..04c74c70e5 100644 --- a/clients/upsstats.c +++ b/clients/upsstats.c @@ -1313,7 +1313,7 @@ static void display_tree(int verbose) printf("%s\n", answer[2]); printf(":\n"); - printf("%s
\n", answer[3]); + printf("%s\n", answer[3]); printf("\n"); } From 073ce37a3aa257e3a6fcdf6ba6ceb859e2c9816f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 12 Feb 2026 21:49:14 +0100 Subject: [PATCH 196/198] common/common.c, include/common.h, drivers/adelsystem_cbi.c, drivers/generic_modbus.c: generalize elapsed_since_timeval() [#1938] Closes: #1938 Co-authored-by: Dimitris Economou Signed-off-by: Jim Klimov --- NEWS.adoc | 2 ++ common/common.c | 25 +++++++++++++++++++++++++ drivers/adelsystem_cbi.c | 33 ++------------------------------- drivers/generic_modbus.c | 34 +++------------------------------- include/common.h | 3 +++ 5 files changed, 35 insertions(+), 62 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index 63622e4fe5..35ee829dbf 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -66,6 +66,8 @@ https://github.com/networkupstools/nut/milestone/12 reality agrees with a status reported by device/protocol (if any). This is also a step in direction of eventually providing a common `runtimecal` style fallback to all drivers. [issue #3146, PR #3156] + * Generalize `elapsed_since_timeval()` code, originally repeated in + several modbus drivers. [issue #1938, PR #3321] * Introduced `NOTIFY_STATE_EXTEND_TIMEOUT` option and relevant variables for `upsnotify()` method, so we can tell systemd to not kill the service unit if its shutdown takes long (see also the `SHUTDOWNEXIT` option in diff --git a/common/common.c b/common/common.c index 8ee5a679ba..aec564876c 100644 --- a/common/common.c +++ b/common/common.c @@ -2734,6 +2734,31 @@ double difftimespec(struct timespec x, struct timespec y) } #endif /* HAVE_CLOCK_GETTIME && HAVE_CLOCK_MONOTONIC */ +/* returns the time elapsed since start in milliseconds */ +long elapsed_since_timeval(struct timeval *start) +{ + long rval; + struct timeval end; + + rval = gettimeofday(&end, NULL); + if (rval < 0) { + upslog_with_errno(LOG_ERR, "elapsed_since_timeval"); + } + if (start->tv_usec < end.tv_usec) { + suseconds_t nsec = (end.tv_usec - start->tv_usec) / 1000000 + 1; + end.tv_usec -= 1000000 * nsec; + end.tv_sec += nsec; + } + if (start->tv_usec - end.tv_usec > 1000000) { + suseconds_t nsec = (start->tv_usec - end.tv_usec) / 1000000; + end.tv_usec += 1000000 * nsec; + end.tv_sec -= nsec; + } + rval = (end.tv_sec - start->tv_sec) * 1000 + (end.tv_usec - start->tv_usec) / 1000; + + return rval; +} + /* Help avoid cryptic "upsnotify: notify about state 4 with libsystemd:" * (with only numeric codes) below */ const char *str_upsnotify_state(upsnotify_state_t state) { diff --git a/drivers/adelsystem_cbi.c b/drivers/adelsystem_cbi.c index 3df478a90a..c1254e5858 100644 --- a/drivers/adelsystem_cbi.c +++ b/drivers/adelsystem_cbi.c @@ -34,7 +34,7 @@ #endif #define DRIVER_NAME "NUT ADELSYSTEM DC-UPS CB/CBI driver (libmodbus link type: " NUT_MODBUS_LINKTYPE_STR ")" -#define DRIVER_VERSION "0.07" +#define DRIVER_VERSION "0.08" /* variables */ static modbus_t *mbctx = NULL; /* modbus memory context */ @@ -83,10 +83,6 @@ int register_write(modbus_t *mb, int addr, regtype_t type, void *data); /* instant command triggered by upsd */ int upscmd(const char *cmdname, const char *extra); -/* count the time elapsed since start */ -long time_elapsed(struct timeval *start); - - /* driver description structure */ upsdrv_info_t upsdrv_info = { DRIVER_NAME, @@ -790,31 +786,6 @@ int register_write(modbus_t *mb, int addr, regtype_t type, void *data) return rval; } -/* returns the time elapsed since start in milliseconds */ -long time_elapsed(struct timeval *start) -{ - long rval; - struct timeval end; - - rval = gettimeofday(&end, NULL); - if (rval < 0) { - upslog_with_errno(LOG_ERR, "time_elapsed"); - } - if (start->tv_usec < end.tv_usec) { - suseconds_t nsec = (end.tv_usec - start->tv_usec) / 1000000 + 1; - end.tv_usec -= 1000000 * nsec; - end.tv_sec += nsec; - } - if (start->tv_usec - end.tv_usec > 1000000) { - suseconds_t nsec = (start->tv_usec - end.tv_usec) / 1000000; - end.tv_usec += 1000000 * nsec; - end.tv_sec -= nsec; - } - rval = (end.tv_sec - start->tv_sec) * 1000 + (end.tv_usec - start->tv_usec) / 1000; - - return rval; -} - /* instant command triggered by upsd */ int upscmd(const char *cmdname, const char *extra) { @@ -861,7 +832,7 @@ int upscmd(const char *cmdname, const char *extra) } /* wait for an increasing time interval before sending shutdown command */ - while ((etime = time_elapsed(&start)) < ( FSD_REPEAT_INTRV / cnt)); + while ((etime = elapsed_since_timeval(&start)) < ( FSD_REPEAT_INTRV / cnt)); upsdebugx(2, "ERROR: load.off failed, wait for %lims, retries left: %d", etime, cnt - 1); cnt--; } diff --git a/drivers/generic_modbus.c b/drivers/generic_modbus.c index 0c7877d39a..de3a791f4a 100644 --- a/drivers/generic_modbus.c +++ b/drivers/generic_modbus.c @@ -31,7 +31,7 @@ #endif #define DRIVER_NAME "NUT Generic Modbus driver (libmodbus link type: " NUT_MODBUS_LINKTYPE_STR ")" -#define DRIVER_VERSION "0.09" +#define DRIVER_VERSION "0.10" /* variables */ static modbus_t *mbctx = NULL; /* modbus memory context */ @@ -69,9 +69,6 @@ int upscmd(const char *cmd, const char *arg); /* read signal status */ int get_signal_state(devstate_t state); -/* count the time elapsed since start */ -long time_elapsed(struct timeval *start); - int register_write(modbus_t *mb, int addr, regtype_t type, void *data); /* driver description structure */ @@ -543,31 +540,6 @@ int register_write(modbus_t *mb, int addr, regtype_t type, void *data) return rval; } -/* returns the time elapsed since start in milliseconds */ -long time_elapsed(struct timeval *start) -{ - long rval; - struct timeval end; - - rval = gettimeofday(&end, NULL); - if (rval < 0) { - upslog_with_errno(LOG_ERR, "time_elapsed"); - } - if (start->tv_usec < end.tv_usec) { - suseconds_t nsec = (end.tv_usec - start->tv_usec) / 1000000 + 1; - end.tv_usec -= 1000000 * nsec; - end.tv_sec += nsec; - } - if (start->tv_usec - end.tv_usec > 1000000) { - suseconds_t nsec = (start->tv_usec - end.tv_usec) / 1000000; - end.tv_usec += 1000000 * nsec; - end.tv_sec -= nsec; - } - rval = (end.tv_sec - start->tv_sec) * 1000 + (end.tv_usec - start->tv_usec) / 1000; - - return rval; -} - /* instant command triggered by upsd */ int upscmd(const char *cmd, const char *arg) { @@ -611,7 +583,7 @@ int upscmd(const char *cmd, const char *arg) } /* wait for FSD_pulse_duration ms */ - while ((etime = time_elapsed(&start)) < FSD_pulse_duration); + while ((etime = elapsed_since_timeval(&start)) < FSD_pulse_duration); data = 0 ^ sigar[FSD_T].noro; rval = register_write(mbctx, sigar[FSD_T].addr, sigar[FSD_T].type, &data); @@ -654,7 +626,7 @@ int upscmd(const char *cmd, const char *arg) } /* wait for an increasing time interval before sending shutdown command */ - while ((etime = time_elapsed(&start)) < ( FSD_REPEAT_INTRV / cnt)); + while ((etime = elapsed_since_timeval(&start)) < ( FSD_REPEAT_INTRV / cnt)); upsdebugx(2,"ERROR: load.off failed, wait for %lims, retries left: %d\n", etime, cnt - 1); cnt--; } diff --git a/include/common.h b/include/common.h index 85bb4e8291..a83001b7e9 100644 --- a/include/common.h +++ b/include/common.h @@ -817,6 +817,9 @@ double difftimeval(struct timeval x, struct timeval y); double difftimespec(struct timespec x, struct timespec y); #endif +/* count the time elapsed since start in milliseconds */ +long elapsed_since_timeval(struct timeval *start); + #ifndef HAVE_USLEEP /* int __cdecl usleep(unsigned int useconds); */ /* Note: if we'd need to define an useconds_t for obscure systems, From 90ad1dce6e2c7eca79066bf719840d3238b335e5 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 13 Feb 2026 22:48:38 +0100 Subject: [PATCH 197/198] docs/man/nut.txt: old asciidoc variable "unset" only works with trailing exclamation mark Signed-off-by: Jim Klimov --- docs/man/nut.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/man/nut.txt b/docs/man/nut.txt index e420389382..fa6a5926c1 100644 --- a/docs/man/nut.txt +++ b/docs/man/nut.txt @@ -370,7 +370,7 @@ to secure access to those files and their copies as well. include::index.txt[] -:!included-skip-title: +:included-skip-title!: /////////////// :leveloffset: 0 From 65e838d2fbb703d413ebcafc7e0643a5b8d9f451 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 14 Feb 2026 09:48:47 +0100 Subject: [PATCH 198/198] docs/images/nut-squared.svg: add a margin-less version of NUT logo Signed-off-by: Jim Klimov --- docs/images/nut-squared.svg | 254 ++++++++++++++++++++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100644 docs/images/nut-squared.svg diff --git a/docs/images/nut-squared.svg b/docs/images/nut-squared.svg new file mode 100644 index 0000000000..84c1dcd2c9 --- /dev/null +++ b/docs/images/nut-squared.svg @@ -0,0 +1,254 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + +